Raspberry Pi シャットダウンスイッチ

Shutdown switch

Concept

ハードウェアスイッチでRaspberry Pi の電源をオン/オフする。電源スイッチをオフしても即時に電源を切断せずにshutdownコマンドの実行完了を待機する仕組みを作成する。電源を自己保持するためMOSFETを設けて電源スイッチとGPIO27のORをとりMOSFETをオンすることで実現する。

graph LR
    user((User))
    tgl[Toggle switch]
    out[GPIO]
    soft((Software))
    user --> tgl
    tgl --> or((OR))
    soft --> out
    out --> or
    or --> tr[MOSFET switch]

Hardware

回路は部品点数を最小限に次のように構成した。本構成は使用方法に制約があり、Q2がオンになる前にSW1を切られると即時電源オフとなる。私の用途では問題ない。
Schematic

モデルを作成しLTspiceでシミュレーションする。
Simulation model

Symbol Description Behavior
V1 電源入力 ACアダプタやモバイルバッテリを接続する。 0.5s後に5.1V,9s後に0Vを出力
MOSFET 電源を遮断、接続するPchのMOSFET。
GPIO22 出力に設定し電源を自己保持する。
V3,SW1 GPIO22の状態を生成する 1s後に3.3V出力,2s後に出力OFFし50kΩでPulldown
Q1,R2,R3 MOSFETをオンさせるトランジスタ。
C2 シャットダウン処理を待つための遅延時間を作る。 時定数 220uF x 50.1kΩ//10k=1.8s
R5 Rasberry PiがReset状態のプルダウン抵抗。
R7 GPIO22をハイレベル出力設定にしたときにC3への突入電流を制限する。 33mA max
Toggle ユーザがアクセスする電源スイッチ。 0.5s後に上SWオン下オフ,1.3s後に上SWオフ下オン
GPIO27 プルアップ付き入力に設定し電源スイッチの状態を認識する。

Simulation result

電源スイッチ投入を模して0.5s時にV1を立上げV(out)が5Vに確立する。1s時にソフトウェアによりGPIO22が出力モードでハイレベルに固定される。1.8s時に電源スイッチがオフされるがGPIO22によりMOSFETはオンを維持する。電源スイッチのオフはGPIO27からソフトウェアへ伝達される。ソフトではshutdownコマンドが実行され3s時にGPIOが初期値に戻る。GPIO22から3.3Vが切断され50kΩプルダウンとなりC2が緩やかに放電される。7.8s時にトランジスタがオフとなりMOSFETもオフする。V(out)が0Vとなり電源切断が完了する。
Waveform

Software

System Serviceを登録する。
/etc/systemd/system/powersw.service
After=pigpiod.target はpigpio daemonが起動した後に実行する設定。
EnvironmentFile=/etc/sysconfig/powersw はライブラリpathを通すための設定。

[Unit]
Description=Power switch control
After=pigpiod.target

[Service]
Type=simple
EnvironmentFile=/etc/sysconfig/powersw
ExecStart=/home/pi/lib/powersw.py

[Install]
WantedBy=multi-user.target

python実行時ライブラリへpathを通す。
/etc/sysconfig/powersw

# for powersw
PYTHONPATH=/home/pi/lib

電源の自己保持と切断時のコマンド発行を行う。
/home/pi/lib/powersw.py
GPIO22を出力に設定してHレベルを出力する。
GPIO27は入力に設定してPull upをオン、Lレベルになったらshutdownを実行する。

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
power control
"""
import os, sys
import time
import pigpio

pi = pigpio.pi()

pi.set_mode(22, pigpio.OUTPUT)             # GPIO22 is output
pi.write(22, 1)                                        # GPIO22 is H, turn on MOSFET
pi.set_mode(27, pigpio.INPUT)                 # GPIO27 is input
pi.set_pull_up_down(27, pigpio.PUD_UP)   # GPIO27 pull up

# Toggle switch turn on
def int_req_halt(gpio, level, tick):
    time.sleep(0.2)             # [s]
    if pi.read(27) == 0:       # GPIO27 is L
        os.system('sudo shutdown -h now')      # shutdown command
        pi.stop()
        sys.exit()

pi.callback(27, pigpio.FALLING_EDGE, int_req_halt)   # GPIO27, H to L

while True:
    time.sleep(60.0) # [s]

pi.stop()

動作例

(準備中)

コメントを残す

メールアドレスが公開されることはありません。