Seeed K.K.の松岡です。
Raspberry PiでGPIOやI2Cなどハードウェア制御するときにはpigpioを使っています。pigpioは、わたしがよく使うインターフェイス(GPIO, PWM, I2C, SPI, UART)の全てに対応しています。長いこと使っていますが困ったことは(1回を除いて)ありません。完全に頼り切っています。
しかしながら、新しいラズパイ、Raspberry Pi 5ではpigpioが使えません😢。ハードウェアが大きく変わっているので使えるようにするには大変ですわね...
そんなわけで、Raspberry Pi 5でGPIO, PWM, I2C, SPI, UARTするPythonコードを調べてまとめました。
デジタル入力
import gpiozero import time pin = gpiozero.DigitalInputDevice(pin=27, pull_up=True) try: while True: print(pin.value) time.sleep(1) finally: pin.close()
- Raspberry Pi公式のドキュメントがgpiozeroだったので、gpiozeroで。
- Raspberry Pi OSに標準でインストールされていました。
- InputDeviceとDigitalInputDeviceのどちらを使うか迷うところ。下記デジタル出力と同じ階層のDigitalInputDeviceに。
- pull_up=Trueするとactive_state=Falseになる。
- お試し回路は、GPIO17にタクトスイッチを接続して、スイッチを押すとGNDに繋がるように。
デジタル出力
import gpiozero import time pin = gpiozero.DigitalOutputDevice(pin=17) try: while True: pin.on() time.sleep(0.2) pin.off() time.sleep(0.8) finally: pin.close()
- Raspberry Pi公式のドキュメントがgpiozeroだったので、gpiozeroで。
- Raspberry Pi OSに標準でインストールされていました。
- OutputDeviceとDigitalOutputDeviceのどちらを使うか迷うところ。PWM出力と同じ階層のほうが使い分けが分かりやすいと思うのでDigitalOutputDeviceに。
- お試し回路は、GPIO17にLEDと抵抗を接続して、GPIO27をHIGH出力するとLEDが点灯するように。
PWM出力
import gpiozero import time pin = gpiozero.PWMOutputDevice(pin=17, frequency=1000) try: while True: values = [0.0, 0.1, 0.5, 1.0, 0.5, 0.1] for value in values: pin.value = value time.sleep(1) finally: pin.close()
- Raspberry Pi公式のドキュメントがgpiozeroだったので、gpiozeroで。
- Raspberry Pi OSに標準でインストールされていました。
- お試し回路は、上記のデジタル出力と同じです。GPIO17にLEDと抵抗を接続して、GPIO27をHIGH出力するとLEDが点灯するように。
I2C
import smbus2 import time bus = smbus2.SMBus(1) try: # Set configuration write = smbus2.i2c_msg.write(0x48, [0x03, 0x80]) bus.i2c_rdwr(write) while True: # Read temperature value write = smbus2.i2c_msg.write(0x48, [0x00]) read = smbus2.i2c_msg.read(0x48, 2) bus.i2c_rdwr(write, read) print((read.buf[0][0] * 256 + read.buf[1][0]) / 128) time.sleep(1) finally: bus.close()
- smbusかsmbus2。smbus2はRaspberry Pi OSに標準でインストールされているので、smbus2で。
- 事前にI2C有効化を忘れずに。
- i2c_rdwrが使いやすい。書き込みメッセージと読み込みメッセージを同時に指定すると、リピートスタートコンディションで通信する👍。
- 読み込んだデータはbufで参照できる。1バイトずつのbytesの配列(!)なので、1バイト目はbuf[0][0]、2バイト目はbuf[1][0]。(もっとスマートな取り方、無いかなぁ。)
- お試し回路は、GPIO2(SDA)とGPIO3(SCL)に温度センサーADT7410を接続して、I2Cで温度を測定できるように。
Raspberry Pi 4で問題のあるクロックストレッチの振る舞いをRaspberry Pi 5で確認しましたが、きちんと動作していました👍👍。(SHT31使用)
import smbus2 # I2C import time # I2C - SHT31 # https://github.com/kplindegaard/smbus2 import smbus2 import time bus = smbus2.SMBus(1) try: write = smbus2.i2c_msg.write(0x45, [0x2C, 0x10]) read = smbus2.i2c_msg.read(0x45, 6) bus.i2c_rdwr(write, read) finally: bus.close()
SPI
import spidev import time bus = spidev.SpiDev() try: bus.open(0, 0) bus.mode = 0 bus.max_speed_hz = 1_000_000 while True: read = bus.xfer([0b0110_1000, 0]) print(read[0] * 256 + read[1]) time.sleep(1) finally: bus.close()
- Spidevで。
- Raspberry Pi OSに標準でインストールされていました。
- 事前にSPI有効化を忘れずに。
- お試し回路は、GPIO8(CE0)とGPIO9(MISO)、GPIO10(MOSI)、GPIO11(SCLK)にADコンバーターMCP3002を接続して、SPIで電圧を測定できるように。
UART
import serial import time uart = serial.Serial('/dev/ttyAMA0', 9600, timeout=0.5) try: while True: uart.write(b'\x22\x00\x00\x22') read = uart.read(4) distance = int.from_bytes(read[1:3], byteorder='big') print(distance) time.sleep(1) finally: uart.close()
- pySerialで。
- Raspberry Pi OSに標準でインストールされていました。
- あいかわらずややこしいUARTコンフィグレーション。
sudo raspi-config
で3 -> I5 -> No -> Yesを選択すればOK。 - お試し回路は、GPIO14(TXD)とGPIO15(RXD)に超音波センサーURM37を接続して、UARTで距離を測定できるように。
参考リンク
- GPIO and the 40-pin header - Raspberry Pi
- GPIO in Python - Raspberry Pi
- Enable/disable I2C interfaces - Raspberry Pi
- Enable/Disable SPI interfaces - Raspberry Pi
- Configuring UARTs - Raspberry Pi
- gpiozero package documentation
- smbus2 package
- Python Spidev package
- pySerial package
- Raspberry Pi I2C clock-stretching bug
- ラズパイ自由自在 電子工作 パーツ制御完全攻略
変更履歴
日付 | 変更者 | 変更内容 |
---|---|---|
2024/4/20 | 松岡 | 作成 |