読者です 読者をやめる 読者になる 読者になる

DreamerDreamのブログ

夢想家の夢です。

RaspberryPiにシャットダウンスイッチを付ける

これは僕がRaspberryPiを手に入れてから一番最初に手を付けたpythonプログラム。

RaspberryPiには起動、終了の為の電源スイッチが無い。電源を入れるとONで終了処理をした後に電源OFFという手順を踏まないと正常に終了させることが出来ない。下手をすればSDカードを壊してしまう。

 

RaspberryPiに直接モニタ等を接続してログインしている場合は問題無いが、接続していない状態でLANに異常が発生して接続出来ていない状態になるとお手上げだ。正常終了が全く出来なくなってしまう。

僕が初めて使ったRaspberryPiはTypeAでLAN端子が付いていないもの。Wi-Fiドングルを接続設定して電源とドングルのみ接続して運用しようと目論んでいたのでWi-Fiが切れた場合を想定して書いたものだ。

 

用意するのはスイッチとインジケータ用LED。

(実はこのプログラムで電源制御するためにPICで小型リレーを制御して物理的に電源ONOFFする回路も作っていたのだが回路が大きくなってしまったのでこれは破棄。)

 

GPIO25がシャットダウンスイッチ

GPIO24がインジケータLED

コード内でシェルを介してjsayを読み出しているが、これは以前に「RaspberryPiにしゃべらせる」で紹介したjsayコマンドを読み出して音声出力している。

 

dreamerdream.hateblo.jp

 

 

== 動作 ==

  1. プログラム実行されるとLEDを3秒点灯。
  2. 電源スイッチが操作されるまで待機。
  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端子にピッタリなメス端子付きのスイッチ