DCC用コントロールパネルを作る

私がNゲージで遊ぶときは、フローリングレイアウト(^^; なので、その日に出して、その日に撤収する必要があります。
※フローリングレイアウトの他に、畳レイアウト、リビングレイアウトがあるそうです。
DCS50Kで、ポイントを変えるには、手順があり車両を運転しながらは結構むつかしいです。
よって、運転に専念出きる様に、DCC用スイッチコントロールパネルを考えてみました。

メニュー
■回路図
■コントローラ部
■コントロールパネル
■ソースファイル
■ソースファイルのダウンロード
■動画
■今後について

本文
■回路図
←クリックすると拡大します。
※ポートPBに繋いでいる液晶はデバックの時に使ったので通常は不要な回路です。
※スイッチ入力の所で使っているプルアップ抵抗はAVRのポート設定で不要になりそう。

■コントローラ部
←クリックすると拡大します。
ブレッドボードの右上はLocoNet I/F部、左上と、左中央は未使用部品。 下部は液晶部で、ポート入力の値と、各ポイントのC/Tを表示しています。

■コントロールパネル
←クリックすると拡大します。
レイアウト図を書いて紙に印刷します。
程よい厚紙が無かったので、牛乳パックを開いてホッチキスで止めています。

←クリックすると拡大します。
穴開けて

←クリックすると拡大します。
スイッチ取り付けて完成

←クリックすると拡大します。
裏はこんな感じ。スイッチはあと2個余っているけど未使用。

←クリックすると拡大します。
コントローラ全体
※ぷーさんのメモは車両のアドレス番号が書いてあります。

←クリックすると拡大します。
レイアウト全体です。


←クリックすると拡大します。
息子の急なレイアウト変更依頼にも即対応(笑

←クリックすると拡大します。
レイアウト全体です。

■ソースファイル
やっつけソースなので、ソースコードが洗練されてないです・・・(^^;
ATtiny2313の個体差で、LocoNetの16600bpsが誤差範囲外で全く動かなかったので、AOSCCAL=0x59; の補正が必要でした。

#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "uart.h" #include "loconet.h" #include "sc2004drv.h" #define C 0x30 #define T 0x10 #define PMAX 3 #define SW_PORT PIND /*入力ポート*/ #define SW_PORTO DDRD /*ポート方向設定*/ void delay_ms(uint16_t ms){ while(ms--){ _delay_ms(1); } } ISR(TIMER0_COMPB_vect){ loconet_timer(800); } void point_c(uint8_t address,uint8_t cort) { uint8_t table[] = {0xb0,0x00,0x00}; // cmd,address,C/T table[1] = address; table[2] = cort; // cort = c or t loconet_send(table, 3); } int main(void){ uint8_t read_sw,read_sw_last; int i; uint8_t foo=0; lcd_init(); /*LCD初期化*/ init_uart(16600); OSCCAL=0x59; /* 今使っている attiny2313 個体差によるOSCの補正 */ /* 通常は不要と思われる */ //800us割り込み OCR0A = 100; OCR0B = 50; TIMSK |= 0b100; //COMPB割り込み TCCR0A = 0b00000010; TCCR0B = 0b00000011; SW_PORTO = 0x00; /* 0000 0000 bit0,bit1 は、txd,rxdに割り当てられているので 0、入力ポートなので、0 */ sei(); /* SW_PORT PD6 sw5 PD5 sw4 PD4 sw3 PD3 sw2 PD2 sw1 PD1 TXD PD0 RXD 0xfc 1111 1100 */ read_sw = SW_PORT & 0xfc; // 今回の状態を読み込み(txd,txdを0xfcでマスク) // lcd_position(0,0); /*カーソル位置の設定*/ // lcd_puthex(read_sw); /*文字列の表示*/ // (i+2)は、TXD,RXDビットをキャンセルさせる為の式です for(i=0;i<=PMAX-1;i++){ // 初回の状態を読み込みポイントを設定する if((( read_sw >> (i+2) ) & 0x01) == 0) point_c(i,C); //close 直線 if((( read_sw >> (i+2) ) & 0x01) == 1) point_c(i,T); //thrown 分岐 delay_ms(100); } while(1){ lcd_position(0,3); /*カーソル位置の設定*/ if(foo==0){ lcd_put_str(" "); /*文字列の表示 ヘルスチェックのつもり*/ foo++; } else { lcd_put_str("*"); /*文字列の表示*/ foo=0; } read_sw_last = read_sw; // 前回の状態を記録 read_sw = SW_PORT & 0xfc; // 今回の状態を読み込み lcd_position(0,1); /*カーソル位置の設定*/ lcd_puthex(read_sw); /*文字列の表示*/ if(read_sw_last != read_sw){ // 前回の今回の値を比較 for(i=0;i<=PMAX-1;i++){ if((( read_sw >> (i+2) ) & 0x01) != (( read_sw_last >> (i+2) ) & 0x01)){ // ビットシフトさせて下位ビットを比較 lcd_position(i,2); /*カーソル位置の設定*/ if((( read_sw >> (i+2) ) & 0x01) == 0){ //close 直線 point_c(i,C); lcd_put_str("C"); } if((( read_sw >> (i+2) ) & 0x01) == 1){ //thrown 分岐 point_c(i,T); lcd_put_str("T"); } } delay_ms(100); } } } return 0; }

■ソースファイルのダウンロード
ダウンロード

■動画
上のレイアウトとはちょっと違いますが雰囲気が分かる動画を。
それから、ディレイ時間を短くしたので、現バージョンのポイント切り替えはキビキビしています。



今後について

・大量のポイントが制御できるか確認したい。(その前にポイントを購入しないと・・・)
・ATMEGAに移植する必要があるかな。
・正しくポイントが切り替わってないとショートしてしまうので、信号等で自動的に対策出来ないかな?


ポンチ買いました

・スイッチの固定用として、紙に丸穴をあけるためのポンチを買ってきました。
 100円ショップにないだろうなーと思って大きめの所を見たところありました。おそろべし。
←クリックすると拡大します。


2009.08.02 初版
2009.08.16 2版 ポンチ追加