ROS2以前の問題で、ラズパイ5で、GPIOをアクセスする方法を探ります。
なぜって、一つは、Linux自体の変化で、
$ echo 21 > /sys/class/gpio/export
のような、sysfsを経由したGPIO操作がなくなるのです。
もひとつの理由は、ラズパイ5で、ラズパイ4までと比べてそうとうハードが変更されて、従来のGPIOを操作するライブラリが使えなくなったことです。
環境
- Raspberry Pi 5 8GB
- 追加ボード;NVMe Base for Raspberry Pi 5 (NVMe Base by Pimoroni)
- Crucial クルーシャル P2シリーズ 500GB 3D NAND NVMe PCIe M.2 SSD CT500P2SSD8
- 初期;RaspberryPi OS Desktop 64bit (Debian version: 12 (bookworm) Release date: March 15th 2024)
- 現在;Ubuntu Desktop 24.04LTS(64-bit)
- ROS2;Jazzy
gpiodが残りそう
マニュアルです。libgpiodのgpiodです??? GPIOをアクセスするライブラリlibgpiodを使うコマンドの総称がgpiodです。
ラズパイ5で、GPIO用コマンド、Cライブラリ、Pythonライブラリのいずれにもに対応しているのがlibgpiodだけらしく、使わざるを得ません。コマンドだけならばpinctrlが対応しているようです。Pythonのライブラリはgpiozeroが対応しているのですが、単にGPIOを操作するには使いにくいです。
ラズパイ5では/dev/gpiochip4を使うようです。
コマンドには、gpiodetect、gpioinfo、gpioset、gpioget、gpiofind、gpiomonがあります。
$ sudo ls /dev/gpio*
/dev/gpiochip0 /dev/gpiochip2 /dev/gpiochip4 /dev/gpiomem1 /dev/gpiomem3
/dev/gpiochip1 /dev/gpiochip3 /dev/gpiomem0 /dev/gpiomem2 /dev/gpiomem4
$ sudo apt install gpiod
$ gpioinfo gpiochip4
gpiochip4 - 54 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" unused input active-high
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: "PCIE_RP1_WAKE" unused output active-high
line 29: "FAN_TACH" unused input active-high
line 30: "HOST_SDA" unused input active-high
line 31: "HOST_SCL" unused input active-high
line 32: "ETH_RST_N" "phy-reset" output active-low [used]
line 33: "-" unused input active-high
line 34: "CD0_IO0_MICCLK" "cam0_reg" output active-high [used]
line 35: "CD0_IO0_MICDAT0" unused input active-high
line 36: "RP1_PCIE_CLKREQ_N" unused input active-high
line 37: "-" unused input active-high
line 38: "CD0_SDA" unused input active-high
line 39: "CD0_SCL" unused input active-high
line 40: "CD1_SDA" unused input active-high
line 41: "CD1_SCL" unused input active-high
line 42: "USB_VBUS_EN" unused output active-high
line 43: "USB_OC_N" unused input active-high
line 44: "RP1_STAT_LED" "PWR" output active-low [used]
line 45: "FAN_PWM" unused output active-high
line 46: "CD1_IO0_MICCLK" "cam1_reg" output active-high [used]
line 47: "2712_WAKE" unused input active-high
line 48: "CD1_IO1_MICDAT1" unused input active-high
line 49: "EN_MAX_USB_CUR" unused output active-high
line 50: "-" unused input active-high
line 51: "-" unused input active-high
line 52: "-" unused input active-high
line 53: "-" unused input active-high
GPIOxxは、従来から使われているI/Oピンの呼び名です。このライブラリでは、GPIOxxをlinexxという呼び方をしており、Cのプログラム内ではxxと数値だけで指定するようです。

40ピン(GPIO21)と39ピン(GND)に抵抗入りLEDをつなぎます。
$ gpioset gpiochip4 21=1
LEDが点灯しました。
gpioinfo gpiochip4
では、下記のように変化しました。
line 21: "GPIO21" unused output active-high
消灯です。
$ gpioset gpiochip4 21=0
(参考文献) http://einstlab.web.fc2.com/RaspberryPi/5B.html
Cのライブラリ libgpiod-dev
ドキュメントは、インストールしたら、次のディレクトリに入っています。バージョンは1.6.3でした。
/usr/share/doc/libgpiod-dev/html/index.html
最新バージョンは2.1.2のようですが、どのOSで実装しているか不明です。1.6.3
に比べて仕様が変化しているように感じます。
$ sudo apt install libgpiod2 libgpiod-dev libgpiod-doc
$ sudo apt info libgpiod-dev
Package: libgpiod-dev
Version: 1.6.3-1.1build1
Lチカのプログラムです。
#include <stdio.h>
#include <unistd.h>
#include <gpiod.h>
#include <error.h>
int main() {
struct gpiod_chip *gchip;
struct gpiod_line *glinein, *glineout;
int value;
// GPIOデバイスを開く
if ((gchip = gpiod_chip_open("/dev/gpiochip4")) == NULL) {
perror("gpiod_chip_open_lookup");
return 1;
}
// GPIO出力
// GPIOのピンのハンドラを取得する ここではGPIO21ピンを
if ((glineout = gpiod_chip_get_line(gchip, 21)) == NULL) {
perror("gpiod_chip_get_line 21");
return 1;
}
// GPIOを出力モードに設定する
if (gpiod_line_request_output(glineout, "LED ON/OFF", 0) != 0) {
perror("gpiod_line_request_output");
}
for (int i=0; i < 10; i++){
// GPIOの値を1に設定する
if ((value = gpiod_line_set_value(glineout, 1)) == -1) {
perror("gpiod_line_set_value");
}
sleep(1);
// GPIOの値を0に設定する
if ((value = gpiod_line_set_value(glineout, 0)) == -1) {
perror("gpiod_line_set_value");
}
sleep(1);
}
// GPIOデバイスを閉じる
gpiod_chip_close(gchip);
return 0;
}
実行します。10回、GPIO21につないだLEDが点滅します。
$ g++ ex401.cpp -lgpiod
$ ./a.out
(参考文献)
いつものように、エラー処理を省略しました。
#include <stdio.h>
#include <unistd.h>
#include <gpiod.h>
int main() {
struct gpiod_chip *gchip;
struct gpiod_line *glinein, *glineout;
// GPIOデバイスを開く
gchip = gpiod_chip_open("/dev/gpiochip4");
// GPIOのピンのハンドラを取得 ここではGPIO21
glineout = gpiod_chip_get_line(gchip, 21);
// GPIOを出力モードに設定
gpiod_line_request_output(glineout, "LED ON/OFF", 0);
for (int i=0; i < 10; i++){
gpiod_line_set_value(glineout, 1); // GPIOの値を1に
sleep(1);
gpiod_line_set_value(glineout, 0); // GPIOの値を0に
sleep(1);
}
gpiod_chip_close(gchip); // GPIOデバイスを閉じる
return 0;
}
gpiod_chip_xxがGPIO chip operationsに分類される関数類でopen/closeにかかわります。
gpiod_line_request_xxが、Line requestsに分類される関数類で、出力、入力の設定をします。
gpiod_line_set_xxが、Reading & setting line valuesに分類される関数類で、出力、入力の値を設定をします。