这几天弄了个树莓派(Raspberry Pi)玩,装了个Linux。树莓派的GPIO其实非常容易调用,甚至可以直接通过Linux的sysfs来读写GPIO接口的状态,周末空闲的时候写了段bash Shell Script来控制LED灯来展示Linux的内存占用率。这只是个很简单的bash脚本,主要来示意一下如何通过Linux sysfs来调用GPIO来操作LED,通过修改脚本其实可以实现更多的功能,例如显示CPU的温度是否过高等。
我使用的硬件设备:
- Raspberry Pi
- LED x3 (不同颜色)
- 470Ω 电阻 x3 (用来为LED降压)
- 杜邦线 (母-公) x3 (用来连接树莓派的GPIO到面包板)
- 面包板 x1
第一步:用gpio命令验证物理连线
gpio命令是需要安装WiringPI之后才有的,默认系统不带。安装之后用root权限(sudo)执行 gpio readall,将得到类似下面的结果:
root@raspberrypi:~# gpio readall +----------+-Rev2-+------+--------+------+-------+ | wiringPi | GPIO | Phys | Name | Mode | Value | +----------+------+------+--------+------+-------+ | 0 | 17 | 11 | GPIO 0 | OUT | Low | | 1 | 18 | 12 | GPIO 1 | OUT | Low | | 2 | 27 | 13 | GPIO 2 | OUT | Low | | 3 | 22 | 15 | GPIO 3 | IN | Low | | 4 | 23 | 16 | GPIO 4 | IN | Low | | 5 | 24 | 18 | GPIO 5 | IN | Low | | 6 | 25 | 22 | GPIO 6 | IN | Low | | 7 | 4 | 7 | GPIO 7 | IN | Low | | 8 | 2 | 3 | SDA | IN | High | | 9 | 3 | 5 | SCL | IN | High | | 10 | 8 | 24 | CE0 | ALT0 | High | | 11 | 7 | 26 | CE1 | ALT0 | High | | 12 | 10 | 19 | MOSI | ALT0 | Low | | 13 | 9 | 21 | MISO | ALT0 | Low | | 14 | 11 | 23 | SCLK | ALT0 | Low | | 15 | 14 | 8 | TxD | ALT0 | High | | 16 | 15 | 10 | RxD | ALT0 | High | | 17 | 28 | 3 | GPIO 8 | ALT2 | Low | | 18 | 29 | 4 | GPIO 9 | ALT2 | Low | | 19 | 30 | 5 | GPIO10 | ALT2 | Low | | 20 | 31 | 6 | GPIO11 | ALT2 | Low | +----------+------+------+--------+------+-------+ root@raspberrypi:~#
Phy对应的是针脚的位置, GPIO对应的是GPIO的编号。需要注意两点:
- 实际执行这个命令后Raspberry Pi显示的GPIO编号很可能和我的不一样,要仔细看好然后再看看要用哪个编号。
- GPIO的编号和物理针脚不一定是顺序对应的,比如我这次要用的是针脚11, 12, 13,对应的GPIO编号是17, 18, 27。当然如果要用wiringPi的逻辑pin的话就是0, 1, 2,但是我这次不打算用wiringPi,只用sysfs来实现对LED的控制。
第二步:连接线路
注意:连线前断电,连好之后请再三确认之后再通电!
连接好线之后,请再次目视检查确认线没接错,特别是0v (GND)一定不要接错!再三确认之后再通电,进入Raspberry Pi的命令行界面测试接线是否正确。刚刚接好线的时候LED是不会像上图那样亮起来的,可以执行下面命令看看LED是否会亮(注意要有root权限):
root@raspberrypi:~# echo 17 >/sys/class/gpio/export root@raspberrypi:~# echo "out" > /sys/class/gpio/gpio17/direction root@raspberrypi:~# echo 1 >/sys/class/gpio/gpio17/value
修改GPIO的数字,依次测试。如果一切正常,那么三盏LED灯会依次亮起来,记住每个数字对应的LED的颜色。
第三步:编写脚本通过sysfs调用GPIO实现用LED灯展示内存占用率
我写的脚本如下,如果你愿意,你可以随意使用/修改后再使用/分发。
#!/bin/bash #A Sample script to check memory usage and reflect the result by LED. #Written by Kang Liu (http://www.liukang.com) #You have the freedom to use and/or modify the script, and the freedom to distribute modified and therefore derivative script. #gpio number for the LEDs orgled=27 greenled=18 redled=17 #precentage of available memory memfreehigh=60 memfreelow=30 #seconds to wait between each check waitperiod=10 #Init GPIO sysfs #Set default as "Off" for LEDs init_led() { for i in $orgled $greenled $redled do if [ ! -d /sys/class/gpio/gpio$i ] then echo $i >/sys/class/gpio/export fi echo "out" >/sys/class/gpio/gpio$i/direction echo 0 >/sys/class/gpio/gpio$i/value done } #Set LED value #Parameter is the GPIO number for the LED set_led() { led_status=`cat /sys/class/gpio/gpio$1/value` if [ "$led_status" -ne 1 ] then init_led echo 1 > /sys/class/gpio/gpio$1/value fi } #Turn off All LEDs before exit cleanup() { init_led for i in $orgled $greenled $redled do if [ -d /sys/class/gpio/gpio$i ] then echo $i > /sys/class/gpio/unexport fi done exit 0 } check_mem_usage() { output=`free |grep Mem|tr -s [:space:]` #uncomment the below lines if you want to debug #echo $output total=`echo $output | cut -d ' ' -f 2` used=`echo $output | cut -d ' ' -f 3` available=$((100-used*100/total)) #echo $available% available if [ $available -le $memfreelow ] then #echo "RED" set_led $redled return fi if [ $available -ge $memfreehigh ] then #echo "GREEN" set_led $greenled return fi #echo "ORANGE" set_led $orgled } init_led trap cleanup INT TERM EXIT while : do check_mem_usage sleep $waitperiod done
上面的脚本实现每10秒钟检查一次内存占用率(利用free命令),如果可用率高于60%,那么亮绿灯;如果可用率低于30%,则亮红灯。在30%到60%之间时亮橙色灯。在退出程序后,LED都会灭掉。
将上面脚本保存为.sh后缀,然后chmod +x赋予执行权限,再执行就可以了。
对上面的脚本稍加修改也可以实现用LED监控树莓派的CPU温度等等,这里就不一一列举代码了。用Shell获取树莓派的CPU/GPU温度可以参考这里:Raspberry Pi onboard temperature sensors。