GPIO output value not changing - linux

I am trying to setup up a output GPIO pin on my Nitrogen6X board, but I can't change the file value. I navigated to /sys/class/gpio/ and I exported my pin (GPIO18) with echo 18 > export. I was then able to change direction with the command echo out > direction and it seems like I should be able to change the value file the same way, with echo 1 > value, but this doesn't seem to be working. I am logged in as root and the permissions on both the direction file and the value file are the same: -rw-r--r-- 1 root root.
Does anyone have an idea why this would not be writing to this file?
Thanks so much for all of your help!

The commands that you have listed should work, if the gpio number is correct. While I have not worked with Nitrogen6X in particular, I have found out that Linux GPIO pin numbers often do not match the labels on the board. I advice trying to find out the proper mapping experimentally by watching all possible GPIOs:
cd /sys/class/gpio
for x in `seq 1 128`; do echo $x > export; done
ground the pin in question via 10k resistor, run:
grep . gpio*/value > /tmp/values0
connect the pin in question to Vcc via 10k resistor, run:
grep . gpio*/value > /tmp/values1
diff the files, and pay attention which pin has changed.

Related

Recursively grep string in a certain variable directory structure

I have a directory structure on a shared Windows network like this:
\\\server\share\directory\anotherDirectory\[variable serial number]\config\
where the variable is a 4 digit integer. And there are hundreds of the [variable serial number] directories I have to go through recursively.
The drive share is mapped in Linux so it sees the Windows share and can traverse it.
Once inside the [variable serial number]\config\ directory, I need to grep in a .csv file that's named:
[variable serial number]_config_v1.csv
so the full path for an individual serial number file might look like this:
\\server\share\directory\anotherDirectory\1234\config\1234_config_v1.csv
There are hundreds of serial number directories I have to search through. I've tried adapting the answer from this SO question with no luck so far.
If it makes any difference, I'm doing this over VPN using Win10's Windows Subsystem for Linux with an Ubuntu distro.
Can I do something along the lines of:
for i in [list of serial numbers]
do
grep -in "string" $i_config_v1.csv >> log.txt
done
?? I'm not sure where to work the leading path in, or I could run the script from the root of where the serial numbered directories start?
You need to put i inside {} to delimit it from _config_v1.csv. Otherwise it will try to read the variable named i_config_v1.
for i in $list_of_serial_numbers
do
grep -in "string" "/path/to/share/$i/config/${i}_config_v1.csv"
done

Update Bash commands every 2 seconds (without re-running code everytime)

