ラズベリーパイのハードウェアWDT   
                                                 2020年 1月
【ラズパイがハングアップする】
 ラズベリーパイを長期運用していると、電源は入っているのに全く応答しなくなる事があります。こうなると電源を落とすしか方法がなく、一旦電源を落とし、再度投入すると普通に動作を開始します。近くで運用している時は良いのですが、離れたところで運用している場合は、全くの困りものです。
 一般的にマイコンにはWDT(Watchdog Timer)という機構があり、何らかの原因で暴走した場合にはそのことを検知して再起動するという仕組みが備わっています。もちろんそれを適用しないと働きませんが・・・。それでラズベリーパイにも、その仕組があるはずだと思いネットでの検索をしました。有りました、 ここに 詳しく解説されています。ありがとうございます。さっそくこれを参照させていただいて設定しました。その中に解説されているように、動作確認のための「フォークボム(Fork爆弾)」を撃ってみますと、確かに再起動します。
 これで一安心と思い一ヶ月ほど運用したところ、またハングアップが起きてしまいました。う〜ん、これは何なんでしょう??? 電源の容量も不足ではないようですし、理由はわかりません。ただハッキリしていることは、たとえこれが発生した場合であっても、「一旦電源を落とし、再度投入する」を行えば復調して再び長期にわたって運用することはできているということです。
 そこで、ラズベリーパイが持っている WDT だけに頼らない、別のやり方の
追加を考えて見ました。つまりラズベリーパイのあるポート(GPIO)に「パルスを一定周期で出力」するソフトをラズベリーパイの側に入れて常時起動して置き、そのパルスをこれから追加する外部の基板で監視して、検出できなくなったら、その基板でラズベリーパイの電源を落とし、しばらく時間をおいて電源を再投入するという、これまで手作業でやってきたことを代わって実行してくれる小基板を作製してみることにしました。以下は、その報告です。現在のところ、上記しましたラズベリーパイ自身によるものと、この外部基板によるものの二重の対策になっていますが、とてもウマク動作し、安定して運用できています。この実装済(マイコン書き込み済)の基板がご入用でしたら、「ラズベリーパイWDT基板」とご記入の上、汎用製品通販のページのトップのメールアドレスへお申し込みください。郵送料込みで 2,000円で承ります。なお、パルス発生の監視とともに、ルーターへの ping テストを行い、ネットワークが不調になった場合の監視も追加いたしました。

[ Contents ]
1. 小基板の回路と実装図
2. 小基板のファームウェア
3. フローチャート
4. ラズベリーパイ側のソフトと設定
. 動作確認
  Appendix (入力の表示)


1. 小基板の回路と実装図
マイコンは、マイクロチップのPIC12F1612を搭載しています。電源は、ラズベリーパイの電源入力と同サイズのマイクロUSBのコネクタを付けていますので、それまでラズベリーパイに供給していたものをこの基板にさしてください。ラズベリーパイの電源は、この基板を通して、GPIOの2, 4番ピン(+5V)、6, 9, 14番ピン(GND)から供給します。ですから、
ラズベリーパイの元の電源は未接続にします。CN1 と CN2 は基板の裏に付いているメスのコネクタですから、ラズベリーパイのGPIOピンの1〜16ピンに刺さります。つまり、ここから電源はラズベリーパイに供給れます。CN3 と CN4 は基板の表にオスのコネクタで実装されており、CN1 と CN2 にパラに接続されていますので、ラズベリーパイの1〜16ピンの代替になります。なお、どの GPIO にラズベリーパイのパルスを出力するかを S1〜S5 で選択しますので、半田でショートしてください。ここでは、S3 の IO22 を使用しています。なお、この小基板は、ラズベリーパイの外側に取り付ける様に設計しています。もし、外側に取り付けることがケースなどで難しい場合は、+5V, GND, パルス入力 の3本だけをリード線で出して、ラズベリーパイのコネクタの該当位置に接続することでも良いです。回路図をクリックすると大きめに表示されます。



  実装図(サイズ 48 x 23 mm)


