Raspberry Piにリブート/シャットダウンスイッチをつける [Raspberry Pi]
Raspberry Pi B+/Pi 2 B用のリブート/シャットダウンスイッチを作ってみました。
まずは、Raspberry Piに取りつけるリブート/シャットダウンボタンを製作します。
▲秋月で購入した2ピンタクトスイッチと、好みの長さに切断できる分割ロングピンソケットで、リセット/シャットダウンスイッチを作ります。RasPi内蔵プルアップ抵抗を使うので、外付け抵抗は不要です。
▲タクトスイッチを、Pin39(GND)-Pin40(GPIO21)間に挿します。
電子工作はこれだけ。超カンタン。
続いて、リブート/シャットダウンスクリプトを作成。あらかじめ、Python(Python3) GPIOモジュールもインストールしておきましょう。
スクリプトの仕様と、動作シーケンスは以下のとおりです。
(1) リブート/シャットダウンスクリプトが起動すると、オンボードPower LEDが点滅します(2秒毎に0.1秒間消灯)。
↓ (2) タクトスイッチを1秒以上押し続けると、LEDがゆっくり点滅(3秒間)。この間にスイッチを離すとリブートします。
↓ (3) さらにタクトスイッチを押し続けると、LEDが速く点滅(3秒間)。この間にスイッチを離すとシャットダウンします。
↓ (4) さらにタクトスイッチを押し続けると、リブート/シャットダウン処理をキャンセルできます。
↓ (1)へ戻る
リセットボタンを押したあとに「いかん! 編集中のデータをまだ保存してなかった!」的な事態に陥っても、ボタンを長押ししつづければ危機回避が可能な仕様となっております。
スクリプトを起動し、動作確認を行います。
リブート、シャットダウンともに正しく動作することを確認できたら、/etc/rc.localの最終行(exit 0)の前の行に /usr/local/bin/resetbutton.py & を追加し、リブートしましょう(※1)。Raspberry Pi起動時に、リブート/シャットダウンスクリプトを自動起動することができます。
※1
/etc/rc.localを書き換えて自動起動させた場合、スクリプトの入力ミスやタクトスイッチに不具合があると、最悪の場合リブートをくり返す可能性があります。Win32DiskImagerなどを使って、事前にシステムのバックアップをとっておきましょう。
※2
拙宅のB+/2 Bでは正しく作動しましたが、古いB+だとエラーが出たり、オンボード Power LEDが点滅しないかもしれません。sudo rpi-updateでファームウェアを更新したり、aptitudeやapt-getで導入済みパッケージの更新を行ってみてください。
Sponsored Link
まずは、Raspberry Piに取りつけるリブート/シャットダウンボタンを製作します。
▲秋月で購入した2ピンタクトスイッチと、好みの長さに切断できる分割ロングピンソケットで、リセット/シャットダウンスイッチを作ります。RasPi内蔵プルアップ抵抗を使うので、外付け抵抗は不要です。
▲タクトスイッチを、Pin39(GND)-Pin40(GPIO21)間に挿します。
電子工作はこれだけ。超カンタン。
続いて、リブート/シャットダウンスクリプトを作成。あらかじめ、Python(Python3) GPIOモジュールもインストールしておきましょう。
$ sudo aptitude install python-rpi.gpio pyhton3-rpi.gpio
スクリプトの仕様と、動作シーケンスは以下のとおりです。
(1) リブート/シャットダウンスクリプトが起動すると、オンボードPower LEDが点滅します(2秒毎に0.1秒間消灯)。
リセットボタンを押したあとに「いかん! 編集中のデータをまだ保存してなかった!」的な事態に陥っても、ボタンを長押ししつづければ危機回避が可能な仕様となっております。
$ sudo vi /usr/local/bin/resetbutton.py #!/usr/bin/env python # -*- coding:utf-8 -*- # # REBOOT & SHUTDOWN Button # for Raspberry Pi B+ / Pi 2 B # Written by gaecen ueno # [Dec.24,2015] # #=================================================================== # # GPIO Connection # S=TACT SW (GPIO 21) / G=GND # # 3 3 3 3 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 # 9 7 5 3 1 9 7 5 3 1 9 7 5 3 1 9 7 5 3 1 # G - - - - - - G - - - - - - - G - - - - # S - - - - - - - - - G - - G - - - - - - # 4 3 3 3 3 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 # 0 8 6 4 2 0 8 6 4 2 0 8 6 4 2 0 8 6 4 2 # # Holding down the button(tact switch) # | [1second] # | [3seconds](LED blink slowly) Release the button -> Reboot # V [3seconds](LED blink faster) Release the button -> Shutdown # Abort Reboot and Shutdown GPIO_BUTTON = 21 # GPIO 21(pin40) -> TACT SW -> GND GPIO_LED = 35 # GPIO 35 is On-Board PWR LED(/sys/class/leds/led1) LED_BLINK_TIME = [ [1.9, 0.1], # default on=1.9sec off=0.1sec [0.5, 0.5], # reboot on=0.5sec off=0.5sec [0.1, 0.1] # shutdown on=0.1sec off=0.1sec ] #=================================================================== import RPi.GPIO as GPIO import time import os SHUTDOWN_NONE = 0 SHUTDOWN_REBOOT = 1 SHUTDOWN_HALT = 2 def getButtonState(io): cnt = 0 prev_btn = not GPIO.input(io) while cnt < 3: time.sleep(0.01) btn = not GPIO.input(io) if prev_btn == btn: cnt += 1 else: prev_btn = btn cnt = 0 return btn def callback(ch): global shutdown_mode global do_shutdown # Waiting for holding down the button.(1sec) for i in range(10): btn = getButtonState(GPIO_BUTTON) if btn == False: break time.sleep(0.1) # [REBOOT] Release the button when the LED is blinking slowly.(3sec) else: shutdown_mode = SHUTDOWN_REBOOT for i in range(30): btn = getButtonState(GPIO_BUTTON) if btn == False: do_shutdown = True break time.sleep(0.1) # [SHUTDOWN] Release the button when the LED is blinking faster.(3sec) else: shutdown_mode = SHUTDOWN_HALT for i in range(30): btn = getButtonState(GPIO_BUTTON) if btn == False: do_shutdown = True break time.sleep(0.1) if do_shutdown == False: shutdown_mode = SHUTDOWN_NONE return #=================================================================== if __name__ == '__main__': GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(GPIO_LED, GPIO.OUT, initial=GPIO.HIGH) GPIO.setup(GPIO_BUTTON, GPIO.IN, pull_up_down=GPIO.PUD_UP) shutdown_mode = SHUTDOWN_NONE do_shutdown = False GPIO.add_event_detect(GPIO_BUTTON, GPIO.FALLING, callback=callback) try: while do_shutdown == False: GPIO.output(GPIO_LED, GPIO.HIGH) time.sleep(LED_BLINK_TIME[shutdown_mode][0]) GPIO.output(GPIO_LED, GPIO.LOW) time.sleep(LED_BLINK_TIME[shutdown_mode][1]) if shutdown_mode == SHUTDOWN_REBOOT: os.system("sudo shutdown -r now > /dev/null 2>&1") elif shutdown_mode == SHUTDOWN_HALT: os.system("sudo shutdown -h now > /dev/null 2>&1") except KeyboardInterrupt: pass finally: GPIO.cleanup(GPIO_LED) GPIO.cleanup(GPIO_BUTTON)
スクリプトを起動し、動作確認を行います。
$ sudo chmod 755 /usr/local/bin/resetbutton.py $ sudo /usr/local/bin/resetbutton.py
リブート、シャットダウンともに正しく動作することを確認できたら、/etc/rc.localの最終行(exit 0)の前の行に /usr/local/bin/resetbutton.py & を追加し、リブートしましょう(※1)。Raspberry Pi起動時に、リブート/シャットダウンスクリプトを自動起動することができます。
※1
/etc/rc.localを書き換えて自動起動させた場合、スクリプトの入力ミスやタクトスイッチに不具合があると、最悪の場合リブートをくり返す可能性があります。Win32DiskImagerなどを使って、事前にシステムのバックアップをとっておきましょう。
※2
拙宅のB+/2 Bでは正しく作動しましたが、古いB+だとエラーが出たり、オンボード Power LEDが点滅しないかもしれません。sudo rpi-updateでファームウェアを更新したり、aptitudeやapt-getで導入済みパッケージの更新を行ってみてください。
uxcell 押しボタンスイッチ タクトスイッチ 2ピン 瞬時触覚タクト ブラック 6x6x5mm 10個入
- 出版社/メーカー: uxcell
- メディア: Tools & Hardware
Sponsored Link
とても丁寧で参考になりました。ありがとう御座います。このようなページを作って頂き、感謝致します。
1点、最後の箇所で上手くいかない点がありましたので、コメント致しました。
> /rc.localの最終行(exit 0)の前の行に /usr/local
> /bin/resetbutton.py & を追加し、リブートしましょう(※1)。
▲こちらの local が不要でした。
見ればすぐ分かるのでアレですが。。。
コピペ初学者の為に、触れさせて頂きました。
by Austin (2016-11-04 12:28)