for my first bash project I am developing a simple bash script that shows basic information about my system:
#!/bash/sh
UPTIME=$(w)
MHZ=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq)
TEMP=$(cat /sys/class/thermal/thermal_zone0/temp)
#UPTIME shows the uptime of the device
#MHZ shows the overclocked specs
#TEMP shows the current CPU Temperature
echo "$UPTIME" #displays uptime
echo "$MHZ" #displays overclocked specs
echo "$TEMP" #displays CPU Temperature
MY QUESTION: How can I code this so that the uptime and CPU temperature refresh every 2seconds without re-generating the code new every time (I just want these two variables to update without having to enter the file path again and re-running the whole script).
This code is already working fine on my system but after it executes in the command line, the information isn't updating because it executed the command and is standing by for the next command instead of updating the variables such as UPTIME in real time.
I hope someone understands what I am trying to achieve, sorry about my bad wordings of this idea.
Thank you in advance...
I think it will help you. You can use the watch command for updating that for every two seconds without the loop.
watch ./filename.sh
It will give you the update of that command for every two second.
watch - execute a program periodically, showing output fullscreen
Not sure to really understand the main goal, but here's an answer to the basic question "How can I code this so that the uptime and CPU temperature refresh every two seconds ?" :
#!/bash/sh
while :; do
UPTIME=$(w)
MHZ=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq)
TEMP=$(cat /sys/class/thermal/thermal_zone0/temp)
#UPTIME shows the uptime of the device
#MHZ shows the overclocked specs
#TEMP shows the current CPU Temperature
echo "$UPTIME" #displays uptime
echo "$MHZ" #displays overclocked specs
echo "$TEMP" #displays CPU Temperature
sleep 2
done
I may suggest some modifications.
For such simple job I may recommend no to use external utilities. So instead of $(cat file) you could use $(<file). This is a cheaper method as bash does not have to launch cat.
On the other hand if reading those devices returns only one line, you can use the bash built-in read like: read ENV_VAR <single_line_file. It is even cheaper. If there are more lines and for example you want to read the 2nd line, you could use sg like this: { read line_1; read line2;} <file.
As I see w provides much more information and as I assume you need only the header line. This is exactly what uptime prints. The external utility uptime reads the /proc/uptime pseudo file. So to avoid to call externals, you can read this pseudo file directly.
The looping part also uses the external sleep(1) utility. For this the timeout feature of the read internal could be used.
So in short the script would look like this:
while :; do
# /proc/uptime has two fields, uptime and idle time
read UPTIME IDLE </proc/uptime
# Not having these pseudo files on my system, the whole line is read
# Maybe some formatting is needed. For MHZ /proc/cpuinfo may be used
read MHZ </sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
read TEMP </sys/class/thermal/thermal_zone0/temp
# Bash supports only integer arithmetic, so chomp off float
UPTIME_SEC=${UPTIME%.*}
UPTIME_HOURS=$((UPTIME_SEC/3600))
echo "Uptime: $UPTIME_HOURS hours"
echo $MHZ
echo $TEMP
# It reads stdin, so pressing an ENTER it returns immediately
read -t 2
done
This does not call any external utility and does not make any fork. So instead of executing 3 external utilities (using the expensive fork and execve system calls) in every 2 seconds this executes none. Much less system resources are used.
you could use while [ : ] and sleep 2
You need the awesome power of loops! Something like this should be a good starting point:
while true ; do
echo 'Uptime:'
w 2>&1 | sed 's/^/ /'
echo 'Clocking:'
sed 's/^/ /' /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
echo 'Temperature:'
sed 's/^/ /' /sys/class/thermal/thermal_zone0/temp
echo '=========='
sleep 2
done
That should give you your three sections, with the data of each nicely indented.

Take parts of the standard output value and put it into a array variable

