これは僕がRaspberryPiを手に入れてから一番最初に手を付けたpythonプログラム。
RaspberryPiには起動、終了の為の電源スイッチが無い。電源を入れるとONで終了処理をした後に電源OFFという手順を踏まないと正常に終了させることが出来ない。下手をすればSDカードを壊してしまう。
RaspberryPiに直接モニタ等を接続してログインしている場合は問題無いが、接続していない状態でLANに異常が発生して接続出来ていない状態になるとお手上げだ。正常終了が全く出来なくなってしまう。
僕が初めて使ったRaspberryPiはTypeAでLAN端子が付いていないもの。Wi-Fiドングルを接続設定して電源とドングルのみ接続して運用しようと目論んでいたのでWi-Fiが切れた場合を想定して書いたものだ。
用意するのはスイッチとインジケータ用LED。
(実はこのプログラムで電源制御するためにPICで小型リレーを制御して物理的に電源ONOFFする回路も作っていたのだが回路が大きくなってしまったのでこれは破棄。)
GPIO25がシャットダウンスイッチ
GPIO24がインジケータLED
コード内でシェルを介してjsayを読み出しているが、これは以前に「RaspberryPiにしゃべらせる」で紹介したjsayコマンドを読み出して音声出力している。
== 動作 ==
- プログラム実行されるとLEDを3秒点灯。
- 電源スイッチが操作されるまで待機。
- 電源スイッチが押されたらシェルでシステム終了させてプログラムが終了されるまでLEDを点灯。
これだけ。
スイッチは25番ピンをGNDへ短絡させることで動作する。
GPIO初期設定時に25番ピンをプルアップさせて電圧低下時にswitch_callback()関数を読み出すよう設定してあるので抵抗は不要。
-- gpio_shutdownd.py --
#!/usr/bin/python
#coding:utf-8
import RPi.GPIO as GPIO
import time
import sys
import os
Switch = 25
Led = 24
def switch_callback(gpio_pin):
GPIO.output(Led,1) #LED on
time.sleep(0.02)
if GPIO.input(gpio_pin) != 0: #pull up
GPIO.output(Led,0) #LED off
return
#print(gpio_pin)
os.system("jsay システム終了処理をします。しばらくお待ちください。")
os.system("shutdown -h now") #<=callShell
def standby():
GPIO.setmode(GPIO.BCM)
GPIO.setup(Switch, GPIO.IN, pull_up_down=GPIO.PUD_UP) #io7 input pullup
GPIO.setup(Led, GPIO.OUT) # ion led
GPIO.add_event_detect(Switch, GPIO.FALLING) # none / rising / falling / both
GPIO.add_event_callback(Switch, switch_callback) # setInterrupt
#GPIO.output(Led,1) # LED on
try:
GPIO.output(Led,1) #LEDon
time.sleep(3)
#os.system("jsay システム起動を完了しました。")
GPIO.output(Led,0) #LED off
while True:
time.sleep(60) # 1min
except KeyboardInterrupt:
GPIO.cleanup()
def fork(): # fork
pid = os.fork()
if pid > 0: # parent
f2 = open('/var/run/gpio_shutdownd.pid','w') # del DaemonContext
f2.write(str(pid)+"\n")
f2.close()
sys.exit()
if pid == 0: # child
standby()
if __name__=='__main__': # if script
fork()
これをデーモンとして稼働させている。
Piの↓GPIO端子にピッタリなメス端子付きのスイッチ
|