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

ファイル
利用手順
初期化
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

ついに発表ですね!
今まで、LocoNetをAVR等のCPUを使って制御させる方法って
発表されていませんでしたので、良い情報ですー。
ベースの機能が公開されると、そこから色んな物が作れそうです!
ありがとうございます。そういっていただけると記事にまとめる甲斐があります。これからいろんな例が見られる事を楽しみにしています。
TCSセンサーを2つ買ったので、発注している基板(赤外線トランスポンディング etc.)が届くまではそれを使ってJMRIでの自動運転で遊んでみようとおもいます。そのときはTCSセンサーについても詳しく…
avr-gcc (WinAVR 20080610) 4.3.0を使って
とりあえず、makeが通るところまでたどり着きました(^_^;
実験回路をブレッドボードで組まないといけません・・・
検証してくださる方がいらっしゃいますと大変心強いです。
AVR Studioのプロジェクトにして公開する方が楽かもしれません。
次回はこれも付けようとおもいます。
実験結果楽しみにしています。
今日時間が取れましたので、実験回路作ってみました。
結果は、試験構成や配線をいろいろ調べないと、だめそうです・・・
という所です(^_^;
コマンドステーションは繋いだ状態でしょうか?
コマンドステーション(マスター)が無い場合LocoNetがプルアップされず通信ができないのかもしれません。
影響はなさそうですが、
void init_uart(unsigned int baud)
内で、
UCSRB = UCSRB & ~_BV(UDRIE); /* UDR空き割り込み禁止 */
の一行を入れておくと、AVR起動時に
ISR(USART_UDRE_vect)
がTxBuf.buf_sizeが0になるまで(255回くらい?)呼び出されなくなります。
あ~
そうですね。
初期化時にはUDRIEをセットしてはいけませんでした。
すいませんうっかりしてました。
修正しておきました。
ギブアップ(^^;
H/W なのか、S/Wなのか切り分けてみたいので、
chibiegg さんが作られたHEXファイルをいただけますか。
PC – usbLOCO – D101 – AVR という感じに接続しました。
オシロが欲しいなと(^^;
りょーかいしました。
整理してできれば木/金のいずれかににコンパイル済みのファイルとプロジェクト一式を公開します。
プロジェクトファイルをおいておきました。
中にコンパイル済みのHEXファイルも含まれています。
ハードウエアの問題かどうかの確認は、Loconetへ送信禁止期間を無視し、シリアルから直接パケットを送信してどうなるか、でわかるかもしれません。
早速ありがとうございます。
早速試してみました。
AVRの3番ピンのブレッドボードの列が接触不良という事を発見。
ですが、まだ何かあるようです・・・
ちょっと進展(^^;
AE-UM232Rを接続して、HHD Free Serial Port Monitor でモニタしてみたところ、
一応送られているようです。
LocoNetを送信する部分が怪しそうです。
Loconet.cの主な内容はタイマーで送信禁止期間を計ることと、エラーバイトの計算をするだけなのですが。
そのうちのタイマーを利用している部分に問題が発生する場合が多いです。
微妙なコードの違いで割り込みがうまく行かなかったり、プログラム全体がフリーズしたりする場合が多々あります。
ソフトウエア的に送信できない場合はこのタイマーのせいで送信関数の送信禁止期間が終わるまで待機する部分でいつまでも待ってしまうことになります。
最適化などによるのかなぁ。タイマー用の変数をvolatileで宣言するとかすればいいのかも…
あ、一つハードウエアをテストする方法を思いつきました。
AVRのTXDに繋がっているトランジスタのベースをTXDの代わりにGNDに接続するとコマンドステーション(DCS50)の画面に「SLP」と出るはずです。(Loconetが異常にLo期間が続く場合のエラー)
このエラーが出ればLocoNetへのオープンコレクタ出力はできていることになります。
>LocoNetを送信する部分が怪しそうです。
すみません。表現の仕方が間違っていました。
H/W部の送信部分が怪しいが正しいです。気を悪くされましたらごめんなさい。
今日まとまった時間が取れましたので、大きなブレッドボードに作り直したところ
ちゃんと動きました(^_^;
お騒がせしました。
お〜。おめでとうございます。
これからも経過を教えてくださいね〜
全然気をわるくなんかしてませんから(笑)。今後も気になる点は教えてください。
タイマー割り込みがかからない事態にはよく遭遇するので誤摩化していたので…
もしやと思っただけです。