数日間カーファインダーの機能を運用してみて、致命的なバグを発見した。
特定の時間内でエンジンをかけ直すと、情報がクラウドに送られないというもの。
【原因】
現在、我が家のCX-8には以下の3つの電源系がある。
1) バッテリー電源(BAT電源)
2) アクセサリ電源(ACC電源)
3) タイマ付きバッテリー電源(BAT+電源)
BAT+電源は、ACC電源OFF後30分経過すると自動的にOFFになる電源で、
ドライブレコーダと情報取得系の機器(Raspberry Pi Zero W, GPS受信機,
LTEルータ)が繋がっている。
Raspberry Pi Zero W はACC電源OFF後、30分も動き続ける必要はないので、
ACC電源OFF後 5分経過したら、シャットダウンプロセスが走るようにしてある。
また、BAT+がOFFからONになった場合、Raspberry Pi Zero W は自動起動する。
なので、ACC電源OFF後、5分以上経過後かつ30分以内に再度エンジンを
かけ直した場合、HALT状態のRaspberry Pi Zero W が起動できない。
以下に状態遷移図を示す。赤で記載した遷移の検討が抜けていた。
【対策】
考えられる対策は以下の2つ。
1) Raspberry Pi Zero W でシャットダウンプロセスを走らせないようにする。
つまり、30分間 sync し続け、BAT+の電源が落ちるのに備える。
(上記状態遷移図のシャットダウンモードをなくす)
2) ACC電源ONをトリガに、Raspberry Pi Zero W を起動する仕組みを入れる。
(上記状態遷移図のシャットダウンモードから通常モードへの遷移を考える)
前者は実装が簡単だが、無駄にバッテリー電源を消費したくない。
5分くらいでOFFになる新しい電源系(BAT++?)を用意するのもちょっと面倒。
さらに、正常にシャットダウンさせないので、microSDカードへの影響も
心配である。
後者はRaspberry Pi Zero WのGPIO3(Pin5)をGNDに落とせば、シャットダウン
状態から
起動するらしいので、出来なくはなさそう。
しかし、GPIO3はI2C SCLとの兼用なので、起動後オープン
(ハイインピーダンス状態)にしてやる必要がある。
(後日、RUNランドがあることに気づき、Pin1をGNDに落とせばHALT状態から
復帰できることが判明。)
車への負担を考え、後者でいくことにした。
【設計】
ACC電源の立ち上がりでワンショットパルスを生成し、リレーを制御するか
オープンドレインの回路を作れば良い気がするけれども、アナログ回路の
定数を計算するのが面倒なので、余っているマイコン(PIC12F509)で制御することにした。
作りは単純で;
・マイコンはACC電源駆動
・GP0ピン:マイコン起動直後はGND出力、1秒後に入力(Hi-Z)
・GP1ピン:ステータスLED制御(起動直後は点灯、以降は1秒周期で点滅)
・GP2ピン:リセット状態用LED制御(起動直後は点灯、1秒後に消灯)
以下ソースコード。
// Reset controller (PIC12F509)
// Programmed by 雑技工房 (2018/2/22)
// version 1.0
//
// GP0 : Reset signal
// GP1 : Active Status LED
// GP2 : Reset LED
// GP3 : NC
// GP4 : NC
// GP5 : NC
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <pic12f509.h>
#define _XTAL_FREQ 4000000 // 動作周波数:4MHz
#pragma config CP = OFF // コードプロテクト:OFF
#pragma config OSC = IntRC // クロック:内部
#pragma config MCLRE = OFF // MCLR機能:OFF
#pragma config WDT = OFF // ウォッチドックタイマ:OFF
int main(void)
{
// OSCCAL値は0x3FF番地(Reset Vector)の下位8bit(MOVLW 0xXX)
// MPLABの場合はFile→Project Propaties→XC8 linker→
// Claibrate oscillatorのチェックボックスをONにすれば、
// プログラム内での設定は不要
//OSCCAL = 0xXX;
OPTION = 0xdf; // T0CKI無効
TRISGPIO = 0b00000000; // GP0~GP2:出力
GPIO = 0b00000110; // GP0:L, GP1:H, GP2:H
__delay_ms(1000);
TRISGPIO = 0b00000001; // GP0を入力(オープンコレクタ)に設定
GPIO = 0b00000010; // GP0:Z, GP1:H, GP2:L
while(1) { // Lチカ(GP1)
__delay_ms(1000);
GP1 ^= 1;
}
return (EXIT_SUCCESS);
}
回路図。
基板配置図。
【製作】
上記のソースコードをMPLAB X IDE v4.10 + XC8でビルドしてPIC12F509に
PICKit3で書き込み、回路図通りにユニバーサル基板上に作成。
部品代は200円くらい。
【取り付け】
車両本体への改修は無く、
・ACCから作った5V電源
・Raspberry Pi Zero WのRUNランドのPin1
・GND
に取り付けるだけ。
これで情報がクラウドに送られないというバグは解決。