ラズパイ工作の定番と言われる,起動・リブート・シャットダウンスイッチです。
赤のタクトスイッチが起動ボタンです。出力として使用しているときに押されてもショートしないように330kΩの抵抗を挟んでいます。(1kΩでは起動しませんでした。330Ωであれば,電流は10mA(3.3 / 330 = 0.01)に抑えられるので,簡単に壊れたりはしないと思います。)
白のタクトスイッチがリブート・シャットダウンボタンです。プルアップし,Pythonで立ち下がりを検出するようにします。LEDが3回点滅するまで押し続けることでリブート,5回点滅するまで押し続けることでシャットダウンするようにPythonのコードを書きます。また,LEDは0.5秒ごとに点滅するようにします。
ケースに組み込んだときなどに,外付けのボタンで操作できるように,タクトスイッチと平行にXHコネクタを付けておくことにします。
☆材料 ラズパイZero用ユニバーサル基板 | 秋月 P-14031 | 100円 |
ラズパイ用スタッキングコネクタ | 秋月 C-10702 | 150円 |
タクトスイッチ×2(赤・白) | 秋月 P-03648 | 20円 |
XHコネクタ(2ピン)×2 | 秋月 C-12247 | 20円 |
超高輝度5mmオレンジ色LED | 秋月 I-06404 | (10個)200円 |
カーボン抵抗 1/4W 0Ω | 秋月 R-25000 | (100本)100円 |
カーボン抵抗 1/4W 330Ω | 秋月 R-25331 | (100本)100円 |
カーボン抵抗 1/4W 1kΩ | 秋月 R-25102 | (100本)100円 |
カーボン抵抗 1/4W 10kΩ | 秋月 R-25103 | (100本)100円 |
合計 | | 890円 |
☆配線図 (抵抗のカラーコードの間違いを修正しました。R01.08.26)
☆できあがり☆テストコード
①まずは,LEDチカチカ
LEDを10回,0.5秒間隔で点けたり消したりする。
import RPi.GPIO as GPIO import time
LED_PIN = 12
GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT)
for i in range(10): GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(0.5) GPIO.output(LED_PIN, GPIO.LOW) time.sleep(0.5) GPIO.cleanup()
|
②タクトスイッチの押下検出
タクトスイッチを押すまで待ち,スイッチを押したら,"Button Pushed.”のメッセージを表示する。
import RPi.GPIO as GPIO import time
BUTTON_PIN = 26
GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(BUTTON_PIN, GPIO.IN) GPIO.wait_for_edge(BUTTON_PIN, GPIO.FALLING) print("Button Pushed.") GPIO.cleanup()
|
☆リブート&シャットダウン
①タクトスイッチの押下でリブートまたはシャットダウンするコード
・wait_for_edge()を使うと,killしても待ち続け,すぐに終了しない。(killしたあと,タクトスイッチを押した時点で終了する。)そのため,add_event_detect()を使ってコールバック関数を呼ぶようにし,ループで待機する。
・コールバック関数で長い時間処理をすると,チャタリングが起きるのか,2回連続でコールバック関数が呼ばれることがあった。そのため,コールバック関数ではフラグをセットしてすぐに終了し,待機ループでフラグの変化を検知して必要な処理を行うようにした。
import RPi.GPIO as GPIO import time import sys import os import signal
LED_PIN = 12 BUTTON_PIN = 26 button_flag = False
def main(): GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT) GPIO.setup(BUTTON_PIN, GPIO.IN) GPIO.output(LED_PIN, GPIO.LOW) blink_led(3, 0.1) GPIO.output(LED_PIN, GPIO.HIGH) GPIO.add_event_detect(BUTTON_PIN, GPIO.FALLING, callback=button_pushed, bouncetime=300) signal.signal(signal.SIGTERM, sigterm_handler) global button_flag try: while True: time.sleep(0.1) if button_flag: choose_action() button_flag = False except KeyboardInterrupt: pass finally: GPIO.output(LED_PIN, GPIO.LOW) GPIO.remove_event_detect(BUTTON_PIN) GPIO.cleanup()
def blink_led(times, wait): for i in range(times): GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(wait) GPIO.output(LED_PIN, GPIO.LOW) time.sleep(wait)
def button_pushed(gpio_pin): global button_flag button_flag = True
def choose_action(): GPIO.output(LED_PIN, GPIO.LOW) time.sleep(0.2) count = 0 while True: blink_led(1, 0.5) count += 1 if GPIO.input(BUTTON_PIN) == GPIO.HIGH: if count == 3: blink_led(3, 0.1) os.system("sudo reboot") sys.exit() if count == 5: blink_led(5, 0.1) os.system("sudo shutdown -h now") sys.exit() blink_led(5, 0.1) GPIO.output(LED_PIN, GPIO.HIGH) break
def sigterm_handler(signal_number, stack_frame): sys.exit()
if __name__ == "__main__": main() |
②サービスとして自動起動するために,下のUnit定義ファイルをファイル名「reboot_shutdown.service」で保存する。[Unit] Description=for Reboot and Shutdown board
[Service] ExecStart=/usr/bin/python3 /home/pi/reboot_shutdown.py
[Install] WantedBy = multi-user.target
|
③「/etc/systemd/system/」にUnit定義ファイルをコピーする。 $ sudo mv reboot_shutdown.service /etc/systemd/system/
|
④サービスとして起動
LEDが3回点滅したあと,点灯して待機することを確認。
$ sudo systemctl start reboot_shutdown
|
⑤サービス再起動
LEDが一度消灯し,その後再起動することを確認。
$ sudo systemctl restart reboot_shutdown
|
⑥サービス終了
LEDが消灯し,終了することを確認。
$ sudo systemctl stop reboot_shutdown
|
⑦サービス自動起動を有効にする
$ sudo systemctl enable reboot_shutdown Created symlink /etc/systemd/system/multi-user.target.wants/reboot_shutdown.service ? /etc/systemd/system/reboot_shutdown.service.
|
⑧再起動
再起動後,LEDが点灯し,自動起動したことを確認。