Edited at

10: Raspberry Pi3 で Push Switch で shutdown / boot する

More than 1 year has passed since last update.


はじめに

こちらは

Arduino と Raspberry Pi の違いのまとめ

の個別記事で、Raspberry Pi3 で Push switch の長押しで shutdown し、その後、再度 Switch を押すと起動する。(のつもりだったが、事情により、shutdownとbootのswitchは別々とした)


目的

Raspeberry Pi3 で shutdown を行う際には、GUI でメニューから操作したり、console から command を入力する必要がある。これは少々面倒であるし、HDMI 入力の Display が不要な場合でも、Display と USB Mouse の接続が必要であり運用上好ましくない。また shutdown 後に再度電源を入れるためには、AC Adapter の On/Off をACタップの独立スイッチで操作するか、Raspberry Pi3 に接続している電源用の USBケーブルを挿抜しなければならない。USBケーブルにスイッチがついたものなどもあるが。

つまり、問題は次の二つである。

-【問題】: shutdown の操作の手間と、shtudown 後の再起動の手間

-【原因】: この問題の原因は、Raspberry Pi3 に通常のPCのように電源Onのスイッチがないからである。電源を供給入れるとすぐ起動する仕組みになっている。また利用用途によっては、頻繁に On / Off を行うが、外部Display を持たない利用方法の時に安全に shutdown する方法が提供されていないためである。いきなり電源を切ると Micro SDカード上の File System が破壊されることが容易に想像される。

-【解決方法】: そこで、指定のボタン一つで shutdown と boot を簡単に操作できるようにする。こうしておけば HDMI 入力の Display がなくても shutdown を簡単に安全に実現できる。また、shutdown 後の再起動でも、電源の USB ケーブルを挿抜したり、AC アダプタの電源を On/Off する必要がなくなる。

Raspberry Pi に最初から備えて欲しい機能ではある。

安全のため長押しで shutdown となり、ちょっと短く押すだけでは何もしない仕様である。


Shutdown ボタン


配線

Push Switch を好きなGPIOと3.3Vに接続する。これは、Pull downするため。ここでの codeは、pull down向けである。Pull upがいい人はGPIOとGNDを接続し、codeは適当に書き換える必要がある。


3.3V --- (Push SW) -- GPIO21 —--— [Internal Pull down Register] --- GND

まずはシンプルに試してみる。


code

pi-shutdown.py 

#!/usr/bin/python
# coding:utf-8
import time
import RPi.GPIO as GPIO
import os

SHUTDOWN_GPIO = 21

GPIO.setmode(GPIO.BCM)
GPIO.setup(SHUTDOWN_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

while True:
state = GPIO.input(SHUTDOWN_GPIO)
print('state = ' + str(state))
if state == True:
print('Button pressed. Pi will go shutdown now.')
os.system("sudo shutdown -h now")
else:
print("Not pressred.")
time.sleep(0.2)


scriptを実行可能に変更する


pi@rp:~ $ sudo chmod 755 pi-shutdown.py


単体テスト


pi@rp:~ $ ./pi-shutdown.py

で起動する。

しかし、これだと間違ってちょっとボタンを押しただけで shutdown してしまので、少し長く押さないと shutdown しないようにした。


#!/usr/bin/python
# coding:utf-8
import time
import RPi.GPIO as GPIO
import os

SHUTDOWN_GPIO = 21

GPIO.setmode(GPIO.BCM)
GPIO.setup(SHUTDOWN_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

counter = 0

while True:
state = GPIO.input(SHUTDOWN_GPIO)
print('state = ' + str(state))
if state == True:
counter += 1
if counter > 100:
print('Button pressed. Pi will go shutdown now.')
os.system("sudo shutdown -h now")
break
else:
print("Not pressed for long enough.")
time.sleep(0.01)

state を間違って逆にしてしまうと、何もボタンを押さなくても shutdown するシステムになってしまい、起動と自動shutdown を繰り返してしまうことになるので注意。(やってしまった...)

os.systemのところをコメントアウトして、十分にテストしてからserviceに登録した方がよさそう。

しかし、起動が面倒くさい。


自動起動の設定

それはさておき、まずは自動起動を設定する。

systemdという仕組みで、Unitというサービスを作る。


shell /usr/lib/systemd/system/shutdownd.service


[Unit]
Description=Shutdown Daemon

[Service]
ExecStart =/home/pi/py-shutdown.py
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target


次にサービスを自動起動するように設定する。


pi@rp:~ $ sudo systemctl enable shutdownd.service

ここで Raspberry Pi を再起動して、service のstatus を確認すると登録されていることが分かる。


pi@rp:~ $ sudo systemctl status shutdownd.service
● shutdownd.service - My Shutdown Daemon, May 2, 2018
Loaded: loaded (/usr/lib/systemd/system/shutdownd.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2018-05-01 19:52:53 UTC; 1min 22s ago
Main PID: 336 (pi-shutdown.py)
CGroup: /system.slice/shutdownd.service
└─336 /usr/bin/python /home/pi/pi-shutdown.py

May 01 19:52:53 rp systemd[1]: Started My Shutdown Daemon, May 2, 2018.

ちなみに、この enable コマンドでは再起動時に自動起動するが、今サービスを起動するわけではない。すぐに有効にするには、start を使う。同様に disable ではすぐは停止しない。再起動が必要である。

今すぐ起動したり、停止したりするには、start あるいは stop を利用する。


pi@rp:~ $ sudo systemctl start shutdownd.service


pi@rp:~ $ sudo systemctl stop shutdownd.service

サービスとして登録されているかを見るには次のようにするとよいだろう。 grepしなければずらずらっとたくさんのサービスが表示される。


$ sudo systemctl list-unit-files --type=service | grep shutdown
shutdownd.service disabled

あるいは

$ sudo systemctl list-unit-files --type=service | grep shutdownd

shutdownd.service enabled

まとめると、以下のようになる。


systemctl オプション一覧

一部のみであるが、まとめてみる

やりたいこと
command

自動起動を有効
systemctl enable your_service_name

自動起動を無効
systemctl disable your_service_name

起動
systemctl start your_service_name

停止
systemctl stop your_service_name

ステータス表示
systemctl status your_service_name


テスト

電源投入時からの Push Button の長押しで shutdown が確認できた。動作ok.


起動ボタン

次に起動を簡単にする。


配線

Raspberry Pi3 には、GPIO#3 と GND をショートすると、再起動する仕組みがある。

shutdown と boot とそれぞれ Push Switch を独立して取り付けてもよいが下記のように配線して、一つで済ますようにする。


GPIO3 —--— + --- (Push SW) --- GND
GPIO21 ---- +

あ、shutdown switch を pull up しておけばスイッチ一つですんだのに...


操作方法

起動中:SW の長押しで shutdown し、短押しでは何もしない

shutdown後:押すと起動する

つまり、shtudown後は、halt しているだけらしく、short させるだけで起動する。


統合テスト

電源投入時からの Push Button の長押しで shutdown および boot が確認できた。動作ok.

参考

https://elinux.org/RPI_safe_mode


親記事

Arduino と Raspberry Pi の違い