2. 小基板のファームウェア
マイクロチップ様の MPLAB-X-IDE において CCS-C でコンパイルしています。タイマーは、SMT1 のタイマーモードを使っており、内容的にはシンプルですので、マイクロチップ様のコンパイラ(XC8)にもすぐに移植できると思います。リストは以下の通りです。

リスト RaspPi_Wdt7


下図が、プロジェクトの様子です。コンパイルして書き込んでください。こちらの基板を使えば CN-PROG から書き込むことができます。




3. フローチャート
 上の PIC のファームウェアのフローチャートを下図に示します。@ 「電源投入から、ラズベリーパイが送っているパルスの初期検出」の部分。次に A 「常時の運用中のパルスの送出を検証」する 部分。最後に B 「パルスが検出できなくなった時に電源を切断」する 部分の3つのパートから構成されています。@->A->B->@->A のようにループします。ラズベリーパイにパルスを送出するソフトを組み込んでいない場合は、最初の@の中でループしますので、電源は入ったままとなり、そのままラズベリーパイは通常通り使用できます。ここでは、パルスは 0.5秒ON、0.5秒OFF の連続を想定しています。この ON/OFF が5秒以内に来ないと電源OFF のモードに入りますから、それに間に合うようにラズベリーパイからパルスを送出するようにしてください。
また、パルス幅は関数 int ChkInPin(int32 BIT, short OFON) の中で、20ms 以上と設定していますのでそのようにして下さい。もし変更が必要であれば、ソースから変更してください。


4. ラズベリーパイ側のソフトと設定
 GPIOに連続パルスを出力する Python によるサンプルを示します。この中には、今回のパルス発生以外に、SWでシャットダウンするための部分もいれていますが、不要であれば削除してください。これは元々SWでラズベリーパイをシャットダウンするために作成していたものに、今回の連続パルス出力部を追加したものです。
 シャットダウンSWは GPIO17(Pin11:ここがHighになるとAvtiveになる)に、パルス出力は GPIO22(Pin15) に割り当てています。コードを見ていただければ分かると思いますが、パルスは 0.5秒 ON/ 0.5秒OFFの繰り返しであり、ほとんどは sleep(0.5) の実行ですので、他の処理の支障になることはないと思います。(ネットワーク監視項目の追加をしています、下に記入している
追加しました
を見てください)
注意!:文字コードは UTF-8 で保存しなければラズパイで動かす時にエラーとなります。
      ラズパイ側のテキストファイルは UTF-8 でなければなりません。

リスト shutdown_Wdt.py


この shutdown_Wdt.py をラズベリーパイ 起動時に稼働するように /etc/rc.local ファイルに記述してください。
ここでは nanoエディタで以下のように起動しています。
sudo nano /etc/rc.local

23行がそのパルス送出・シャットダウン操作のための設定です。
21, 22行は、その他の設定のサンプルですので、必要な設定に書き換えてください。
内容は同じではないと思いますが、要するに exit 0 の前に
「python /home/pi/shutdown_Wdt.py &」 が記述されていれば良いです。もちろんこの場合は、shutdown_Wdt.py は /home/pi/ の場所に 保存してください。場所は任意ですのでご自分の好きな場所で良いです。


1 #!/bin/sh -e
2 #
3 # rc.local
4 #
5 # This script is executed at the end of each multiuser runlevel.
6 # Make sure that the script will "exit 0" on success or any other
7 # value on error.
8 #
9 # In order to enable or disable this script just change the execution
10 # bits.
11 #
12 # By default this script does nothing.
13
14 # Print the IP address
15 _IP=$(hostname -I) || true
16 if [ "$_IP" ]; then
17 printf "My IP address is %s\n" "$_IP"
18 fi
19
20 # for Start file
21 sudo systemctl start webiopi
22 sh /home/pi/xxxxxx-stream.sh
23
python /home/pi/shutdown_Wdt.py &
24
25 exit 0

