标签归档:bash script

对比用SHELL SCRIPT和C语言API操作RASPBERRY PI GPIO的速度

对Raspberry Pi的GPIO在shell script里面可以直接用sysfs的方式进行操作,也可以调用gpio命令来进行操作,还可以用API来进行操作。今天做了个实验对比sysfs方式、第三方gpio命令以及C语言API操作对效率的影响。

昨天写的文章里面提到了用GPIO来控制LED灯的显示,今天其实是突发奇想,想看看用第三方gpio命令来操作和直接操作sysfs的效率到底有多大的区别。

物理连线

连线和昨天写的文章里面的连线方法基本一样,只是在GPIO管脚和GND之间跨接了一个可以测频率的万用表(UNI-T UT136D)。

Shell Script 响应速度测试

测试脚本

#!/bin/bash
#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.
#Actually in this test, I will only use GPIO 17 (WiringIO 0) (Red LED)
orgled=27
greenled=18
redled=17
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
}

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
}
gpio_ben()
{
 echo 1 > /sys/class/gpio/gpio$1/value
 echo 0 > /sys/class/gpio/gpio$1/value
 #gpio write 0 1 #method 4
 #gpio write 0 0 #method 4
}

init_led
trap cleanup INT TERM EXIT
while :
do
 #gpio_ben 17 #method 2, method 4
 echo 1 > /sys/class/gpio/gpio17/value #method 1
 echo 0 > /sys/class/gpio/gpio17/value #method 1
 #gpio write 0 1 #method 3
 #gpio write 0 0 #method 3
done

方法1:直接调用sysfs控制通断

脚本中默认没有注释掉的就是方法1,相当于用下面命令来操作gpio实现让电路通断:

while :
do
 echo 1 > /sys/class/gpio/gpio17/value #method 1
 echo 0 > /sys/class/gpio/gpio17/value #method 1
done

实测频率在1.1kHz左右。目测LED基本感觉不到闪烁。

测试结果照片如下,最后两位数字在不断跳动。

万用表测试GPIO接口频率 (Shell Script)

方法2:用shell脚本中的函数调用sysfs控制通断

相当于用下面命令来通过自定义函数gpio_ben操作gpio,实现电路通断:

【BASH脚本】通过LINUX SYSFS调用GPIO实现LED显示RASPBERRY PI内存占用率

这几天弄了个树莓派(Raspberry Pi)玩,装了个Linux。树莓派的GPIO其实非常容易调用,甚至可以直接通过Linux的sysfs来读写GPIO接口的状态,周末空闲的时候写了段bash Shell Script来控制LED灯来展示Linux的内存占用率。这只是个很简单的bash脚本,主要来示意一下如何通过Linux sysfs来调用GPIO来操作LED,通过修改脚本其实可以实现更多的功能,例如显示CPU的温度是否过高等。

我使用的硬件设备:

  1. Raspberry Pi
  2. LED x3 (不同颜色)
  3. 470Ω 电阻 x3 (用来为LED降压)
  4. 杜邦线 (母-公) x3 (用来连接树莓派的GPIO到面包板)
  5. 面包板 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的编号。需要注意两点:

  1. 实际执行这个命令后Raspberry Pi显示的GPIO编号很可能和我的不一样,要仔细看好然后再看看要用哪个编号。
  2. GPIO的编号和物理针脚不一定是顺序对应的,比如我这次要用的是针脚11, 12, 13,对应的GPIO编号是17, 18, 27。当然如果要用wiringPi的逻辑pin的话就是0, 1, 2,但是我这次不打算用wiringPi,只用sysfs来实现对LED的控制。

第二步:连接线路

注意:连线前断电,连好之后请再三确认之后再通电!

raspberrypi-led-gpiov2
Raspberry Pi Control LED by using GPIO
gpio2_bb
GPIO LED 树莓派 面包板接线示意图

gpio_circuit_diagram-900x647
GPIO 连接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