時々ハングするIoT機器を再起動させるUSBアダプタを作った

tl;dr

  • GoogleHomeから操作できる家電リモコンが時々ハングして、使いたい時に限って使えないことがあったよ。電源を挿し直せば直るよ
  • CH217 はスイッチ機能がついたUSB電源保護ICだよ。2Aくらい流せるのでWiFi機器でもいけそうだよ。
  • このICのENを、CH32V003で制御して、12時間ごとに再起動させるアダプタを作ったよ。
  • Kicadファイルとファームウェアのコードは GitHub で公開しているよ。

よくある素行の悪いIoT機器を再起動したい

お家ではとあるIoT機器を使って、GoogleHomeやスマートフォンから家電を操作できるようにしています。 しかし、それは1ヶ月くらい使っていると時々ハングアップするのかアクセスできない状態になってしまい、いざという時に使えません。 これを、自動で電源オンオフする仕組みさえ作れば改善できるのにと思っていました。

USB電源保護ICのCH217にスイッチ機能があることに気づく

前の記事では、USB電源保護ICであるCH217を紹介しました。

74th.hateblo.jp

Ch217 Usb Current Limiting Power Distribution Switch Chip Adjustable Current Limiting Threshold 10pcs/lot - Integrated Circuits - AliExpress

https://www.aliexpress.com/i/1005005392218373.html

このCH217には、スイッチ機能があり、ENをLOWにしたときだけ、VOUTに出力される様になっています。 この機能を使えば、USB電源のオンオフが可能なことに気づきました。

いや、普通にMOS FETだけでもできると思うのですが、USBの5V電源を供給する機能も必要なので、このIC一つでちょうどよさそうに思ったのです。

USB Type-C Plugが秋月でも買えるようになった

スイッチアダプタの片方の端子が USB Type-C Plugになっていたら、そのまま機器に接続できて便利です。

最近秋月で、基板取り付け用のUSB Type-C Plugが販売されるようになりました。

akizukidenshi.com

これのストックを持っていました。こちらを使うことにしました。

はんだ付けをしてみたところ、妙に傘になっている部分があり、そこに差し込む様にはんだごてを当てる必要があり、簡単ではありませんでした。

ですが、Boothでも販売している自作のUSBソケットテスターを使うことで、正しく実装できているか確認しながらできたので、最終的には問題なくうまくいきました。

74th.booth.pm

タイマー機能のためだけにCH32V003を使う

タイマーの制御は、CH32V003を使うことにしました。CH32V003は、今や秋月で40円で買える格安マイコンです。私はこのマイコンを既に150個購入しているので、贅沢に組み込めます。

電源を3.3Vだけでなく5Vでも良いため、レギュレータなしで組み込むことが来ます。今回はレギュレータなしにUSB5Vを直結させていました。

ファームウェアはch32v003funを使って実装しました。ch32v003funは直接レジスタ触るのを少しやりやすくしてある感じなのですが、GPIOの操作についてはサブライブラリ的なのがあります。これを使うとクロックの設定や、GPIOの有効化の設定、またIOの出力がやりやすくなっています。

github.com

以下が実際のコードです。

#define EN_PIN GPIOv_from_PORT_PIN(GPIO_port_C, 2)
#define FLAG_PIN GPIOv_from_PORT_PIN(GPIO_port_C, 1)
#define LED_PIN GPIOv_from_PORT_PIN(GPIO_port_A, 2)

void setup_gpio()
{
    GPIO_port_enable(GPIO_port_A);
    GPIO_port_enable(GPIO_port_C);
    GPIO_port_enable(GPIO_port_D);
    GPIO_pinMode(FLAG_PIN, GPIO_pinMode_I_pullUp, GPIO_Speed_10MHz);
    GPIO_pinMode(EN_PIN, GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz);
    GPIO_pinMode(LED_PIN, GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz);
}

#define LOOP_MS 1000

#define ACTIVE_SEC 12 * 60 * 60
#define INACTIVE_SEC 1

int main()
{
    SystemInit();
    init_rcc();
    setup_uart();
    printf("start\n\r");

    setup_gpio();

    while (1)
    {

        // オンにする
        printf("active\n\r");
        GPIO_digitalWrite_0(EN_PIN);
        GPIO_digitalWrite_1(LED_PIN);

        for (int i = 0; i < ACTIVE_SEC; i++)
        {
            printf("%d/%d\n\r", i, ACTIVE_SEC);
            Delay_Ms(LOOP_MS);
        }

        // オフにする
        printf("unactive\n\r");
        GPIO_digitalWrite_1(EN_PIN);
        GPIO_digitalWrite_0(LED_PIN);

        for (int i = 0; i < INACTIVE_SEC; i++)
            Delay_Ms(LOOP_MS);
    }
}

github.com

わりと一瞬で動くコードは仕上がりました。

最後におまけ機能として、UART TXで今のカウントダウンを見られるようにしていました。

基板の設計

回路図は簡単なものです。GitHub上にアップロードしてあります。

github.com

kicanvas

https://kicanvas.org/?github=https%3A%2F%2Fgithub.com%2F74th%2Fusb-rebooter%2Fblob%2Fv1.0.0%2Fpcb%2Fusb_auto_reboot.kicad_sch

ポイントは以下の通りです。

  • CH217を組み込んで、ENピンをCH32V003で制御させる。
  • CH32V003には
  • CH32V003の書き込み用に、SWIOとGNDのピンを持たせておく。
  • CH32V003のデバッグ用に、TXピンをPD6として出しておく。標準のPD5を使うと、CH32V003J4M6(8ピンのやつ)ではSWIOのPD1と兼用のため、書き込みが難しくなる。PD6はalternate機能としてUART1 TXに繋がる。

反省点

作って動くものになったのですが、いくつか反省点があります。

  • CH32V003自体を保護にするのに、CH213(理想ダイオード)を組み込んでもよかった。
  • よりCH32V003の消費電力を減らすために、クロックを下げたり、Low Power Modeを使ったり、まだ工夫の余地がありそう。
  • 使ったUSB Type-C Plugは秋月で買えるのは便利ですが、LCSCで安く買えるものにしておけばもっとストックを持っておけるので良かったかも。
  • CCはそのままReceptacle(メス)からPlug(オス)に流していたはずですが、PDのやりとりが伝播できてなさそう。なんでや。。。

回路図、ファームウェアのコードは公開中

USB Type-C Plugの実装が思いのほか大変だったため、電子工作キットにしようとは今のところ考えていません。

ファームウェアのコードとkicadファイルは以下に公開しています。

github.com

まとめ

CH217で気軽にUSB5Vをスイッチ制御できるのは、今後も何かと役に立ちそうです!

ぜひCH217とCH32V003を使ってみてください。