お父にゃんの電子工作 -14ページ目

お父にゃんの電子工作

暇なおじさんが、電子工作(主にラジオ製作)をして勝手な感想を書く

Raspberry PiでWebラジオのソフトウェアが何となく出来てきたので、そろそろパネルに固定してスタンドアロンのWebラジオに仕立てていこうと思っている。

スタンドアロンで動かすにあたって、問題になるのが、「どのように安全に電源を切るか」

なのである。

 

いきなり電源を切ると、以下のような不具合が有る、とChatGPTは言うのである。

 

① SDカードのファイル破損
Raspberry Pi の OS(Raspberry Pi OSなど)は Linux なので、内部で常にログやキャッュ、設定ファイルなどを書き込んでいます。
電源をいきなり切ると、書き込み中のデータが途中で途切れてしまい、
 ・OSのファイルシステム(ext4)の整合性が壊れる
 ・/home/pi/ などにあるデータファイルが破損する
最悪の場合、次回起動時にブートしなくなる(カーネルパニックや復旧モード)
といった症状が起こります。

② 長期的にはSDカードの寿命を縮める
書き込み途中で電源断が繰り返されると、SDカードのフラッシュメモリ内の管理情報が不整合になり、寿命が短くなります。

 
補足:SDカードの構成(通常のRaspberry Pi OSの場合)
SDカードをパソコンで見ると、最初の小さなパーティション(約256MB)は「boot」ですが、実際にはこうなっています:
パーティション ファイルシステム 内容
/boot FAT32 起動用ファイル(kernel、config.txt、cmdline.txtなど)
/ (ルート) ext4 OS本体・アプリ・ログ・ユーザーデータなどすべて
ext4はジャーナリングファイルシステムで、一応電源断に強い設計ですが、
 ・書き込み途中で電源が落ちる
 ・キャッシュがフラッシュされていない
といった状態だと、ファイルやディレクトリ構造が不整合を起こすことがあります。
最悪の場合、
「起動しなくなる」
「ファイルが消える・壊れる」
ということが起こります。
 
と言うのである。
なので、雑に扱っても安全に電源を落とせる(シャットダウン処理が完了してから電源が落ちる)ように考えないといけないのである。
 
 
じゃぁ、具体的にどうするか?
例えば、以下のプログラムを走らせて、GPIOでスイッチの状態を監視して、スイッチonでシャットダウンコマンドを実行させる、と良いらしい。
import RPi.GPIO as GPIO
import os
import time
 
BUTTON_PIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
 
try:
    while True:
        if GPIO.input(BUTTON_PIN) == GPIO.LOW:
            print("シャットダウンします...")
            os.system("sudo shutdown -h now")
            time.sleep(1)
        time.sleep(0.1)
except KeyboardInterrupt:
    GPIO.cleanup()
 
シャットダウンした後に信号を変化させるには、gpio-poweroff という仕組みを使うと良いらしい。これを /boot/firmware/config.txt に設定すると、シャットダウン(halt/poweroff)時に指定ピンをソフトウェア的に HIGH/LOW に駆動してくれるらしい。
 
・config.txtを編集
  sudo nano /boot/firmware/config.txt
・最後に追記:   GPIO26をシャットダウン後にLowに設定
  dtoverlay=gpio-poweroff,gpiopin=26,active_low=1
 
以上を基に、電源制御回路を描いてみる。
トグルSWの状態をソフトで監視出来るようにして、シャットダウンを開始。GPIO26をpower off信号に使って、トグルSW OFF後、シャットダウン処理終了後にFTTがoffする。
ちなみに2SJ334を使った理由は、ON抵抗が約50mΩと低く、Vgsが-3Vで確実にonに出来るため。ただ、amazonで3個で850円と、ややお高い。探せばもっと安いものが見つかると思う。
 
暫定回路図

Raspberry Pi側: shut_down、Power off信号追加
 