I'm currently working on a script (using BASH) which backups VM file to a remote server.
I want to try and make the script a bit more dynamic by being able to just looping though each VM from a "show VM command". my idea is to take the standard output of a command which show all the VM and break up and turn it to useful variables. possibly a multi-array.
the Output comes out like this is there anyway to break it all up? say by spaces and line breaks?
Vmid Name File Guest OS Version Annotation
10 FREEPBX [datastore2] FREEPBX/FREEPBX.vmx other26xLinux64Guest vmx-08
13 AdaptivNICE2Cloud [datastore2] AdaptivNICE2Cloud/AdaptivNICE2Cloud.vmx other26xLinux64Guest vmx-08
15 IVSTelManager [datastore2] IVSTelManager/IVSTelManager.vmx debian6Guest vmx-08
4 Neptune [datastore1] Neptune/Neptune.vmx winNetEnterprise64Guest vmx-08
9 Kayako [datastore2] Kayako/Kayako.vmx other26xLinux64Guest vmx-08
I guess you need this:
$ vim-cmd vmsvc/getallvms | sed -n 's|.*\[|/vmfs/volumes/|;s|\] *|/|;s|\.vmx .*|.vmx|p'
/vmfs/volumes/datastore2/FREEPBX/FREEPBX.vmx
/vmfs/volumes/datastore2/AdaptivNICE2Cloud/AdaptivNICE2Cloud.vmx
/vmfs/volumes/datastore2/IVSTelManager/IVSTelManager.vmx
/vmfs/volumes/datastore1/Neptune/Neptune.vmx
/vmfs/volumes/datastore2/Kayako/Kayako.vmx
# Prints all VMX files paths
OR
$ vim-cmd vmsvc/getallvms | sed -n 's|.*\[|/vmfs/volumes/|;s|\] *|/|;s|/[^/]*\.vmx .*||p'
/vmfs/volumes/datastore2/FREEPBX
/vmfs/volumes/datastore2/AdaptivNICE2Cloud
/vmfs/volumes/datastore2/IVSTelManager
/vmfs/volumes/datastore1/Neptune
/vmfs/volumes/datastore2/Kayako
# Prints all directories having VMX files. These directories also contain the virtual HDDs, which you would want to backup.
(Ignore the $ in the prompt; it is still root prompt. SO would interpret it as comment if I use # in place if $..)

Beaglebone Linux: issues appending a line to a file

I am working to enable spi on my beaglebone black (Angstrom distribution), using instructions here.
I am at the point where i need to add BB-SPI1-01 to /sys/devices/bone_capemgr.*/slots to enable the drivers.
issuing the command echo BB-SPI1-01 > /sys/devices/bone_capemgr.*/slots or echo BB-SPI1-01 >> /sys/devices/bone_capemgr.*/slots, however, yields the error echo: Write error: file exists
Trying to edit in the line with nano also fails. I'm able to open the file and edit it, but when I save it gives me Error writing slots: no such file or directory
I've set permissions on the file to 777.
Does anybody know why I cannot edit the file? if it's not possible, is there a workaround?
I, too have battled with this dilemma while trying to port ILI9340C display stuff to Beaglebone Black. The way /dev/devices/bone_capemgr.* works is that anything which you echo to its slots directory it goes and searches for a Device Tree overlay for that device, a new thing in Linux Kernel 3.0 and higher. For anyone who does not know (it took me forever to find this) Device Trees are basically a driver that tells Linux how to deal with a device, but instead of containing any code, they are simply a configuration file, per-se, that tells Linux what to put where in order to talk to a device, and what to expect in return. That being said, BB-SPIx-01 is a compiled Device Tree file, a .dts in /lib/firmware/ which points to the SPI device, and tells spidev what to do with it.
BB-SPI1-01 happens to be connected to the HDMI port already for some audio thing (I think) and, therefore, unless you disable HDMI entirely, SPI1 is always tied up by the HDMI framer. This explains why writing BB-SPI1-01 to /sys/devices/bone_capemgr.*/slots fails. This is a special file, and when you write to it, a kernel process reads your input and proceeds to attempt to make a 'device' file elsewhere, and since BB-SPI1-01 is already enabled, that file already exists, and so the kernel process that handles those things returns an error and pipes it through whatever process initiated it, in this case, you, the user, typing echo BB-SPI1-01 > /sys/devices/bone_capemgr.*/slots.
On the bright side, SPI0 is left unused. Therefore, in order to use it, all you have to do is enable it in userland. To do that, (and you have figured this out already, but for everyone else) type echo BB-SPI0-01 > /sys/devices/bone_capemgr.*/slots at the command line, and then just to be sure that spidev is running, type modprobe spidev as root. Now, to verify, type ls /dev | grep spi and see what comes up. /dev/spidevX.Y is your SPI bus, for me that would be /dev/spidev1.0.
I'm sorry that was really long winded, but I'm culminating my research thus far into one spot in the hopes that it will help someone.
If you have any questions, please feel free to ask!
For those who are curious, while I haven't found the exact answer, I did find some more information.
The SPI1 interface on the beaglebone black can't be enabled unless the hdmi interface has been turned off, which I have not done. I'm instead using the SPI0 interface now. Interestingly, that same command works if BB-SPI0-01 is used instead of BB-SPI1-01. Therefore the error in question is probably not coming from the base command, but rather the system in response to the command (which can't allocate the resources requested due to conflicts with hdmi).
While I haven't tested SPI1 with hdmi turned off, I can only assume that my errors would go away.
Might it be because you're trying to access more than one file at a time with echo BB-SPI1-01 > /sys/devices/bone_capemgr.*/slots ?
Try selecting single path to the slots file and see if that works
Based on PyroAVR's answer, here is the concrete solution. You need to disable HDMI, that's easily done by editing the following file: /boot/uEnv.txt
You can uncomment the line which causes HDMI to be disabled by running the following command as root:
sed -i.bck '/cape_disable=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN$/ s/^#//' /boot/uEnv.txt
as Mixaz mentioned in a comment, the real errors are found in the dmesg output; "no such file or directory" is a red herring, and even strace doesn't give any clues as to the real problem. in my case I found:
[26858.517893] bone_capemgr bone_capemgr: slot #5: override
[26858.517937] bone_capemgr bone_capemgr: Using override eeprom data at slot 5
[26858.517986] bone_capemgr bone_capemgr: slot #5: 'Override Board Name,00A0,Override Manuf,jc_gpio_test'
[26924.230357] bone_capemgr bone_capemgr: part_number 'jc_gpio_test', version 'N/A'
from that I guessed that it didn't like "0000" as a version number, changed to "00A0" and recompiled, then it worked.
here's the Makefile I wrote to help automate the process, in case it helps.
%.install: %-00A0.dtbo
cp -f $< /lib/firmware
echo $* > /sys/devices/platform/bone_capemgr/slots
%-00A0.dtbo: %.dts
dtc -O dtb -o $# -b 0 -# $<
use it as: make jc_gpio_test.install, assuming your .dts file name is jc_gpio_test.dts.
it turns out, my guess was probably wrong. the change that more likely fixed it was adding the -00A0 part to the dtbo file. apparently the "dash-versionnumber" is required by the slot loader.

Does anybody know of a USB Postage Scale that's Linux compatible?

I'm looking for a postage scale that already has linux support (drivers, etc) for a shipping system that I'm working on. I'm planning to use Ubuntu 9.04, but I am willing to switch distro's for compatibility.
Does anybody know of any scales that currently work? Is there an open source project that's working on scale drivers or similar?
Thanks!
I use the 5lb stamps.com scale. You can pick it up for $10 if you sign up for an account with them and then cancel it.
To read from it in linux, get this script: http://gist.github.com/503896
Edit the script file to set the proper hidraw device path. You can find the path by running dmesg after you've plugged the scale in. You will see something like "/dev/hidraw2".
After setting the hidraw path in the script, add execute permission and then run it as root:
chmod +x usbscale.pl
sudo ./usbscale.pl
Place an object on the scale and it will print the weight.
Update:
I've created a newer version of my earlier script that mattismyname linked. It's written in C, and you can find it at https://github.com/erjiang/usbscale
To use it, just download the source code and run (inside its directory):
sudo aptitude install libusb-1.0-0-dev
make
./usbscale
You might need to copy the 50-usb-scales.rules to your /etc/udev/rules.d (or run as root, haha) if you run into a permissions error.
Exponent value is passed as signed integer, and weight is passed in little endian byte order. Other answers do not properly account for these factors. See a more comprehensive example here.
<?php
$binary = fread(fopen('/dev/hidraw3', 'r'), 7);
$data = (object) unpack('Creport/Cstatus/Cunit/cexponent/vweight', $binary);
if ($data->report == 0x03 && $data->status == 0x04) {
$data->weight = $data->weight * pow(10, $data->exponent);
if ($data->unit == 0x0B) {
// convert ounces to grams
$data->weight *= 28.349523125;
// and unit to grams
$data->unit = 0x02;
}
if ($data->unit == 0x02) {
echo "{$data->weight} g\n";
} else {
echo "{$data->weight} in other unit\n";
}
}

Resources