ラズパイでシャットダウンボタンを付ける(ついでに起動ボタン)


##■動機
自分はラズパイ開発はMacからSSH接続で行っていて、かつ同一ネットワークのwifi接続なので電源のみの接続で開発できている。

開発しているときは良いものの、外出時にMac持ち運んだ時とか、寝落ちした時とか、
ラズパイが起動したままSSH接続が切れているときがよくある。

そんな時、ラズパイのシャットダウンのためだけにPC起動するのも面倒だし、かと言って電源ぶつ切りもシステム壊れそうでやりたくない・・・

そんなわけで、PCを起動しなくてもラズパイ本体だけでシャットダウンさせたかった。
探してみると、ボタン一個あればできるみたいなので挑戦。

やることは、
1. ピンの入力状態を変えるボタンを接続
2. シャットダウンするプログラムを作成
3. 2をラズパイ起動時に自動起動して、バックグラウンドで動作するサービスとして登録
という感じ。

3の自動起動は、昔は/etc/rc.localというのを使っていたらしいが、
最近はsystemdというのを使うのが主流になってきているらしいので、
今回はsystemdを使うことにする。


###■参考サイト
[RaspberryPiにshutdownボタンを付けよう](http://jellyware.jp/kurage/raspi/shutdown_button.html)
[Raspberry Pi 3 にシャットダウン/リブート/再開ボタンを追加する](http://hammmm.hatenablog.com/entry/2016/11/14/231337)
[Raspbian jessieでSystemdを使った自動起動](https://qiita.com/yosi-q/items/55d6d3d6834c778ae2ea)

毎度先達には感謝ばかりです。探せば絶対誰かやってるからなぁ・・・

##■初期状態確認
GPIOのピン状態を確認。
初めて出したけど、きれいに整形している。

 ```Console
pi@raspberrypi:~ $ gpio readall
 |-----|-----|---------|------|---|-Pi ZeroW-|---|------|---------|-----|-----|
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 |-----|-----|---------|------|---|----------|---|------|---------|-----|-----|
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 | ALT0 | 1 |  3 || 4  |   |      | 5v      |     |     |
 |   3 |   9 |   SCL.1 | ALT0 | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 1 | ALT5 | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | ALT5 | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 1 | OUT  | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI | ALT0 | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO | ALT0 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK | ALT0 | 0 | 23 || 24 | 1 | OUT  | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 1 | OUT  | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 | ALT4 | 0 | 35 || 36 | 1 | OUT  | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | ALT4 | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | ALT4 | GPIO.29 | 29  | 21  |
 |-----|-----|---------|------|---|----------|---|------|---------|-----|-----|

 ```


 BCM 23 をIN、UPに設定してみる。
 
 ```Console
pi@raspberrypi:~ $ gpio -g mode 23 in
pi@raspberrypi:~ $ gpio -g read 23
0
pi@raspberrypi:~ $ gpio -g mode 23 up
pi@raspberrypi:~ $ gpio -g read 23
1

pi@raspberrypi:~ $ gpio readall
 +-----+-----+---------+------+---+-Pi ZeroW-+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 | ALT0 | 1 |  3 || 4  |   |      | 5v      |     |     |
 |   3 |   9 |   SCL.1 | ALT0 | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 1 | ALT5 | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | ALT5 | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 1 | OUT  | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 1 | IN   | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI | ALT0 | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO | ALT0 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK | ALT0 | 0 | 23 || 24 | 1 | OUT  | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 1 | OUT  | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 | ALT4 | 0 | 35 || 36 | 1 | OUT  | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | ALT4 | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | ALT4 | GPIO.29 | 29  | 21  |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+-Pi ZeroW-+---+------+---------+-----+-----+

 ```


##■配線
 ![UNADJUSTEDNONRAW_thumb_10fe.jpg](https://qiita-image-store.s3.amazonaws.com/0/199149/27c6ee58-4436-d8af-a252-9eb672dc7db4.jpeg "UNADJUSTEDNONRAW_thumb_10fe.jpg")

ボタンを押したらBCM23番PINがGNDにつながるだけ。
(緑のケーブル。青ケーブルは一番下で解説)
(右側のケーブルの束はI2CのセンサやらLCDなので関係なし)


■動作確認。

```
#ボタンを離した状態
pi@raspberrypi:~ $ gpio -g read 23
1

#ボタン押した状態
pi@raspberrypi:~ $ gpio -g read 23
0
``` 
HIGHからLOWに落とす条件にしているので、
ボタンを押していない状態で1(HIGH:3.3V)、
ボタンを押した状態で0(LOW:GND)となっているのできちんと認識している様子。


##■シャットダウンのプログラムを作成
ピン番号以外は完全コピペです。[RaspberryPiにshutdownボタンを付けよう](http://jellyware.jp/kurage/raspi/shutdown_button.html)


```/home/pi/pyhome/shutdownd.py
#!/usr/bin/python 
# coding:utf-8 
import time
import RPi.GPIO as GPIO
import os
 
pinnumber=23
GPIO.setmode(GPIO.BCM)
 
#GPIO23pinを入力モードとし、pull up設定とします 
GPIO.setup(pinnumber,GPIO.IN,pull_up_down=GPIO.PUD_UP)
 
while True:
    GPIO.wait_for_edge(pinnumber, GPIO.FALLING)
    sw_counter = 0
 
    while True:
        sw_status = GPIO.input(pinnumber)
        if sw_status == 0:
            sw_counter = sw_counter + 1
            if sw_counter >= 50:
                print("長押し検知！")
                os.system("sudo shutdown -h now")
                break
        else:
            print("短押し検知")
            break
 
        time.sleep(0.01)
 
    print(sw_counter)
```

作成後に`sudo chmod 755 Lchika.py`で権限付与も忘れずに。


##■サービスファイルを作成
`sudo nano /usr/lib/systemd/system/shutdownbuttond.service`
で以下を作成。

```/usr/lib/systemd/system/shutdownbuttond.service
[Unit]
Description=Shutdown Daemon

[Service]
ExecStart =/home/pi/pyhome/shutdownd.py
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target

```

■サービス有効化(これやらないと自動起動しないので重要)
`pi@raspberrypi:~ $ systemctl enable shutdownbuttond.service`

■デーモン再起動
`sudo systemctl daemon-reload`


##■サービスが有効になっているか確認
`systemctl status shutdownbuttond.service`にてステータスが見れる

**○成功時**

```Console
pi@raspberrypi:~ $ systemctl status shutdownbuttond.service
● shutdownbuttond.service - Shutdown Daemon
   Loaded: loaded (/usr/lib/systemd/system/shutdownbuttond.service; enabled)
   Active: active (running) since 日 2017-10-08 19:25:47 JST; 4min 57s ago
 Main PID: 1442 (shutdownd.py)
   CGroup: /system.slice/shutdownbuttond.service
           └─1442 /usr/bin/python /home/pi/pyhome/shutdownd.py
```

↑ で`(/usr/lib/systemd/system/shutdownbuttond.service; enabled)`、
`active (running)`になっていれば起動しているはず。

**×失敗時** 
disable,failedになっている。
このときはファイル名とか間違ってた。

```Console
pi@raspberrypi:~ $ systemctl status shutdownbuttond.service
● shutdownbuttond.service - Shutdown Daemon
   Loaded: loaded (/usr/lib/systemd/system/shutdownbuttond.service; disabled)
   Active: failed (Result: start-limit) since 日 2017-10-08 18:41:09 JST; 1min 30s ago
```

確認方法としては以下で全サービスを出すのもあり。Activeとして載っていればOK。
`systemctl -t service`


これにて、ボタンを0.5秒程度押すと自動でシャットダウンできるようになった。


##■シャットダウン時から起動もさせられる!

[Raspberry Pi 3 にシャットダウン/リブート/再開ボタンを追加する](http://hammmm.hatenablog.com/entry/2016/11/14/231337)
こちらのサイトでは、シャットダウン時からの起動にも触れている。
左の上から3番目(BCM3、SCL)のピンをGNDに落とすとシャットダウン時から起動できるらしい。
コマンドでシャットダウンすると、USBケーブル抜かないと行けないから煩わしいと思っていたのだけど、抜き差しせずに起動できるのは助かる。

上の配線写真の、手前青い線がBCM3=SCLにつながっている。(I2Cで使っているので、そちら側から分岐させて持ってきた)

結果的に一個のボタンで、
**起動時は長押しでシャットダウン、
停止時(かつ電源接続時)は短押しで起動**

ができるようになった。