[小さな機械の相棒]Raspberry Pi 3 Model B+に電源ボタン類を追加する

Raspberry Pi 3 B+の電源スイッチ

Author:試作E型

エイです。
ちょっと確認事項ができてしまったので、記事にするのが遅くなってしまいました。

本体が届いたあと、暫くしてから到着した、Raspberry Pi 3 B+用の電源用ボタンを追加しました。
もともとはACアダプタ部分をスイッチ経由にするつもりだったのですが、いきなりの電源断はアレなので…
ボタンの機能はOS側で実装する必要がありますが、H/W的にはスイッチのみでなんとかなるので、かなりお手軽です。

参考:Raspberry Pi 3 にシャットダウン/リブート/再開ボタンを追加する
http://hammmm.hatenablog.com/entry/2016/11/14/231337

GPIOのピン配置(公式Readme)
https://www.raspberrypi.org/documentation/usage/gpio/README.md

今回購入したのは、1×4(各スイッチ用と共通ピンの5ピン)のフラットスイッチと、それに接続するためのオスーメスジャンパ線です。本当は1×3でよかったのですが、Amazonでちょうど良いのが見つからなかったので…
お値段は合計\480ちょっとです。

…実はこのせいで、エンクロージャに貼り付けておく、というのはあきらめざるを得なくなったのですが(汗
スイッチがでかすぎた…

まぁ、持ち運ぶわけでもないので、とりあえず機能の実装に入ります。
今回は、

・シャットダウンボタンを
・リセットボタンを(赤側)
・電源OFFからの復帰ボタンを

に割り当てました。

それぞれの接続先ですが、ボタン赤側から1番ピン…とすると、
・スイッチ1番ピンをGPIO26に接続
・スイッチ2番ピンをGPIO19に接続
・スイッチ4番ピンをGPIO3に接続
・スイッチ5番ピンをGND(どこでも良いが、今回はGPIO26の隣のGNDを使用)に接続

と接続しておきます。
※GPIO3以外は、どこのGPIOを使っても原則問題はないので、適当に空いているところを使います。

そして電源操作用のコードを書きます。
電源ボタンを押した瞬間にシャットダウンなどが実行されてしまうと、いろいろ面倒なため、長押しで動作するようにしています。

shutdown_by_button.py:

#!/usr/bin/env python

import RPi.GPIO as GPIO
import os, time
import syslog

GPIO.setmode(GPIO.BCM)

# GPIO19 : reset button
GPIO.setup(19, GPIO.IN, pull_up_down = GPIO.PUD_UP)
# GPIO26 : shutdown button
GPIO.setup(26, GPIO.IN, pull_up_down = GPIO.PUD_UP)

def shutdown(channel):
sw_counter = 0

while True:
sw_status = GPIO.input(26)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 100:
syslog.syslog('Shutdown Long Push')
os.system("sudo shutdown -h now")
break
else:
syslog.syslog('Shutdown Short Push {}sec'.format(sw_counter*0.01))
break

time.sleep(0.01)

def reboot(channel):
sw_counter = 0

while True:
sw_status = GPIO.input(19)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 100:
syslog.syslog('Reset Long Push')
os.system("sudo reboot")
break
else:
syslog.syslog('Reset Short Push {}sec'.format(sw_counter*0.01))
break

time.sleep(0.01)

GPIO.add_event_detect(26, GPIO.FALLING, callback = shutdown, bouncetime = 2000)
GPIO.add_event_detect(19, GPIO.FALLING, callback = reboot, bouncetime = 2000)

while 1:
time.sleep(100)

念の為、/var/log/messageに、押した時間を出すようにしています。
そして、各ボタン1秒長押し(0.01秒を100カウント)でシャットダウン/再起動を行うようにしています。

実は、即応型にした時に、何かのきっかけでGPIOが一瞬だけプルダウンしてしまい、勝手に電源が落ちるorリブートすることがあったので、その確認のためです。

まずはスクリプトを実行可能にしておきます。

$ chmod 0755 shutdown_by_button.py

この時点で、スクリプトが動作するかどうかを確認します。
1秒以上長押しでシャットダウンorリブート、それ未満ならログを出すだけで何もしないことを確認します。

そしてこれを、Raspbianが立ち上がった時に、自動的に起動するように、サービスの定義を行います。

$ sudo nano /usr/lib/systemd/system/shutdown_by_button.service

ファイルの中身は以下のようにしておきます。

[Unit]
Description=Shutdown/Reboot raspberry pi by GPIO button input
Wants=network.target

[Service]
ExecStart=/home/pi/shutdown_by_button.py
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target

そして設定をsystemdに反映させ、起動時に自動実行されるようにします。

$ sudo systemctl daemon-reload
$ sudo systemctl start shutdown_by_button.service
$ sudo systemctl enable shutdown_by_button.service

サービスの状態を調べるには以下のコマンドで行います。

$ sudo systemctl status shutdown_by_button.service

緑の●がついていれば、サービスは正常に動作しています。

なお、電源OFF後の再起動には、GPIO3に接続した緑ボタンを押すだけです。
(これがないと、シャットダウン後に電源の抜き差しが必要になります)

とりあえず、これで自由にシャットダウン/再起動ができるようになりました。
電源を抜き差しするのはあまりやりたくないので、かなり便利です。