5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GPIO信号でシャットダウン

Last updated at Posted at 2019-12-22

#1.はじめに

RaspberryPiのGPIO端子に信号が入力されると、シャットダウンする機能について解説します。既にいろいろなサンプルがありますが、ここでは、systemdからスクリプトを起動して、定期的にGPIOを監視する方法を説明します。

※本記事は、下名がはてなブログで公開している内容を元に、一部内容を訂正したものになります。(十分試用して、問題無いようですのでこちらに転載しました)

##環境

  • Raspberry Pi シリーズ (1, 2, 3, 3+)
  • OS
    • Raspbian
    • Ubuntu Linux 18.04 (ラズパイ版 32/64bit)

#2.つくりかた

##(1)ファイル構成

本記事では、下記のファイルを作成します。

ファイル名 機能
setPowerWatcher.sh GPIO入力ピンの状態監視とシャットダウン処理
setPowerWatcher.service systemdのサービスファイル

最後に、systemdにサービスとして登録します。

##(2)シェルスクリプト

「定数」の所は、環境に合わせて修正してください。

定数 機能
SET_WATCH_PORT GPIOピンにシャットダウン信号を入れる番号を指定
SET_TRIGGER 信号の立ち上がり・立ち下がりどちらで反応するかを設定
SET_WATCH_INTERVAL 指定した秒数ごとに、シャットダウン信号の状態を監視

ソース中の所々の[INSTALL DIR]は、お使いの環境に合わせて書き換えてください。

setPowerWatcher.sh
#!/bin/bash
#--------------------------------------------------------------------
# UPSの信号監視とシャットダウン
# 2019 by myasu
# MIT Licence
#--------------------------------------------------------------------
#
#install:
# $ sudo ln -s /home/pi/[INSTALL DIR]/setPowerWatcher.service /etc/systemd/system
# $ sudo systemctl enable setPowerWatcher.service
# $ sudo systemctl start setPowerWatcher.service
#--------------------------------------------------------------------
#ref:
#
# ※必ずbashを使うこと。shを使うと関数の宣言でエラーが出ます
#   https://yatta47.hateblo.jp/entry/2014/04/20/222707
#

#----------------------------------
#定数
#----------------------------------

#監視するポート(BMC番号で指定)
SET_WATCH_PORT=4

#監視モード
# 1:ダウンパルス、0:アップパルス
SET_TRIGGER=1

#監視ループの間隔(sec)
SET_WATCH_INTERVAL=1


#----------------------------------
#関数
#----------------------------------

#シャットダウンの開始処理
function ShutdownGoProc ( ) {
    #シャットダウン信号を検出したメッセージを表示
    echo "  ! Shutdown signal detected. ${MESSAGE}"

    #シャットダウン処理を開始
    if [ ! "$MODE_TEST" = 1 ]; then
        #瞬停防止のため2秒だけshutdownを待つ(-t 2)
        /sbin/shutdown -P -t 2
    fi
}

#シャットダウンの停止処理
function ShutdownStopProc ( ) {
    #シャットダウン信号を検出したメッセージを表示
    echo "  + Shutdown signal disappeared. ${MESSAGE}"

    #シャットダウン処理を中止
    if [ ! "$MODE_TEST" = 1 ]; then
        /sbin/shutdown -c
    fi

    #すぐにループ処理に戻らないよう、ウェイト
    sleep 1
}


#----------------------------------
#メイン処理
#----------------------------------

#実行中ユーザをチェック
if [ `/usr/bin/id -u` != "0" ]; then
    #rootでなければ異常終了
    echo " ! Please run as root."
    exit 1
fi

#主要コマンドの存在をチェック
if [ ! -x /usr/bin/gpio ]; then
    #見つからなければ異常終了
    echo " ! No 'gpio' Command."
    exit 1
fi

#自身のコマンド名を変数に入れる。usage用
CMDNAME=`basename $0`

#引数のチェックと動作フラグの生成
#https://shellscript.sunone.me/parameter.html
while getopts vt OPT
do
    case $OPT in
        "v" )
            #verboseモード
            MODE_VERBOSE=1 ;;
        "t" )
            #テストモード(シャットダウンはしない)
            MODE_TEST=1 ;;
        * )
            #それ以外の指定は、usageを表示
            echo "Usage: $CMDNAME [-v] [-t]" 1>&2
            exit 1 ;;
    esac
done

#動作モードのメッセージ
if [ ${SET_TRIGGER} -eq 1 ]; then
MESSAGE="(MODE: Down trigger)"
else
MESSAGE="(MODE: Up trigger)"
fi

