Ubuntu + Raspberry PiでGPIOアクセスのための設定

[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)

# 概要
Raspberry PiでROS2を使用するためにはUbuntuを入れるのが楽．
Ubuntuを単に入れるとRaspberry PiでGPIOを使用するときに管理者権限(rootになること)が必要．
具体的にはGPIOなどを使用するプログラムを実行するためには，sudoが必要．
面倒．

ということで一般ユーザのままでGPIOを使用するための設定．
これができれば，sudoなしでプログラム実行できて嬉しい．

## 想定

- [Raspberry Pi 3/4にUbuntuをインストール](https://qiita.com/NeK/items/a16cbc33dd3195226940)
    - 各種設定は管理者権限が必要
        - 管理者権限のある`ubuntu`ユーザで設定
- マルチユーザでの使用を想定
    - 一般ユーザは複数人を想定
        - 例えば複数人で一台のRaspberry Piを共有して演習することを想定
        - ただし一度に一人しか使えない(ハードウェアは一つなので当たり前)
        - 一般ユーザの例として以下のユーザ名を使用
            - nek

# デバイスアクセスのための設定
方針は以下の通り．

- GPIOなどのデバイスにアクセスするためにudev rulesを使用
    - udev rulesファイルを作成
    - デバイスアクセスのためのグループを作成
    - そのグループにユーザを追加


## udev rulesファイルの作成
`sudo apt install rpi.gpio-common`でも入るという情報もあるが，うまくいかなかったので手動で作成．

- 対象ファイル
    - /etc/udev/rules.d/99-com.rules

```text:99-com.rules
SUBSYSTEM=="input", GROUP="input", MODE="0660"
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
SUBSYSTEM=="bcm2835-gpiomem", GROUP="gpio", MODE="0660"
SUBSYSTEM=="rpivid-*", GROUP="video", MODE="0660"

KERNEL=="vcsm-cma", GROUP="video", MODE="0660"
SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660"

SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\
	chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;\
	chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio;\
	chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath\
'"

SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
	chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
	chown -R root:gpio /sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
'"

KERNEL=="ttyAMA0", PROGRAM="/bin/sh -c '\
	ALIASES=/proc/device-tree/aliases; \
	if cmp -s $$ALIASES/uart0 $$ALIASES/serial0; then \
		echo 0;\
	elif cmp -s $$ALIASES/uart0 $$ALIASES/serial1; then \
		echo 1; \
	else \
		exit 1; \
	fi\
'", SYMLINK+="serial%c"

KERNEL=="ttyAMA1", PROGRAM="/bin/sh -c '\
	ALIASES=/proc/device-tree/aliases; \
	if [ -e /dev/ttyAMA0 ]; then \
		exit 1; \
	elif cmp -s $$ALIASES/uart0 $$ALIASES/serial0; then \
		echo 0;\
	elif cmp -s $$ALIASES/uart0 $$ALIASES/serial1; then \
		echo 1; \
	else \
		exit 1; \
	fi\
'", SYMLINK+="serial%c"

KERNEL=="ttyS0", PROGRAM="/bin/sh -c '\
	ALIASES=/proc/device-tree/aliases; \
	if cmp -s $$ALIASES/uart1 $$ALIASES/serial0; then \
		echo 0; \
	elif cmp -s $$ALIASES/uart1 $$ALIASES/serial1; then \
		echo 1; \
	else \
		exit 1; \
	fi \
'", SYMLINK+="serial%c"

ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon1", RUN+="/bin/sh -c '\
	if echo RPi-Sense FB | cmp -s /sys/class/graphics/fb0/name; then \
		echo 0 > /sys$devpath/bind; \
	fi; \
'"
```

### 必要グループ追加
最初からグループが存在し，`group hogehoge already exists`などのメッセージが出ることもあるが，気にしない．

```shell
$ sudo groupadd input; sudo groupadd i2c; sudo groupadd spi; sudo groupadd gpio; sudo groupadd video;
```

### ユーザ追加
ユーザ名:nekとして説明．

```shell
$ sudo adduser nek
```

名前や部屋番号，電話番号などの情報を入力するように促されるが，パスワード以外は空欄(そのままエンター)でおっけ．

```shell
$ sudo gpasswd -a nek input; sudo gpasswd -a nek i2c; sudo gpasswd -a nek spi; sudo gpasswd -a nek gpio; sudo gpasswd -a nek video;
```

# 確認
例えばGPIO21にLEDをつなげて以下を実行してみる．

```shell
$ echo 21 > /sys/class/gpio/export
$ ls /sys/class/gpio
gpio21が増えていることを確認
$ echo out > /sys/class/gpio/gpio21/direction
$ echo 1 > /sys/class/gpio/gpio21/value
$ echo 0 > /sys/class/gpio/gpio21/value
LEDがついたり消えたりする
$ echo 21 > /sys/class/gpio/unexport
$ ls /sys/class/gpio
gpio21が消えていることを確認
```

# 制限事項
pigpioライブラリでは，`/dev/mem`を使用している．これはrootでないと触れないものみたいでやっかい．現在`/dev/gpiomem`が登場し，他のライブラリではこれが使われているようだけど，pigpioライブラリではそうでないので困っている．．．以下のコマンドで無理やりgpiomemにできるが，今度は違うエラーが出て困っている．

```shell:
$ cd [pigpioライブラリをDL，makeしたところ]
$ sed "s/\/dev\/mem/\/dev\/gpiomem/g" pigpio.c > pigpio.c
```