ワンコインデコーダXのようなDIY(自作)を前提としたオープンソース・ハードウェアにおいて、最も悩ましい問題が「半導体の在庫切れ(ディスコン)」です。「指定されたモータードライバICが手に入らず、デコーダが作れない…」という事態を防ぐため、本プロジェクトのソースコードは、仕様の異なる別のICへ簡単に乗り換えられる柔軟なアーキテクチャを採用しています。
現在、ワンコインデコーダXのソースコードは以下の2つの代表的なモータードライバICに標準対応しています。
- TB67H450(東芝製)など: 「Active-Low」制御。マイコンから Low(0V) の信号を送った時にモーターに電気が流れます。少し特殊ですが、安価で入手性が高く、性能に優れています。
- BD6231(ローム製)など: 「Active-High」制御。マイコンから High(5V) の信号を送るとモーターに電気が流れる、直感的で分かりやすい仕様です。
この2つは「HighとLowのどちらでモーターが回るか」が真逆であるため、もしプログラムを書き換えずにICだけを交換すると、モーターが暴走したりショートしたりしてしまいます。
ソースコードを根本から書き直す必要はありません。ユーザーがコンパイルを行う際、decoder_config.h という設定ファイル内の 1行のコメントアウト(//)を付け替えるだけ で、全ての制御ロジックが自動的に切り替わるようになっています。
// ============================================================================
// モータードライバICの切り替えマクロ
// ============================================================================
#ifdef HAS_MOTOR_OUTPUT
//#define USE_BD6231 // 正論理 (Active-High): ピンがHigh(1)の時に出力ON
#define USE_TB67H450 // 負論理 (Active-Low) : ピンがLow(0)の時に出力ON
#endifこの #define の設定指示を受けると、コンパイラは motor_ctrl.c の中にある #ifdef(条件付きコンパイル)を読み取り、選択されたICに合わせた専用の計算式と出力ロジックだけを抜き出してファームウェアを生成します。
特に複雑なのが、Active-Low(LowでON)である TB67H450 をPWM(パルス幅変調)でスピードコントロールする処理です。
#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状態)
}
#endifTB67H450の場合、目標のスピード(ONにしたい時間)をマイコンの最大値(max_p)から引き算して「波形を裏返す」という数学的な処理を行っています。
このようなマクロ設計にしておくことで、将来まったく新しい第3のモータードライバICが登場したとしても、メインのDCCパケット解釈などの複雑なコードには一切手を触れず、出力部分の #ifdef ブロックを1つ追加するだけで簡単に対応させることができます。
「手に入る部品で工夫して作る」というDIYの精神を、ソースコードの設計レベルで強力にサポートしています。