Raspberry Piのメモ

シェルからGPIOを使う

GPIOのピン

Rev.2.0のもの。リビジョンにより多少違うらしいので要確認。 この写真は海外ショップで販売されているピン表示ガイド板。

http://siio.jp/gyazo/20140125180158.png http://siio.jp/gyazo/20140125175851.png

GPIOの使用例(入力編)

GPIOの7とGNDは隣り合っているので、ここにスイッチを付けてみる。こんなスイッチが使える。 (写真クリックでメーカーサイトへ)

http://www.ainex.jp/products/pa-045.htm

これを入力にしてプルアップにするにはシェルから次のように打ち込む。 (ピンを設定したり読んだりするためにはほかにもいろいろな方法がある)

echo 7 > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio7/direction 
echo "high" > /sys/class/gpio/gpio7/direction 

Raspberry PiのGPIOはプルアップ、プルダウンを指定出来る。"high"はプルアップ、"low"とするとプルダウン。指定しないとプルアップもダウンもされず高インピーダンス入力になる。スイッチを付ける場合は、外部抵抗でプルアップなどしないといけない。 設定で、プルアップ、プルダウンを指定すると、スイッチ接続が簡単になる。プルアップされているならそのピンに付けたスイッチをGNDに、プルダウンなら電源に接続するだけでok。普通は、引き回しが簡単なGNDに接続することになるので、ここはプルアップが便利(GPIO入力は3.3vが最大なのでうっかり5vに接続して破壊する可能性もあるのでGND接続が良い)。 今回も、スイッチをGNDに接続したので、常時はプルアップ(high)にしておき、スイッチが押されるとlowになるようにする。

cat /sys/class/gpio/gpio7/value

をすると、ボタンを押さなければ1が、ボタンを押せば0が返ってくる。(rootじゃなくても実行出来る)

echo 7 > /sys/class/gpio/unexport

exportメソッドでは、ピンを排他的に使用するらしい。 なので、exportしたままだと、次に別のプロセスからこれを利用できなかったり、警告が出たりする。 ということで利用終わったら上記のようにunexportするとよいらしい(効果は未確認)。

