ラズパイでコードを書かずにシャットダウン・電源ボタンを作る

ラズパイに物理的なシャットダウンボタン・電源ボタンを作ろうとググると、「GPIO にボタンを接続し、Pythonでボタンが押されたときにshutdownコマンドを走らせるコードを書いて常駐させよう」という話がよく出てきますが、**コードを書く必要はありません**。設定ファイルを 1 行編集するだけで実現できます。

## 用意するもの

- Raspberry Pi（4Bで検証済み）
- スイッチ
    - 見た目を気にしないなら[秋月で手に入る1個10円程度のタクトスイッチ](https://akizukidenshi.com/catalog/c/ctactsw/)で十分です
- ブレッドボード等


## 用意する環境

- Raspberry Pi上の設定ファイルを編集できる環境
    - SSHやVNCのリモート接続でも構いませんし、USBやHDMIを有線で接続した環境でも構いません。

## 1. 配線する

スイッチを押すことで **GPIO 3 (ピン番号 5)** と **GND (ピン番号 6)** を短絡できるように（つながるように）してください。これだけでOKです。
デフォルトは**GPIO3**なので、それ以外のピンを使いたい場合は設定での記述内容が増えます。

ブレッドボードでは以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185296/e34a32f4-f5b1-71b2-acd4-cc5f7ec0c16d.png)


## 2.設定ファイルの編集

nano などで `/boot/config.txt` を開いて編集してください。標準の `pi` などの一般ユーザで作業しているならroot 権限が必要なので `sudo` を付けましょう。

```sh
sudo nano /boot/config.txt
```

最終行に以下のものを記述します。

```
dtoverlay=gpio-shutdown
```

`Ctrl`+`O`→ `Enter` で保存し、`Ctrl` + `X` で nano を閉じます。
続いて、以下のコマンドでシャットダウンします。

```sh
sudo shutdown -h now
```

## 3. 起動とシャットダウン

電源ケーブルが繋がれており、シャットダウンしている状態でタクトスイッチを押すと起動します。

起動した後にタクトスイッチを押すとシャットダウンします。

1つのボタンを起動・シャットダウンで兼用できるので便利です。


## これは何か？

標準で備わっている[デバイスツリーオーバーレイ](https://www.raspberrypi.org/documentation/configuration/device-tree.md)を利用しています。

Raspberry Pi OS (旧: Raspbian)上に存在しているREADMEを見ると、以下のような情報が記載されています。
上記のように特にパラメータを渡さない場合、GPIO 3とGNDが短絡したときにシャットダウンが走るようになっています。

パラメータを変えると別のGPIOピンでもシャットダウンを割り当てることができます。

```plaintext:/boot/overlays/READMEより一部引用
Name:   gpio-shutdown
Info:   Initiates a shutdown when GPIO pin changes. The given GPIO pin
        is configured as an input key that generates KEY_POWER events.
        This event is handled by systemd-logind by initiating a
        shutdown. Systemd versions older than 225 need an udev rule
        enable listening to the input device:

                ACTION!="REMOVE", SUBSYSTEM=="input", KERNEL=="event*", \
                        SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", \
                        ATTRS{keys}=="116", TAG+="power-switch"
        This overlay only handles shutdown. After shutdown, the system
        can be powered up again by driving GPIO3 low. The default
        configuration uses GPIO3 with a pullup, so if you connect a 
button between GPIO3 and GND (pin 5 and 6 on the 40-pin header),
        you get a shutdown and power-up button.
Load:   dtoverlay=gpio-shutdown,<param>=<val>
Params: gpio_pin                GPIO pin to trigger on (default 3)
        active_low              When this is 1 (active low), a falling
                                edge generates a key down event and a
                                rising edge generates a key up event. 
                                When this is 0 (active high), this is
                                reversed. The default is 1 (active low).

        gpio_pull               Desired pull-up/down state (off, down, up)
                                Default is "up".

                                Note that the default pin (GPIO3) has an
                                external pullup.
        debounce                Specify the debounce interval in milliseconds
                                (default 100)
```

また、ラズパイはシャットダウンされた状態で GPIO 3 と GND を短絡することで起動するようになっています（こちらは設定は不要です）。
これら 2 つの組み合わせにより、1 つのボタンでシャットダウン・起動ボタンを実現できるのです。

## 注意事項

GPIO3 は I2C 用のピンを兼ねています。そのため、設定画面などで I2C をオンにしているとシャットダウンが正常に走らない場合があります。
その際は `/boot/config.txt` で以下のように `dtparam=i2c_arm=on` をコメントアウトしてあげてください。

```
#dtparam=i2c_arm=on
```

また、このボタンはラズパイへの電源供給を遮断するものではありません（`shutdown -h now` を叩くのと同様の挙動をする）。
電源自体を投入しなおしたい場合はコードを抜き差しする必要があります。