The Fool In The Valleyの雑記帳

-- 好奇心いっぱいのおじいちゃんが綴るよしなし事 --

Raspberry Piのプログラム自動実行とシャットダウン

Raspberry Piは基本的には電源として5VをUSBで供給し、キーボード/マウス、ディスプレイを接続して使うように作られています。電源を繋ぐと自動的にOSが立ち上がり起動後に下のようなデスクトップが表示されるので、GUIを使ってアプリケーションを選択して実行することができます。また、シャットダウンするときにもGUIを使ってログアウトを選択し、安全に停止させることができます。

起動後に現れるデスクトップ

しかし、Raspberry PiのGPIOを使って専用の制御システム構築し、それを屋外で使用する場合には、5Vを供給するモバイルバッテリーは必須ですが、キーボード/マウス、ディスプレイは接続しない状態で使うことになります。その場合にはGUIが使えないので、アプリケーションの起動やシステムのシャットダウンについては別の方法を用意する必要があります。
本記事は、その方法の一つを備忘のために記録したのものです。

【プログラムの起動】

実行したいのがPythonプログラムの実行だとすると、OSが起動した後に自動で ”python3 (実行したいPythonファイル)” というコマンドを実行するようにしておけば十分です。
Raspberry PiのOSであるRaspbianは基本的にLinuxなので、自動起動の設定は /etc/systemd/system
のなかで行ないます。
そこにtarget.serviceというファイルを作り、以下のように起動したいサービスの設定ファイルを登録します。

pi@raspberrypi:/etc/systemd/system $ cat target.service
[Unit]
Description=Run target application automatically

[Service]
ExecStart=/usr/bin/python3 /home/pi/Development/PythonProgram/SCCS.py

[Install]
WantedBy=multi-user.target

ここで、
Description:起動後に実行したい内容の記述
ExecStart:実行するコマンドライン  (絶対パスで記述)
です。
サービスの設定ファイルができたら、サービス起動デーモンsystemdをコントロールするコマンドsystemctlを使って、サービス起動、サービスステータス表示ができます。

pi@raspberrypi:/etc/systemd/system $ sudo systemctl start target.service
pi@raspberrypi:/etc/systemd/system $ sudo systemctl status target.service
● target.service - Run target application automatically
     Loaded: loaded (/etc/systemd/system/target.service; disabled; vendor prese>
     Active: active (running) since Wed 2022-12-07 16:59:43 JST; 16s ago
   Main PID: 1936 (python3)
      Tasks: 1 (limit: 4165)
        CPU: 869ms
     CGroup: /system.slice/target.service
             └─1936 /usr/bin/python3 /home/pi/Development/PythonProgram/SCCS.py

1207 16:59:43 raspberrypi systemd[1]: Started Run target application automat>
lines 1-10/10 (END)

起動時に実行させるためには、次のコマンドでセットします。

pi@raspberrypi:/etc/systemd/system $ sudo systemctl enable target.service
Created symlink /etc/systemd/system/multi-user.target.wants/target.service → /etc/systemd/system/target.service.

この後、一度シャットダウンして起動させると、目的の /home/pi/Development/PythonProgram/SCCS.pyというPythonプログラムが自動敵に実行されます。
無限ループでずっと実行されているプログラムであれば、その様子は下のように確認できます。

pi@raspberrypi:~ $ ps aux | grep SCCS.py
root         501  5.5  0.2  14248  9840 ?        Ds   22:47   0:35 /usr/bin/python3 /home/pi/Development/PythonProgram/SCCS.py
pi          1683  0.0  0.0   4228   656 pts/0    S+   22:58   0:00 grep --color=auto SCCS.py

プロセスID 501として /usr/bin/python3 /home/pi/Development/PythonProgram/SCCS.py が実行されているのが分かります。
それを停止させるには、下のようにします。

pi@raspberrypi:~ $ sudo kill 501
pi@raspberrypi:~ $ ps aux | grep SCCS.py
pi          1708  0.0  0.0   4228   676 pts/0    S+   23:04   0:00 grep --color=auto SCCS.py
【シャットダウン】

Raspberry Piには、GPIOピンを使ってShutdownする機能が備えられており、それは /boot/config.txt で定義することによって使うことができます。
それについては /boot/overlays/README の中で下記のように書かれています。

Name:   gpio-shutdown
Info:   Initiates a shutdown when GPIO pin changes. The given GPIO pin
        is configured as an input key that generates KEY_POWER events.

        This event is handled by systemd-logind by initiating a
        shutdown. Systemd versions older than 225 need an udev rule
        enable listening to the input device:

                ACTION!="REMOVE", SUBSYSTEM=="input", KERNEL=="event*", \
                        SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", \
                        ATTRS{keys}=="116", TAG+="power-switch"

        Alternatively this event can be handled also on systems without
        systemd, just by traditional SysV init daemon. KEY_POWER event
        (keycode 116) needs to be mapped to KeyboardSignal on console
        and then kb::kbrequest inittab action which is triggered by
        KeyboardSignal from console can be configured to issue system
        shutdown. Steps for this configuration are:

            Add following lines to the /etc/console-setup/remap.inc file:

                # Key Power as special keypress
                keycode 116 = KeyboardSignal

            Then add following lines to /etc/inittab file:

                # Action on special keypress (Key Power)
                kb::kbrequest:/sbin/shutdown -t1 -a -h -P now

            And finally reload configuration by calling following commands:

                # dpkg-reconfigure console-setup
                # service console-setup reload
                # init q

        This overlay only handles shutdown. After shutdown, the system
        can be powered up again by driving GPIO3 low. The default
        configuration uses GPIO3 with a pullup, so if you connect a
        button between GPIO3 and GND (pin 5 and 6 on the 40-pin header),
        you get a shutdown and power-up button. Please note that
        Raspberry Pi 1 Model B rev 1 uses GPIO1 instead of GPIO3.
Load:   dtoverlay=gpio-shutdown,<param>=<val>
Params: gpio_pin                GPIO pin to trigger on (default 3)
                                For Raspberry Pi 1 Model B rev 1 set this
                                explicitly to value 1, e.g.:

                                    dtoverlay=gpio-shutdown,gpio_pin=1

        active_low              When this is 1 (active low), a falling
                                edge generates a key down event and a
                                rising edge generates a key up event.
                                When this is 0 (active high), this is
                                reversed. The default is 1 (active low).

        gpio_pull               Desired pull-up/down state (off, down, up)
                                Default is "up".

                                Note that the default pin (GPIO3) has an
                                external pullup. Same applies for GPIO1
                                on Raspberry Pi 1 Model B rev 1.

        debounce                Specify the debounce interval in milliseconds
                                (default 100)

そこで、GPIO4のピンとGndの間にタクトスイッチを繋ぎ、それを2秒以上押したときにシャットダウンされるようにするためには、/boot/config.txt にroot権限で下のような一行を書き込みます。

dtoverlay=gpio-shutdown,gpio_pin=4,debounce=2000

その後、一度シャットダウンして再起動させた後は、/boot/config.txt でGPIOを使ったシャットダウンが設定されるので、 GPIO 4ピンとGndの間のスイッチを2秒以上押すことにより、安全にシャットダウンされます。Raspberry Piの緑のLEDはSDへのアクセスを示しているので、その点滅がしばらく続いた後に消灯し、安定した状態になればシャットダウン完了と判断できます。
シャットダウンでは電源はオフにならないので、赤のLEDは点いたままです。この状態から電源をオフするためには5Vを供給してるUSBのコネクタを抜く必要があります。また、再起動するためにはUSBのコネクタを挿し直す必要があります。