Hatena::ブログ(Diary)

猫ぱーんち!

2013-09-25

Raspberry Pi にシャットダウンボタンをつける

コンソールを使わずに運用する場合でも自力でシャットダウンができないと何かと不便なので、スイッチでシャットダウンできるようにしました。

f:id:penkoba:20130926005508j:image:w480

参考にしたサイト
http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio

準備

まず、以下のように対話モードでpythonを実行し、RPi.GPIOのバージョンが0.5.1以上であることを確認します。

% sudo python
Python 2.7.3 (default, Jan 13 2013, 11:20:46) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import RPi.GPIO as GPIO
>>> GPIO.VERSION
'0.5.2a'

配線

Raspberry Piにスイッチを接続します。

f:id:penkoba:20130926010208g:image

P1ピンヘッダの 14ピン(GND) と 16ピン(GPIO23) から、スイッチに配線します。

サンプルの動作確認

まずは割り込み動作の確認のため、参考サイトのサンプルをそのまま試してみます。

% wget http://raspi.tv/download/interrupt1.py.gz
gunzip interrupt1.py.gz

interrupt1.py

#!/usr/bin/env python2.7  
# script by Alex Eames http://RasPi.tv/  
# http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio  
import RPi.GPIO as GPIO  
GPIO.setmode(GPIO.BCM)  

# GPIO 23 set up as input. It is pulled up to stop false signals  
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  

print "Make sure you have a button connected so that when pressed"  
print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"   
raw_input("Press Enter when ready\n>")  

print "Waiting for falling edge on port 23"  
# now the program will do nothing until the signal on port 23   
# starts to fall towards zero. This is why we used the pullup  
# to keep the signal high and prevent a false interrupt  

print "During this waiting time, your computer is not"    
print "wasting resources by polling for a button press.\n"  
print "Press your button when ready to initiate a falling edge interrupt."  
try:  
        GPIO.wait_for_edge(23, GPIO.FALLING)  
        print "\nFalling edge detected. Now your program can continue with"   
        print "whatever was waiting for a button press."  
except KeyboardInterrupt:  
        GPIO.cleanup()  # clean up GPIO on CTRL+C exit  
GPIO.cleanup()          # clean up GPIO on normal exit 

このスクリプトを、rootで起動します。
(pin16とpin6をボタンに繋げと書いてありますが、pin6の代わりにpin14を使用しました。
 14と16が隣同士なのでこちらの方がわかりやすいかと)

% sudo ./interrupt1.py
Make sure you have a button connected so that when pressed
it will connect GPIO port 23 (pin 16) to GND (pin 6)

Press Enter when ready
>
Waiting for falling edge on port 23
During this waiting time, your computer is not
wasting resources by polling for a button press.

Press your button when ready to initiate a falling edge interrupt.

(ここでスイッチを押す)

Falling edge detected. Now your program can continue with
whatever was waiting for a button press.

スイッチに反応してコマンドが終了します。

スクリプト改造

上記のサンプルを元に、スイッチが押されたらシャットダウンを行うコマンドを作ります。
/usr/local/sbin/shutdown-btn.py

#!/usr/bin/env python2.7  
import RPi.GPIO as GPIO  
import os
GPIO.setmode(GPIO.BCM)  

GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  

try:  
        GPIO.wait_for_edge(23, GPIO.FALLING)  
except KeyboardInterrupt:  
        GPIO.cleanup()  # clean up GPIO on CTRL+C exit  
GPIO.cleanup()          # clean up GPIO on normal exit  
os.system("/sbin/shutdown -h now")

これをrootで起動し、スイッチを押せばシャットダウンが行われます

sudo /usr/local/sbin/shutdown-btn.py

(スイッチを押す)

Broadcast message from root@pi2 (pts/1) (Thu Sep 26 01:27:26 2013):

The system is going down for system halt NOW!

init script作成

自動で起動したいので、サービス化します。
下記内容で、/etc/init.d/shutdown-button を作成します。

