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

DCCの謎仕様? CV読み込みと「Ack(応答)」

 ワンコインデコーダXをはじめとするDCCデコーダのプログラムトラック(設定線路)での挙動について、ソースコードの観点から少しマニアックな解説をします。

 DCCを始めたばかりの方が必ず一度はぶつかる壁が、「なぜモーターを繋がないとCV値が読み込めない(エラーになる)のか?」という疑問です。
実はこの謎を解くカギは、デコーダのプログラムファイル motor_ctrl.c の中に書かれた、DCC規格特有の「力技な通信の仕組み」に隠されています。

DCCは「一方通行」の通信である

 そもそも、コマンドステーションから線路へ流れるDCC信号は、テレビのリモコンなどと同じ「一方通行」の通信です。線路にはプラスとマイナスの2本の線しかなく、デコーダ側からコマンドステーションへ「私のCV3の値は10です」といったデータを送り返すための通信線(TX線)は存在しません。

 では、コマンドステーションはどうやってデコーダのCV値を「読み取って」いるのでしょうか?

 実は直接数値を読み取っているのではなく、「CV3の値は1ですか?」「CV3の値は2ですか?」と順番に質問(パケットを送信)し、デコーダが「YES」と答えた時の数値を画面に表示しているのです。

「YES」の返事は「電流のスパイク」で作る

 通信線を持たないデコーダが、どうやってコマンドステーションに「YES(= Ack:Acknowledge)」と返事をするのか。ここがDCC最大の物理的ハックです。

「一瞬だけモーターを全力で回して、線路の電流をドカッと消費する」

 NMRA(全米鉄道模型協会)のDCC規格では、「60mA以上の電流を、5ミリ秒(0.005秒)以上消費すること」が「YES(Ack)」の合図として定められています。コマンドステーションは、質問を投げた直後に線路に流れるアンペア数をじっと監視し、この電流の跳ね上がり(サージ)を検知して返事を受け取っています。

ソースコードで見る Send_Ack() の正体

 ワンコインデコーダXのソースコード(motor_ctrl.c)の中に、まさにこの「YESの返事をする」ための関数 Send_Ack() が定義されています。

c
void Send_Ack(void) {
    // 質問を受け取った後、規定のタイミングまで少し待つ
    uint16_t pre_wait = TIM2->CNT;
    while ((uint16_t)(TIM2->CNT - pre_wait) < 5000); 

    // 【ハック部分】
    // モーターの前進ピンに、一瞬だけマイコンの最大パワー(mp+1)を出力する!
#ifdef HAS_MOTOR_OUTPUT
    uint32_t mp = TIM1->ATRLR;
    SET_MOTOR_FWD(mp+1); 
    SET_MOTOR_REV(0);
#endif

    // ※この後、約6ミリ秒後にモーター出力をOFFに戻す処理が続きます
}

 このコードが実行されると、マイコンは一瞬だけモーターにフルパワーの電圧をかけます。しかし、通電時間がわずか数ミリ秒と短すぎるため、ギアや車輪が回り出す前に通電が終わり、人間の目には「モーターから『チッ』あるいは『プッ』という微かな音がしただけ(車体は動かない)」ように見えます。
 しかし電気的には、コマンドステーションがしっかり検知できるだけの「60mA以上の大電流スパイク」が発生しているのです

「モーターを繋がないとエラー」の真の理由

 これで疑問は氷解したはずです。

 もしモーターを繋がずに、LED(室内灯など)だけを配線した状態でプログラムトラックに乗せた場合、Send_Ack() が実行されてピンからフルパワーが出力されても、LEDが消費する電流はせいぜい10〜20mA程度です。
これでは規格である「60mA以上の大電流スパイク」に届かないため、コマンドステーションのアンペア計は反応できず、「(デコーダは一生懸命YESと叫んでいるのに)声が小さすぎてコマンドステーションに聞こえていない」という状態になります。これが「読み込みエラー」の正体です。

テクニック: X や Xplusでモーターを繋がない状態で車両に搭載したい場合は、モーター端子に一時的に「100Ω〜150Ω程度のダミー抵抗」を繋ぐことで、強制的に60mA以上の電流を消費させ、Ackを読ませることができます。
(ただし、マイコンの出力は10mA程度しか流せません。100Ω〜150Ω程度のダミー抵抗を繋ぐとマイコンが壊れます。