#起動メッセージ
if [ "$MODE_VERBOSE" = 1 ]; then

  #メッセージ
  echo " * Monitor the GPIO signal and shutdown * ${MESSAGE}"

  #テストモードのメッセージ表示
  if [ "$MODE_TEST" = 1 ]; then
    echo '  - test mode (no shutdown)'
  fi
fi

#ポートの初期化
`/usr/bin/gpio -g mode ${SET_WATCH_PORT} in`

#監視ポートの状態変数の初期化と問い合わせ
STAT_PORT_PREV=`/usr/bin/gpio -g read ${SET_WATCH_PORT}`

#監視ループ
while :
do
    #監視ポートの状態を問い合わせ
    STAT_PORT_NOW=`/usr/bin/gpio -g read ${SET_WATCH_PORT}`

    if [ ${SET_TRIGGER} -eq 1 -a ${STAT_PORT_PREV} = "1"  -a  ${STAT_PORT_NOW} = "0" ]; then
        #ダウントリガで検知
        ShutdownGoProc
    elif [ ${SET_TRIGGER} -eq 0 -a ${STAT_PORT_PREV} = "0"  -a  ${STAT_PORT_NOW} = "1" ]; then
        #アップトリガで検知
        ShutdownGoProc 

    elif [ ${SET_TRIGGER} -eq 1 -a ${STAT_PORT_PREV} = "0"  -a  ${STAT_PORT_NOW} = "1" ]; then
        #アップトリガで検知
        ShutdownStopProc
    elif [ ${SET_TRIGGER} -eq 0 -a ${STAT_PORT_PREV} = "1"  -a  ${STAT_PORT_NOW} = "0" ]; then
        #ダウントリガで検知
        ShutdownStopProc 
    fi

    #監視ポートの状態変数に、現在の状態を代入
    STAT_PORT_PREV=${STAT_PORT_NOW}

    #ウェイト
    sleep ${SET_WATCH_INTERVAL}
done

exit 0

##(3)systemdに登録するserviceファイル

setPowerWatcher.service
[Unit]
Description=Monitor the GPIO signal and shutdown
After=local-fs.target
ConditionPathExists=/home/pi/[INSTALL DIR]

[Service]
ExecStart=/home/pi/[INSTALL DIR]/setPowerWatcher.sh
ExecStop=/bin/kill ${MAINPID}
Restart=on-failure
StartLimitInterval=60
StartLimitBurst=3
KillMode=mixed
Type=simple
User=root
Group=root

[Install]
WantedBy=multi-user.target

##(4)配線

前述(3)のプログラムにならって、GPIO4にリセットボタンを繋ぎます。

配線例

#2.セットアップ手順

##(1)systemdへ登録
systemdに登録して、サービスを起動します。

コマンドライン
$ sudo ln -s /home/pi/[INSTALL DIR]/setPowerWatcher.service /etc/systemd/system
$ sudo systemctl enable /home/pi/[INSTALL DIR]/setPowerWatcher.service

##(2)serviceファイルを修正した時

下記のリロード操作をします。

コマンドライン
$ sudo systemctl daemon-reload

##(3)状態を確認

systemctl statusコマンドで、状態を確認します。
まだ起動していません

コマンドライン
$ systemctl status setPowerWatcher.service
● setPowerWatcher.service - Monitor the GPIO signal and shutdown
   Loaded: loaded (/home/pi/[INSTALL DIR]/setPowerWatcher.service; linked; vendor preset: enabled)
   Active: inactive (dead)

##(4)起動

コマンドライン
$ sudo systemctl start setPowerWatcher.service

##(5)状態を確認

左上の●が緑色になっていれば、正常に起動しています。

コマンドライン
$ systemctl status setPowerWatcher.service
● setPowerWatcher.service - Monitor the GPIO signal and shutdown
   Loaded: loaded (/home/pi/[INSTALL DIR]/setPowerWatcher.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2019-03-09 15:47:22 JST; 9s ago
 Main PID: 537 (setPowerWatcher)
   CGroup: /system.slice/setPowerWatcher.service
           tq537 /bin/bash /home/pi/[INSTALL DIR]/setPowerWatcher.sh
           mq564 sleep 1

Mar 09 15:47:22 raspizwh systemd[1]: Started Monitor the GPIO signal and shutdown.

##(6)動作確認

GPIOに信号を入れると、間もなくシャットダウンします
その際syslogには、下記のメッセージが残ります。

コマンドライン
Mar  9 15:58:13 raspizwh setPowerWatcher.sh[537]:   ! Shutdown signal detected. (MODE: Down trigger)

#おわりに

こんな感じで、外部信号からシャットダウンできるようになりました。
ご参考頂けると幸いです。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?