### BEGIN INIT INFO
# Provides: shutdown-button
# Required-Start:
# Required-Stop:
# Default-Start: 1 2 3 4 5 6
# Default-Stop: 0
# Short-Description: Shutdown Button
# Description: wait Shutdown Button
### END INIT INFO
#! /bin/sh
# /etc/init.d/shutdown-button
PIDFILE=/var/run/shutdown-btn.pid
case "$1" in
        start)
                if [ -f $PIDFILE ]; then
                        echo $PIDFILE exists.
                        exit 1
                fi
                start-stop-daemon -S -x /usr/local/sbin/shutdown-btn.py -b -m -p $PIDFILE
                ;;
        stop)
                if [ ! -f $PIDFILE ]; then
                        echo $PIDFILE not found.
                        exit 1
                fi
                start-stop-daemon -K -p $PIDFILE
                rm $PIDFILE
                ;;
        *)
                echo "Usage: /etc/init.d/shutdown-button {start|stop}"
                exit 1
                ;;
esac
exit 0

update-rc.dでinit scriptを登録します。デフォルトのrunlevel設定と違うと警告が出ますが、これでOKです。

% sudo update-rc.d shutdown-button defaults
update-rc.d: using dependency based boot sequencing
update-rc.d: warning: default start runlevel arguments (2 3 4 5) do not match shutdown-button Default-Start values (1 2 3 4 5 6)
update-rc.d: warning: default stop runlevel arguments (0 1 6) do not match shutdown-button Default-Stop values (0)

これで /usr/local/sbin/shutdown-btn.py が自動で起動されるようになりました。

まとめ

とりあえずシャットダウンスイッチが動作するようになりました。
が、これだけのために専用のプロセスがずっと待ち受けているのはちょっと不格好な気がしますし、pythonモジュールを使ってちょいちょいとスクリプトを書いただけで中身がよくわかりません。
GPIOがらみはもう少し掘り下げて、応用がきく状態にしたいと思っています。

hotstaffhotstaff 2013/12/25 09:06 丁寧な説明でとても参考になりました.
動作も完璧です.

penkobapenkoba 2013/12/25 10:17 ありがとうございます。参考になれば幸いです。

すたじおわーくすすたじおわーくす 2014/04/01 23:31 こんにちは。ハーネスの入手先を教えて頂けないでしょうか?

penkobapenkoba 2014/04/01 23:42 写真のはこれですね

TAKETAKE 2014/08/09 06:01 はじめまして、GPIOでボタンをつけて何かできたらいいなぁ、と思って検索してきました。
記事のとおりに回路を作ってGPIOで接続すると、ボタンを押したら電源が切れて面白かったです!
記事を書いて頂き、ありがとうございました

penkobapenkoba 2014/08/09 12:41 コメントありがとうござます。結構実用的ですよね。応用もきくと思います。

mtkzmtkz 2015/03/22 14:05 お世話になります。
% sudo update-rc.d shutdown-button defaults
の後、
insserv: script shutdown-button is not an executable regular file, skipped!
よく分からないのですが。。

mtkzmtkz 2015/03/22 14:05 お世話になります。
% sudo update-rc.d shutdown-button defaults
の後、
insserv: script shutdown-button is not an executable regular file, skipped!
よく分からないのですが。。

penkobapenkoba 2015/03/23 02:25 エラーメッセージは shutdown-button が実行ファイルではないと言っています。
sudo chmod a+x /etc/init.d/shutdown-button
としてみてはいかがでしょうか?

mtkzmtkz 2015/03/23 07:59 適切なアドバイスありがとうございます。エラーメッセジは出なくなりました。ただ他に余計なことを試したのでシャットダウンは出来ていません。ちょっとがんばってみます。ありがとうございました。

kenken 2015/09/02 11:05 以下のようなエラーメッセージが出ます。 volumio で行っています
root@volumio:~# update-rc.d shutdown-button defaults
update-rc.d: using dependency based boot sequencing
insserv: warning: script 'shutdown-button' missing LSB tags and overrides
insserv: There is a loop between service monit and shutdown-button if stopped
insserv: loop involving service shutdown-button at depth 2
insserv: loop involving service monit at depth 1
insserv: Stopping shutdown-button depends on monit and therefore on system facility `$all' which can not be true!
insserv: exiting now without changing boot order!
update-rc.d: error: insserv rejected the script header

kenken 2015/09/02 11:09 sudo /usr/local/sbin/shutdown-btn.py にてボタンが押されるとhaltするのは確認できています。どうしてもupdate-rc.dでエラーが出てしまいます。ご教授お願いします。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/penkoba/20130925/1380129824
リンク元
Connection: close