私がNゲージで遊ぶときは、フローリングレイアウト(^^; なので、その日に出して、その日に撤収する必要があります。
※フローリングレイアウトの他に、畳レイアウト、リビングレイアウトがあるそうです。
DCS50Kで、ポイントを変えるには、手順があり車両を運転しながらは結構むつかしいです。
よって、運転に専念出きる様に、DCC用スイッチコントロールパネルを考えてみました。
■回路図
■コントローラ部
■コントロールパネル
■ソースファイル
■ソースファイルのダウンロード
■動画
■今後について
■回路図
←クリックすると拡大します。
※ポートPBに繋いでいる液晶はデバックの時に使ったので通常は不要な回路です。
※スイッチ入力の所で使っているプルアップ抵抗はAVRのポート設定で不要になりそう。
■コントローラ部
←クリックすると拡大します。
ブレッドボードの右上はLocoNet I/F部、左上と、左中央は未使用部品。
下部は液晶部で、ポート入力の値と、各ポイントのC/Tを表示しています。
■コントロールパネル
←クリックすると拡大します。
レイアウト図を書いて紙に印刷します。
程よい厚紙が無かったので、牛乳パックを開いてホッチキスで止めています。
←クリックすると拡大します。
穴開けて
←クリックすると拡大します。
スイッチ取り付けて完成
←クリックすると拡大します。
裏はこんな感じ。スイッチはあと2個余っているけど未使用。
←クリックすると拡大します。
コントローラ全体
※ぷーさんのメモは車両のアドレス番号が書いてあります。
←クリックすると拡大します。
レイアウト全体です。
←クリックすると拡大します。
息子の急なレイアウト変更依頼にも即対応(笑
←クリックすると拡大します。
レイアウト全体です。
■ソースファイル
やっつけソースなので、ソースコードが洗練されてないです・・・(^^;
ATtiny2313の個体差で、LocoNetの16600bpsが誤差範囲外で全く動かなかったので、AOSCCAL=0x59; の補正が必要でした。
#include
#include
#include
#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版 ポンチ追加