次に、このコードをWebラジオのコードに追加して、シャットダウンできるか確認する。
GPIO17をshut_down_signalとして使用。
(この関数は定期的に呼び出し)
#==== シャットダウン要求チェック ===~
def power_off_check():
    if GPIO.input(shut_down_signal) == GPIO.LOW:
        print("シャットダウンします...")
        draw.rectangle((0, 0, 320, 240), fill="black")  #/display clear
        draw.text((0, 50), "シャットダウン中", font=font28, fill="white")
        draw.text((0, 100), "電源を抜かないでください", font=font24, fill="white")
        device.display(image)
        os.system("sudo shutdown -h now")
        time.sleep(1)
 
GPIO17を試しにGNDに繋いでみると、このように表示した後にシャットダウンする。
GPIO26の挙動を見ると、config.txt修正前は電源投入後はGPIO26はLow(プルダウン状態)だったが、修正後はHighになり、シャットダウン後にLow(プルダウン状態)になる事が分かった。
これで、ちゃんと動きそうだ。
 
実際に仮配線して試してみる。
電源SW(左下トグルSW)をONにすると、電源が入る。次にWebラジオソフトを起動させる。
 
電源SWをOFFにすると、シャットダウン開始
 
シャットダウン開始から約10秒程度で自動的に電源OFF
(GUIが立ち上がってなければ2~3秒で電源off)
思った通りに動作した。
 
ついでに、電源を入れれば、Webラジオとして自動でPythonプログラムが立ち上がるようにする。
 
①/etc/rc.localを編集(または新規作成)
 sudo nano /etc/rc.local
 
②PythonのWebラジオプログラムを起動するように、以下のように記述
   python3 /home/nya/Documents/Web_Radio_V0_33.py  &
 exit 0
 
 注)ファイルの場所、ファイル名等は、環境に応じて変更、 最後に&を入れておく
    &:プログラムをバックグラウンドで実行(起動処理をブロックしない)
   Pythonプログラムをバックグラウンドにせずに起動すると、
   そのプロセスが終了するまで rc.local 全体が待ち続けてしまい、
   システムの起動が完了しなくなる(ブートが止まる)ことがあるらしい。

③実行権限を付与
 sudo chmod +x /etc/rc.local

④systemd に rc-local サービスを有効化
 sudo systemctl enable rc-local

⑤手動テスト(エラー確認)
 sudo /etc/rc.local
 これでエラーが無ければOK
 
試してみると、電源を入れてしばらくすると、Webラジオプログラムが動き出す。
ちなみに電源onから音が鳴るまで40秒くらいかかる。
OSの起動だけで30秒くらいかかるので、まぁ仕方無い。
 
これでとりあえず、電源を入れれば勝手にWebラジオが立ち上がり、電源を切れば安全に電源が落ちるようになった。
 
簡単な仕組みだけど、ちゃんと動くと、なんかうれしいのである。
 
参考までに今回のプログラムを以下に置いておきます
そこそこちゃんと動くが、まだ少し動きが怪しいところが有るので、ちゃんとしたものが欲しい方は完成まで、もうしばらくお待ちを。
 
 
「そんなことくらいで喜んでるようじゃダメにゃ」
 
 

----------- 補足----------

なお、今回のコードを動かす前に以下作業も必要

●液晶を動かすためにLuma.lcdのインストール
sudo apt update

sudo apt install python3-luma.lcd python3-pil

●日本語対応フォントがインストールされていないので、noto-cjkをインストール。
sudo apt install fonts-noto-cjk

● rpi-lgpioにアップデート
sudo apt remove python3-rpi.gpio
sudo apt install python3-rpi-lgpio 

● I2Sドライバを有効化
sudo nano /boot/firmware/config.txt

ファイルを開いたら以下を追加: 
# PCM5102 用 I2S 設定
dtparam=i2s=on
dtoverlay=hifiberry-dac

 

●pigpioを自動起動に

電源投入時に自動で起動するように設定

sudo systemctl enable pigpiod
sudo systemctl start pigpiod


●pigpioがPCM用タイマを使っているので、PWMタイマーを使う設定にする
sudo mkdir -p /etc/systemd/system/pigpiod.service.d
sudo nano /etc/systemd/system/pigpiod.service.d/override.conf
エディタが開いたら以下を記入
[Service]
ExecStart=
ExecStart=/usr/bin/pigpiod -t 0 -l

保存してリブート 

 

●Webラジオの再生ソフトのmpvをインストール

sudo apt install mpv