下の図は、ラズベリーパイが送出している信号 (GPIO Pin15) を観測したものです。

 ラズベリーパイからの信号

【 追加しました
 ラズパイに支障が起こった時の症状は色々とあると思います。メインのアプリケーションの動作がおかしくなっても、ラズパイ固有のWDTに引っかかることもなかったり、この監視用のパルスの発生にも問題なかったりすることもあるかもしれません。それで、チェック項目の追加をしました。
 それは、自分のルーター(192.168.1.1) に ping を打って、"1 received" という応答が含まれているかを 10分間に1回実行し、全トライ5回の内に1回でも返ってくれば何もしない、もし返らなければ shwfg フラグを 1 として、監視用のパルスの発生を停止する、という処理を入れました。これで重要項目であるネットワークの監視もできると思います。もちろんこの項目は、ネットワークを使っている場合のみですので、使っていない場合は、cnt += 1 をレム(頭に#を記入)にしてください。私のルーターのアドレスは、192.168.1.1 ですが、これはそれぞれ違うと思いますので、shutdown_Wdt.py の行 ・・・
shutdown_Wdt.py の cmd = 'ping 192.168.1.1 -c 1'  #ルーターにping
・・・ これに含まれるルーターのアドレスをお使いのアドレスにご変更ください。


5. 動作確認
 下の写真は運用している例です、こちらでは実際には、カメラ付きの遠隔地ビデオモニターに取り付けています。これはテストのための構成です。左の方は、コネクタが挿せる状態の時で、この場合は別途配線は必要ありません。右の方は、ケースの構造で直接コネクタを挿せない時の例で、その場合は電源(+5V, GND) とラズベリーパイから受け取る信号の線の3本を接続して下さい。ラズベリーパイの GPIO の初めの 16ピンと、この基板の 16ピンは同じ配列ですので、ケース構造で挿すことができる場合は左のようにそのまま挿せます。挿せない場合は、写真のように、赤(+5V) は 4番ピン、茶(GND) は 6番ピン、橙(信号) は 15番ピンに接続しています。配線は極力短い方が良いです。
 ラズベリーパイが立ち上がって動作している時に、右の接続をしていれば、橙色の線(信号)を外すと信号が検出できない状態となり、約5秒後に基板の LED が点灯して電源OFF となります。それから約30秒間 OFF が続き、その後再起動のため電源ON となります。これで、この
基板の動作確認ができます。4.(上記)の「ラズベリーパイ側のソフトと設定」をしていない場合は、フローチャートの@で待機になるので電源は入ったままとなり、普通にラズベリーパイは使用できます。



 これをラズベリーパイに取り付けることによって遠隔地に設置しているビデオモニターを安定して稼働させることができるようになりました。結局、
最初に述べた対策もそのまま使っていますので、二重の対策をしていることになります。

追記
 遠隔地ビデオモニターとは別に、「Raspberry Pi Zero WH」を使って連続でインターネットラジオを再生しているのですが、それがハングアップしました。これにはもちろん最初に述べたラズベリーパイが持っている対策を入れており、「フォークボム(Fork爆弾)」での確認もとっておりました。まったく音が出なくなっていたので「リモートデスクトップ」の接続を試みましたが、これも接続できませんし、ping も通りません。それでも電源を入れ直しましたら問題なく動作を再開しました。ラズベリーパイが立ち上がり、ラジオが再生された時に、再確認のため、もう一度フォークボム(
:(){ :|:& };:)を撃つとキチンと再起動します。そういうことなので、遠隔地ではないのですが、このインターネットラジオにも、このWDT基板を取り付けることにいたしました。

【Appendix】

 この WDT基板にはハードウェアとしては含めていませんが、実は PIC の 7番ピンに Reportの出力(この基板が再起動を実行したことを示す)を On/Off で示すようにしています。この PIC のポートに LED を追加すれば、この基板がラズパイの再起動を実行した時は LED が点滅します。また、6番ピンを入力(内蔵PullUpしている)にしており、ここを GND に落とせば RS232C(19200bps:6番ピン, TX)で、その再起動を実行した回数を見ることもできるようにしています。上記のファームウェアに、これらは既に入れております。
 さらに、7番ピン(Report)の出力(5V-GND)を、そのままでは電源レベルが違うため直接には GPIOに入れられないため、 7Pin-10KΩ-20KΩ-GND を接続し、抵抗の中点を
GPIO(INに設定)に入れました。この入力の状況をブラウザに表示するようにすれば、遠隔地よりラズベリーパイの再起動があったかどうかを知ることができるわけです。GPIO(OUT) をブラウザから操作する方法についてはネット上に多くの例があるのですが、GPIO(IN) の入力をブラウザに表示する方法について、WebIOPi が提供している関数のみで行っている例が見つからず手間取りました。
 WebIOPi 提供先のメインメニューの GPIO Header (http://192.168.x.xx:8000/app/gpio-header) では表示されているので方法はあるはずです。試行錯誤の結果、以下の方法でブラウザの画面に表示できるようになりました。要は、
OUT も IN も同じ Button を使っており、OUT に設定するか IN に設定するかでその動作が変わってくるということです。IN に設定した場合の表示は、ポートの High/Low を反映し、クリックは無視されます。また、入力をボタンに表示できるようにはなった当初、入力(GPIO) を High/Low しても表示は変化しなかったのですが、それに IOPI.refreshGPIO(true); を追加することで変化・応答するようになりました。

リスト index.html


下図の写真は、実際に使っている遠隔地ビデオモニターの例で、皆様の環境とは違うと思いますが、
要はWebIOPiを使っている以下の記述に注目してください。
;--- Java Script ---
IOPI.setFunction(25, "IN");
var WarnBtn = IOPI.createGPIOButton(25, "報告");
$("#warnbtn").append(WarnBtn);
IOPI.refreshGPIO(true);
;--- Body ブロック ---
<div id="warnbtn"></div>

ブラウザ表示の例 (一部)


 この「遠隔地ビデオモニター」は、金丸隆志氏の「実例で学ぶ Raspberry Pi 電子工作」の第6章を使用させていただいております。オリジナルのコードに、ボタン操作・表示部(報告)を追加いたしました。さらに、外部のネットワークからアクセスできるように、「MyDNS」に登録し、グローバルアドレスを取得(ありがとうございます)し、遠隔地からモニターできるようにいたしました。これは後閑哲也氏の「PICと楽しむRaspberry Pi」の第7章を参照させていただきました。
 上図の表示の「照明」が OUT で、現在の表示は点灯している状態です。「報告」は IN で、現在は Low の状態です。なお照明には、商用電源(AC100V)を使っており、秋月電子通商さんの
ソリッド・ステート・リレーキットを使っています。
 最後に、どれくらいの期間でこのハードウェアWDT による再起動が起こっているかを報告します。この「遠隔地ビデオモニター」で使っているものは「Raspberry Pi 2 Model B」です。これまでも、何回かハングアップは経験していますが、1〜6ヶ月など様々でした。このハードウェアWDT でのテストは、2020年1月20日にセッティングして、4月10日に「報告」の項目が点滅を開始しました。ですので約80日間の運用で再起動が確認された事になります。そのまま運用してもビデオモニターは動作しているので全く支障はないのですが、次の日に現場に行く用件がありましたので、「報告」をクリアして、次の再起動を確認できるようにするために再セットしました。また、再起動が起こりましたら追加の報告をします。再起動は、様々な状況によって変わるとは思いますが1つの参考になれば幸いです。


Reported by TokioYamada@ADK


汎用製品通販のページへ    ラズパイ Zero によるインターネットラジオへ    USB-IOのページへ