このボタンを5秒間押し続けたらRasberry Piをシャットダウンさせるスクリプトは次のように書ける。 ( http://blog.livedoor.jp/victory7com/archives/32699844.html を参考にしました。これによると このスクリプトを/etc/rc.localの最後にsu -c /home/pi/shutdown-daemon.sh & と書いておけばシャットダウンスイッチとして使える )

#!/bin/sh
GPIO=7     #使用するGPIOポート
PUSHTIME=5  #押す秒数

#初期設定
echo "$GPIO" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio$GPIO/direction
echo "high" > /sys/class/gpio/gpio$GPIO/direction

#5秒間押されるまで待つ
cnt=0
while [ $cnt -lt $PUSHTIME ] ; do
  data=`cat /sys/class/gpio/gpio$GPIO/value`
  if [ "$data" -eq "0" ] ; then
    cnt=`expr $cnt + 1`
  else
    cnt=0
  fi
  sleep 1
done

#このあとシャットダウンするから不要かもしれないけど一応お行儀良く
echo "$GPIO" > /sys/class/gpio/unexport
#シャットダウンの実行
shutdown -hP now

GPIOの使用例(出力編)

一方、ピンを出力にするにはシェルから次のように打ち込む。

echo 7 > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio7/direction 
echo 7 > /sys/class/gpio/unexport

GPIOピンの先に抵抗とLEDを直列につなぎ、先をGNDに落とせば、GPIOピンのH/LでLEDが点滅する。 抵抗は330オームくらいか1kオームくらい。LEDによっては330オームは結構眩しいかも。

echo 1 > /sys/class/gpio/gpio7/value

をするとLEDが点灯する。echo 0をすれば消灯する。

上記のシャットダウンボタンは、フィードバックがなくて動いているかどうか確認できない。 そこで、こんな

http://akizukidenshi.com/catalog/g/gP-04074/ http://siio.jp/gyazo/20140730132620.png

LED内蔵押しボタンスイッチ(写真クリックで秋月電子へ)を買ってきて、シャットダウンカウントダウンに点滅するようにしてみる。 これはスイッチとLEDのために4本の端子が付いている。 これをRaspberryのピンに刺すコネクタを作成する。

http://siio.jp/gyazo/20140201171247.png

これを、GPIO 7→スイッチ→GNDと、また、GPIO 8→抵抗→LED→GNDのように接続する。 以下のようなスクリプトを常駐させておけば、シャットダウンできる。

#!/bin/sh
BTN=7    #使用するGPIOポート
LED=8
PUSHTIME=5  #押す秒数

#初期設定
echo "$BTN" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio$BTN/direction
echo "high" > /sys/class/gpio/gpio$BTN/direction
echo "$LED" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio$LED/direction

#5秒間押されるまで待つ
cnt=0
while [ $cnt -lt $PUSHTIME ] ; do
  data=`cat /sys/class/gpio/gpio$BTN/value`
  if [ "$data" -eq "0" ] ; then
    cnt=`expr $cnt + 1`
	echo 1 > /sys/class/gpio/gpio$LED/value
	sleep 0.5
	echo 0 > /sys/class/gpio/gpio$LED/value
	sleep 0.5	
  else
	cnt=0
	sleep 1
  fi
done
 
#このあとシャットダウンするから不要かもしれないけど一応お行儀良く
echo "$BTN" > /sys/class/gpio/unexport
echo "$LED" > /sys/class/gpio/unexport
#シャットダウンの実行
shutdown -hP now

PythonからGPIOを使う

上記の方法は、たぶん仮想ファイル経由でデバイスドライバにアクセスしているようなもので、これを使えば、cだろうとjavaだろうとpythonだろうと、シェルコマンド呼ぶ関数で利用できてお手軽。でも、echo とcatコマンドで頑張らないといけないので、プログラミングには面倒だし凝った事ができない。

CやPythonなどのために、GPIOを呼ぶライブラリーも提供されている。 以下は、GPIO 8に抵抗とLEDを取り付け、これを点滅させる例。 最終的にGPIO.cleanupを呼びたいので、コントロールC押下あとで処理出来るようにtry文を使用している。

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
LED=8
GPIO.setmode(GPIO.BCM)
GPIO.setup(LED, GPIO.OUT)
print("Type control-c to stop.\n");
try:
        while True:
                GPIO.output(LED,1)
                time.sleep(1)
                GPIO.output(LED,0)
                time.sleep(1)
except KeyboardInterrupt:
        GPIO.cleanup()

実は、出力に設定したGPIOピンても、その値を読む事ができる。これを利用すれば、上記の無限ループ部分は、

        while True:
                GPIO.output(LED,(1-GPIO.input(LED)))
                time.sleep(1)

と簡素化できる。( 1-1=0, 1-0=1を使って1,0を反転させる手法)

以下は、GPIO 7とGNDに取り付けた押しボタンスイッチの状態を読む例。 GPIO.setupのpull_up_down引数でプルアップ/ダウンを指定出来る。

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
Switch=7 
GPIO.setmode(GPIO.BCM)
GPIO.setup(Switch, GPIO.IN, pull_up_down=GPIO.PUD_UP)
print("Type control-c to stop.\n");
try:
        while True:
                print(GPIO.input(Switch))
                time.sleep(1)
except KeyboardInterrupt:
        GPIO.cleanup()

Callbackを使う

callback関数を設定しておく事で割り込み処理が可能である。 スイッチの状態などをポーリングして監視し続けなくても良いので、プログラミングが楽になる。 GPIO.FALLING, GPIO.RISING, GPIO.BOTHの指定で、1-->0, 0-->1, その両方のイベントでのコールバックを指定する。

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
Switch=7 

def switch_callback(gpio_pin):
	print(gpio_pin)

GPIO.setmode(GPIO.BCM)
GPIO.setup(Switch, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(Switch, GPIO.FALLING)
GPIO.add_event_callback(Switch, switch_callback)
print("Type control-c to stop.\n");
try:
	while True:
		time.sleep(1)
except KeyboardInterrupt:
	GPIO.cleanup()

上で示した機械的なスイッチを取り付けただけだとチャッタリングのために指定したイベント以外の変化でも呼び出されることがある。上記のプログラムで以下のような対策をとれば多少は緩和される筈。 このcallback関数では、イベントにより呼びだされた後、チャッタリングが収まるまで30ms待って、もう一度チェックして間違って呼ばれたようならなにもしないで終了する。

def switch_callback(gpio_pin):
	time.sleep(0.03)
	if GPIO.input(gpio_pin) != 0:
		return
	print(gpio_pin)

トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS