【工事中】このサイトは現在作成中です。正式公開までしばらくお待ちください。

マクロでモータードライバ切り替える

 ワンコインデコーダXのようなDIY(自作)を前提としたオープンソース・ハードウェアにおいて、最も悩ましい問題が「半導体の在庫切れ(ディスコン)」です。「指定されたモータードライバICが手に入らず、デコーダが作れない…」という事態を防ぐため、本プロジェクトのソースコードは、仕様の異なる別のICへ簡単に乗り換えられる柔軟なアーキテクチャを採用しています。

 現在、ワンコインデコーダXのソースコードは以下の2つの代表的なモータードライバICに標準対応しています。

  • TB67H450(東芝製)など: 「Active-Low」制御。マイコンから Low(0V) の信号を送った時にモーターに電気が流れます。少し特殊ですが、安価で入手性が高く、性能に優れています。
  • BD6231(ローム製)など: 「Active-High」制御。マイコンから High(5V) の信号を送るとモーターに電気が流れる、直感的で分かりやすい仕様です。

 この2つは「HighとLowのどちらでモーターが回るか」が真逆であるため、もしプログラムを書き換えずにICだけを交換すると、モーターが暴走したりショートしたりしてしまいます。

設定ファイル: decoder_config.h

 ソースコードを根本から書き直す必要はありません。ユーザーがコンパイルを行う際、decoder_config.h という設定ファイル内の 1行のコメントアウト(//)を付け替えるだけ で、全ての制御ロジックが自動的に切り替わるようになっています。

c
// ============================================================================
// モータードライバICの切り替えマクロ
// ============================================================================
#ifdef HAS_MOTOR_OUTPUT

//#define USE_BD6231    // 正論理 (Active-High): ピンがHigh(1)の時に出力ON
#define USE_TB67H450  // 負論理 (Active-Low) : ピンがLow(0)の時に出力ON

#endif

内部で何が起きているのか?(motor_ctrl.c)

 この #define の設定指示を受けると、コンパイラは motor_ctrl.c の中にある #ifdef(条件付きコンパイル)を読み取り、選択されたICに合わせた専用の計算式と出力ロジックだけを抜き出してファームウェアを生成します。

 特に複雑なのが、Active-Low(LowでON)である TB67H450 をPWM(パルス幅変調)でスピードコントロールする処理です。

c
#ifdef USE_TB67H450 
    // TB67H450(負論理): LowがONのため、目標のDuty比(ON時間)を反転させる
    duty = max_p - duty; 

    if (logical_dir) { 
        SET_MOTOR_FWD(max_p+1);  // 前進ピンは常にHigh (OFF状態に固定)
        SET_MOTOR_REV(duty);     // 後進ピンに反転させたPWM波形を出力する
    } 
#else 
    // BD6231(正論理): HighがONのため、そのままDuty比を出力する
    if (logical_dir) { 
        SET_MOTOR_FWD(duty);     // 前進ピンにそのままのPWM波形を出力
        SET_MOTOR_REV(0);        // 後進ピンは常にLow (OFF状態)
    }
#endif

 TB67H450の場合、目標のスピード(ONにしたい時間)をマイコンの最大値(max_p)から引き算して「波形を裏返す」という数学的な処理を行っています。

この設計のメリット

 このようなマクロ設計にしておくことで、将来まったく新しい第3のモータードライバICが登場したとしても、メインのDCCパケット解釈などの複雑なコードには一切手を触れず、出力部分の #ifdef ブロックを1つ追加するだけで簡単に対応させることができます。

 「手に入る部品で工夫して作る」というDIYの精神を、ソースコードの設計レベルで強力にサポートしています。