コンテンツにスキップ

Raspberry Pi の GPIO

Raspberry Pi Documentation - Raspberry Pi OS

GPIO

pigpio

デーモンを自動起動させる

1
$ systemctl enable pigpiod

以下は GPIO17 から 100ms のパルスを 60 秒間出力するプログラムである。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import pigpio
import time

PORT_OUTPUT = 17

def main():
    pi = pigpio.pi()
    target = PORT_OUTPUT
    pi.set_mode(target, pigpio.OUTPUT)
    pulses = [
        pigpio.pulse(1 << target, 0, 1 * 100 * 1000),
        pigpio.pulse(0, 1 << target, 1 * 100 * 1000),
    ]

    pi.wave_clear()
    pi.wave_add_generic(pulses)
    wave_id = pi.wave_create()
    pi.wave_send_repeat(wave_id)
    start = time.time()
    while True:
        if time.time() - start >= 60:
          break
    pi.write(target, pigpio.LOW)
    pi.wave_tx_stop()
    pi.wave_clear()


if __name__ == "__main__":
    main()

設定は/lib/systemd/system/pigpiod.serviceにある。

パルス幅がなぜか 2 倍になるときは以下のように-t0 オプションを追加する。

/lib/systemd/system/pigpiod.service
1
2
3
4
5
6
7
8
[Unit]
Description=Daemon required to control GPIO pins via pigpio
[Service]
ExecStart=/usr/bin/pigpiod -l -t0
ExecStop=/bin/systemctl kill pigpiod
Type=forking
[Install]
WantedBy=multi-user.target

pigpiod - 雑記帳

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pigpio
import time

PORT_LED = 2


def main():
    pi = pigpio.pi()
    pi.set_mode(PORT_LED, pigpio.OUTPUT)

    while True:
        pi.write(PORT_LED, pigpio.HIGH)
        time.sleep(1)
        pi.write(PORT_LED, pigpio.LOW)
        time.sleep(1)


if __name__ == "__main__":
    main()

とりあえず 1ms 刻みのパルスは余裕らしい。

gpiod

Linux には標準で GPIO にアクセスできるlibgpiodというライブラリがであり、それを Python でバインディングできるようにしたのがgpiodである。

pigpioではデーモンの起動が必要(sudo pigpiod)だが、こちらは不要らしい。

1
$ pip install gpiod

GPIO へのアクセスはデバイスファイルを経由する。デバイスファイルは以下のコマンドで確認可能である。

1
2
3
4
$ ls -1 /dev/gpiochip*
/dev/gpiochip0
/dev/gpiochip1
/dev/gpiochip4

gpioinfoコマンドで使用可能なピンを確認できる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
$ gpioinfo
gpiochip0 - 58 lines:
        line   0:     "ID_SDA"       unused   input  active-high
        line   1:     "ID_SCL"       unused   input  active-high
        line   2:      "GPIO2"       unused   input  active-high
        line   3:      "GPIO3"       unused   input  active-high
        line   4:      "GPIO4"  "onewire@0"  output  active-high [used open-drain]
        line   5:      "GPIO5"       unused   input  active-high
        line   6:      "GPIO6"       unused   input  active-high
        line   7:      "GPIO7"   "spi0 CS1"  output   active-low [used]
        line   8:      "GPIO8"   "spi0 CS0"  output   active-low [used]
        line   9:      "GPIO9"       unused   input  active-high
        line  10:     "GPIO10"       unused   input  active-high
        line  11:     "GPIO11"       unused   input  active-high
        line  12:     "GPIO12"       unused   input  active-high
        line  13:     "GPIO13"       unused   input  active-high
        line  14:     "GPIO14"       unused   input  active-high
        line  15:     "GPIO15"       unused   input  active-high
        line  16:     "GPIO16"       unused   input  active-high
        line  17:     "GPIO17"       unused   input  active-high
        line  18:     "GPIO18"       unused   input  active-high
        line  19:     "GPIO19"       unused   input  active-high
        line  20:     "GPIO20"       unused   input  active-high
        line  21:     "GPIO21"       unused   input  active-high
        line  22:     "GPIO22"       unused   input  active-high
        line  23:     "GPIO23"       unused   input  active-high
        line  24:     "GPIO24"       unused   input  active-high
        line  25:     "GPIO25"       unused   input  active-high
        line  26:     "GPIO26"       unused   input  active-high
        line  27:     "GPIO27"       unused   input  active-high
        line  28: "RGMII_MDIO"       unused   input  active-high
        line  29:  "RGMIO_MDC"       unused   input  active-high
        line  30:       "CTS0"       unused   input  active-high
        line  31:       "RTS0"       unused   input  active-high
        line  32:       "TXD0"       unused   input  active-high
        line  33:       "RXD0"       unused   input  active-high
        line  34:    "SD1_CLK"       unused   input  active-high
        line  35:    "SD1_CMD"       unused   input  active-high
        line  36:  "SD1_DATA0"       unused   input  active-high
        line  37:  "SD1_DATA1"       unused   input  active-high
        line  38:  "SD1_DATA2"       unused   input  active-high
        line  39:  "SD1_DATA3"       unused   input  active-high
        line  40:  "PWM0_MISO"       unused   input  active-high
        line  41:  "PWM1_MOSI"       unused   input  active-high
        line  42: "STATUS_LED_G_CLK" "ACT" output active-high [used]
        line  43: "SPIFLASH_CE_N" unused input active-high
        line  44:       "SDA0"       unused   input  active-high
        line  45:       "SCL0"       unused   input  active-high
        line  46: "RGMII_RXCLK" unused input active-high
        line  47: "RGMII_RXCTL" unused input active-high
        line  48: "RGMII_RXD0"       unused   input  active-high
        line  49: "RGMII_RXD1"       unused   input  active-high
        line  50: "RGMII_RXD2"       unused   input  active-high
        line  51: "RGMII_RXD3"       unused   input  active-high
        line  52: "RGMII_TXCLK" unused input active-high
        line  53: "RGMII_TXCTL" unused input active-high
        line  54: "RGMII_TXD0"       unused   input  active-high
        line  55: "RGMII_TXD1"       unused   input  active-high
        line  56: "RGMII_TXD2"       unused   input  active-high
        line  57: "RGMII_TXD3"       unused   input  active-high

Raspberry Pi 4 では/dev/gpiochip0が相当するらしい。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import time

import gpiod
from gpiod.line import Direction, Value


def main() -> None:
    try:
        request = gpiod.request_lines("/dev/gpiochip0", config={
            17: gpiod.LineSettings(
                direction=Direction.OUTPUT, output_value=Value.ACTIVE
            )
        })
        while True:
            request.set_value(17, Value.ACTIVE)
            time.sleep(1)
            request.set_value(17, Value.INACTIVE)
            time.sleep(1)
    finally:
        request.release()


if __name__ == "__main__":
    main()