Power on/Shutdown switch
Concept
1つのトグルスイッチでRaspberry Pi の電源をオン/オフしたい。スイッチをオンすると即時起動し、オフした場合は即時に電源を切断せずにshutdownコマンドが完了するのを待機する仕組みを作成しよう。電源を自己保持するためMOSFETを設けて電源スイッチとGPIO27のORをとりMOSFETをオンすることで実現する。
Structure
graph LR
user((User))
tgl[Toggle switch<br>On/Off]
out[GPIO<br>1/0]
soft((Software))
pwr[Power 5V]
user --> tgl
tgl --> or((OR))
soft --> out
out --> or
or --> tr[MOSFET switch]
pwr --> tr
tr --> Output
Hardware
回路は部品点数を最小限に次のように構成した。本構成は使用方法に制約があり、Q2がオンになる前にSW1を切られると即時電源オフとなる。私の用途では問題ない。
モデルを作成しLTspiceでシミュレーションする。
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となり電源切断が完了する。
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()
動作例
(準備中)