2013年8月16日金曜日

Raspberry Pi RPIO

ここではパラレル入出力で LED ピカピカをやってみます。

Raspberry Pi で、GPIO を使おうとすると結構大変です。
何が大変かというと、ライブラリがいくつかあったり、ポートの番号の表現がいろいろあるからです。
古い Raspberry Pi と、新しいものとで少し違ったり、使うライブラリによって番号の割り振りが異なることがあります。

RPIOは root 権限が必要なので、Python を root で起動します。
$ sudo python

手始めに、インタプリタから直接いろいろやってみます。
最初にライブラリ(python-rpi.gpio)をインポートします。このライブラリははじめから入っているので、インストールする必要はありません。
>>> import RPi.GPIO as GPIO

ここで使っているピンは、GPIO09と GPIO10 です。ピン番号で言うと GPIO09 が 21 番ピン、GPIO10 は 19 番ピンになります。
回路図はこうです。


GPIO09 を出力にセットして、最初は0、次に1を出力してみます。
>>> GPIO.setup(9, GPIO.OUT)
>>> GPIO.output(9, 1)
>>> GPIO.output(9, 0)

今度は入力です。となりの GPIO10 をプルアップ抵抗付きの入力端子にします。
そして、ポートの状態を読み込みます。
>>> GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_UP)
>>> GPIO.input(10)
False
>>> GPIO.input(10)
True

最後は・・・
GPIO.cleanup()

まとめて、Python のプログラムにするとこんな感じ。
GPIO10 が0になるまで GPIO09 を0にしたり1にしたりを繰り返します。
#!/usr/bin/env python
# coding: UTF-8

# import RPIO as GPIO
import RPi.GPIO as GPIO
import time

pin_out = 9
pin_in = 10
sleep_sec = 0.5

GPIO.setmode(GPIO.BCM)
GPIO.setup(pin_out, GPIO.OUT)
GPIO.setup(pin_in, GPIO.IN, pull_up_down=GPIO.PUD_UP)
out_value = False
loop = True
while (loop):
    GPIO.output(pin_out, out_value)
    out_value = not out_value
    loop = GPIO.input(pin_in)
    time.sleep(sleep_sec)
GPIO.cleanup()

class にしたバージョンはこれ。
#!/usr/bin/env python
# coding: UTF-8
# http://pythonhosted.org/RPIO/rpio_py.html#ref-rpio-py-rpigpio

# import RPIO as GPIO
import RPi.GPIO as GPIO
import time

class test_gpio():
    
    def __init__(self):
        self.pin_out = 9
        self.pin_in = 10
        self.sleep_sec = 0.5
        self.loop = True
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.pin_out, GPIO.OUT)
        GPIO.setup(self.pin_in, GPIO.IN, pull_up_down=GPIO.PUD_UP)

    def main(self):
        out_value = False
        while (self.loop):
            GPIO.output(self.pin_out, out_value)
            out_value = not out_value
            self.loop = GPIO.input(self.pin_in)
            time.sleep(self.sleep_sec)
        GPIO.cleanup()
    

if __name__ == '__main__':
    test = test_gpio()
    test.main()

こんどは割り込みを使います。
このプログラムでは sleep でお休みしていますが、普通のプログラムではいろいろなことをやっているときにイベントが発生すれば、その処理をひとまず中断して、そのイベントに対応した処理を実行します。
主たる処理は中断を気にしないで処理を続けることができます。
割り込み処理は RPIO をインポートします。
インストールしてない場合は、先にインストールしておいてください。
#!/usr/bin/env python
# coding: UTF-8
# http://pythonhosted.org/RPIO/rpio_py.html#ref-rpio-py-rpigpio

import RPIO as GPIO
# import RPi.GPIO as GPIO
import time

class test_gpio():
    
    def __init__(self):
        self.pin_out = 9
        self.pin_in = 10
        self.sleep_sec = 0.5
        self.loop = True
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.pin_out, GPIO.OUT)
        GPIO.setup(self.pin_in, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.add_interrupt_callback(self.pin_in,
                                    self.call_back,
                                    edge='falling',     # rising, falling or both
                                    pull_up_down=GPIO.PUD_UP,
                                    threaded_callback=True,
                                    debounce_timeout_ms=100)
        GPIO.wait_for_interrupts(threaded=True)

    def call_back(self, gpio_id, val):
        print("gpio %s: %s" % (gpio_id, val))
        if gpio_id == self.pin_in:
            self.loop = False
        
    def main(self):
        out_value = False
        while (self.loop):
            GPIO.output(self.pin_out, out_value)
            out_value = not out_value
            time.sleep(self.sleep_sec)
        GPIO.cleanup()
    

if __name__ == '__main__':
    test = test_gpio()
    test.main()