AVRからLocoNetに送信

On 2009年5月24日, in DCC機器の自作, by chibiegg

以前、LocoNetにAVRを接続する回路は掲載しました。が、送信禁止期間等の実装がようやくできたので送信だけとりあえず現状を公開します。環境はAVR-GCCと、ATtiny2313で実験しています。
センサーとモボ621

ファイル

利用手順

初期化

uartの初期化をする必要があるので、init_uart(16600);として初期化しておき、割り込み許可しておきます。これは、割り込みを利用したUSART通信を参照してください。

タイマー

送信禁止期間の計測をするために、外部でタイマーを用意する必要があります。具体的には定期的に、loconet_timer関数を引数に㎲単位の経過時間をつけてコールする必要があります。

たとえば、タイマー0を用いて、800㎲ごとの割り込みを利用する場合割り込みの時に、

       loconet_timer(800);

とし、この関数を呼んでください。

LocoNetパケットの送信

パケットの送信にはloconet_send関数を利用します。引数に送信するバイト列の配列へのポインタと、送信するバイト数を渡します。エラーバイトは自動的に計算され送信されるので配列に含める必要はありません。送信時にLocoNetが利用中であったり、送信禁止期間であった場合は送信できる状態になるまで待機します。送信そのものはシリアルの割り込みで送信されますが、送信が開始されるまでは処理が進みません。(これが今後の改善点ですね)。次の例は線路電源をONにするパケットを送信する例です。

uint8_t POWER_ON[] = {0x82};
loconet_send(POWER_ON,1);

利用例

以下は1秒ごとにセンサー検出のON,OFFを送出する例です。

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "uart.h"
#include "loconet.h"

void delay_ms(uint16_t ms){
	while(ms--){
		_delay_ms(1);
	}
}

ISR(TIMER0_COMPB_vect){
	loconet_timer(800);
}

int main(){

	init_uart(16600);

	//800us割り込み
	TCCR0A = 0b00000010;
	TCCR0B = 0b00000011;
	OCR0A = 100;
	OCR0B = 50;
	TIMSK |= 0b100; //COMPB割り込み

	sei();

	uint8_t BDL_ON[] = {0xB2,0x00,0x50};
	uint8_t BDL_OFF[] = {0xB2,0x00,0x40};

	while(1){
		loconet_send(BDL_ON,3);
		wait_ms(1000);
		loconet_send(BDL_OFF,3);
		wait_ms(1000);
	}

return 0;
}

プロジェクトファイル

AVR StudioとWinAVR用のプロジェクトファイルをおいておきます。
こちらは一秒ごとにレール電源をオンオフします。
loconet-test.lzh

Tagged with:  

17 Responses to AVRからLocoNetに送信

  1. あやのすけ より:

    ついに発表ですね!
    今まで、LocoNetをAVR等のCPUを使って制御させる方法って
    発表されていませんでしたので、良い情報ですー。
    ベースの機能が公開されると、そこから色んな物が作れそうです!

    • chibiegg より:

      今まで、LocoNetをAVR等のCPUを使って制御させる方法って
      発表されていませんでしたので、良い情報ですー。

      ありがとうございます。そういっていただけると記事にまとめる甲斐があります。これからいろんな例が見られる事を楽しみにしています。

      TCSセンサーを2つ買ったので、発注している基板(赤外線トランスポンディング etc.)が届くまではそれを使ってJMRIでの自動運転で遊んでみようとおもいます。そのときはTCSセンサーについても詳しく…

      • あやのすけ より:

        avr-gcc (WinAVR 20080610) 4.3.0を使って
        とりあえず、makeが通るところまでたどり着きました(^_^;

        実験回路をブレッドボードで組まないといけません・・・

        • chibiegg より:

          検証してくださる方がいらっしゃいますと大変心強いです。

          AVR Studioのプロジェクトにして公開する方が楽かもしれません。
          次回はこれも付けようとおもいます。

          実験結果楽しみにしています。

          • あやのすけ より:

            今日時間が取れましたので、実験回路作ってみました。
            結果は、試験構成や配線をいろいろ調べないと、だめそうです・・・
            という所です(^_^;

          • chibiegg より:

            コマンドステーションは繋いだ状態でしょうか?

            コマンドステーション(マスター)が無い場合LocoNetがプルアップされず通信ができないのかもしれません。

          • あやのすけ より:

            影響はなさそうですが、
            void init_uart(unsigned int baud)
            内で、
            UCSRB = UCSRB & ~_BV(UDRIE); /* UDR空き割り込み禁止 */
            の一行を入れておくと、AVR起動時に
            ISR(USART_UDRE_vect)
            がTxBuf.buf_sizeが0になるまで(255回くらい?)呼び出されなくなります。

          • chibiegg より:

            あ~
            そうですね。
            初期化時にはUDRIEをセットしてはいけませんでした。

            すいませんうっかりしてました。
            修正しておきました。

          • あやのすけ より:

            ギブアップ(^^;
            H/W なのか、S/Wなのか切り分けてみたいので、
            chibiegg さんが作られたHEXファイルをいただけますか。

            PC – usbLOCO – D101 – AVR という感じに接続しました。

            オシロが欲しいなと(^^;

          • chibiegg より:

            りょーかいしました。
            整理してできれば木/金のいずれかににコンパイル済みのファイルとプロジェクト一式を公開します。

          • chibiegg より:

            プロジェクトファイルをおいておきました。
            中にコンパイル済みのHEXファイルも含まれています。

            ハードウエアの問題かどうかの確認は、Loconetへ送信禁止期間を無視し、シリアルから直接パケットを送信してどうなるか、でわかるかもしれません。

          • あやのすけ より:

            早速ありがとうございます。
            早速試してみました。
            AVRの3番ピンのブレッドボードの列が接触不良という事を発見。
            ですが、まだ何かあるようです・・・

          • あやのすけ より:

            ちょっと進展(^^;
            AE-UM232Rを接続して、HHD Free Serial Port Monitor でモニタしてみたところ、
            一応送られているようです。
            LocoNetを送信する部分が怪しそうです。

          • chibiegg より:

            Loconet.cの主な内容はタイマーで送信禁止期間を計ることと、エラーバイトの計算をするだけなのですが。
            そのうちのタイマーを利用している部分に問題が発生する場合が多いです。
            微妙なコードの違いで割り込みがうまく行かなかったり、プログラム全体がフリーズしたりする場合が多々あります。

            ソフトウエア的に送信できない場合はこのタイマーのせいで送信関数の送信禁止期間が終わるまで待機する部分でいつまでも待ってしまうことになります。

            最適化などによるのかなぁ。タイマー用の変数をvolatileで宣言するとかすればいいのかも…

          • chibiegg より:

            あ、一つハードウエアをテストする方法を思いつきました。
            AVRのTXDに繋がっているトランジスタのベースをTXDの代わりにGNDに接続するとコマンドステーション(DCS50)の画面に「SLP」と出るはずです。(Loconetが異常にLo期間が続く場合のエラー)

            このエラーが出ればLocoNetへのオープンコレクタ出力はできていることになります。

          • あやのすけ より:

            >LocoNetを送信する部分が怪しそうです。
            すみません。表現の仕方が間違っていました。
            H/W部の送信部分が怪しいが正しいです。気を悪くされましたらごめんなさい。

            今日まとまった時間が取れましたので、大きなブレッドボードに作り直したところ
            ちゃんと動きました(^_^;
            お騒がせしました。

          • chibiegg より:

            お〜。おめでとうございます。
            これからも経過を教えてくださいね〜

            全然気をわるくなんかしてませんから(笑)。今後も気になる点は教えてください。
            タイマー割り込みがかからない事態にはよく遭遇するので誤摩化していたので…
            もしやと思っただけです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>