DCC s použitím Arduina – 2. část

Minule jsme si ukázali, jak vytvořit hardwarovou část DCC centrály, nyní si popíšeme její software.

Software pro jednoduchou centrálu je opravdu jednoduchý. Já jsem se velmi intenzivně inspiroval u Michaela Blanka, který začal dělat jedny z prvních pokusů. Jeho software je založen na používání přerušení od časovače Timer2. Hodnotu časovače nastavuje podle toho, jakou odesílá logickou hodnotu na 0x8D pro jedničku a nebo 0x1B pro nulu. (timer pracuje na frekvenci 2MHz s prescalerem /8 takže 57µs a 114µs).
Přerušovací rutina je tvořená stavovým automatem, který rozeznává 3 stavy:
0=PREAMBLE (Odesílání preambule pevné délky 16 jedniček, která zahrnuje i bit konce paketu)
1=SEPARATOR (Odeslání 0, která je oddělovačem preambule od datových bajtů a také datových bajtů od sebe)
2=SENDBYTE (odeslání jednoho bajtu z fronty „msg“; po odeslání se vrací na odeslání separátoru, pokud je ve frontě další bajt a nebo na odeslání preambule)

A to je vlastně vše. Fronta „msg“ je definována tak, že každý řádek představuje jeden paket, takže si ji lze vytvořit libovolně velkou.
Hlavní program pak periodicky kontroluje stav obvodu LMD18200 jestli nedošlo k přetížení a nebo přehřátí. Pak také kontroluje stav tlačítek a potenciometru a na jejich základě upravuje pakety ve frontě „msg“.

Program je koncipován pouze jako ukázka jednoduchosti. Je v něm celá řada konstant, například adresa lokomotivy a podobně. Zároveň však ošetřuje prakticky všechny okrajové stavy, jako je sledování aby nedošlo k zápisu do paketu který je vysílán, sledování zkratu a tak dále. Při rozpoznání zkratu nebo přetížení program reaguje tak, že rozsvítí červenou LED L na pinu D13 a odpojí obvod LMD18200. Pro obnovení z tohoto stavu je nutné použít tlačítko reset, zejména proto, že nemáme připojené žádné jiné tlačítko pro obnovení provozu. Program také ovládá světla lokomotivy, ačkoli obsahuje i rutiny pro ovládání dalších funkcí F1-F4. Tyto rutiny jsou zakomentovány, zejména proto, že jsem nechtěl znepřehledňovat zapojení dalšími přepínači.

//Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {
  //Capture the current timer value TCTN2. This is how much error we have
  //due to interrupt latency and the work in this function
  //Reload the timer and correct for latency.  
  // for more info, see http://www.uchobby.com/index.php/2007/11/24/arduino-interrupts/
  unsigned char latency;
  
  // for every second interupt just toggle signal
  if (every_second_isr)  {
     digitalWrite(DCC_PIN,1);
     every_second_isr = 0;    
     
     // set timer to last value
     latency=TCNT2;
     TCNT2=latency+last_timer; 
     
  }  else  {  // != every second interrupt, advance bit or state
     digitalWrite(DCC_PIN,0);
     every_second_isr = 1; 
     
     switch(state)  {
       case PREAMBLE:
           flag=1; // short pulse
           preamble_count--;
           if (preamble_count == 0)  {  // advance to next state
              state = SEPERATOR;
              byteIndex = 0; //start msg with byte 0
           }
           break;
        case SEPERATOR:
           flag=0; // long pulse
           // then advance to next state
           state = SENDBYTE;
           // goto next byte ...
           cbit = 0x80;  // send this bit next time first         
           outbyte = msg[msgIndex].data[byteIndex];
           break;
        case SENDBYTE:
           if (outbyte & cbit)  { 
              flag = 1;  // send short pulse
           }  else  {
              flag = 0;  // send long pulse
           }
           cbit = cbit >> 1;
           if (cbit == 0)  {  // last bit sent, is there a next byte?
              byteIndex++;
              if (byteIndex >= msg[msgIndex].len)  {
                 // this was already the XOR byte then advance to preamble
                 state = PREAMBLE;
                 preamble_count = 16;
                 // get next message
                 msgIndex++;
                 if (msgIndex >= MAXMSG)  {  msgIndex = 0; }  
              //byteIndex = 0; //start msg with byte 0
              }  else  {
                 // send separtor and advance to next byte
                 state = SEPERATOR ;
              }
           }
           break;
     }   
 
     if (flag)  {  // if data==1 then short pulse
        latency=TCNT2;
        TCNT2=latency+TIMER_SHORT;
        last_timer=TIMER_SHORT;
     }  else  {   // long pulse
        latency=TCNT2;
        TCNT2=latency+TIMER_LONG; 
        last_timer=TIMER_LONG;
     }  
  }

}

V ukázkovém programu jsem se snažil postihnout několik běžných situací. Program je navržen pro ovládání dvou lokomotiv současně.

Lokomotiva na adrese 3 se ovládá způsobem tradičním pro ovládání lokomotiv – potenciometr určuje rychlost a tlačítko přepíná směr. Druhé tlačítko slouží k ovládání světel této lokomotivy.
Lokomotiva na adrese 4 se ovládá pouze jedním potenciometrem a to tak, že ve středové poloze lokomotiva stojí, při otáčení doleva se zvětšuje rychlost couvání, při otáčení doprava se zvětšuje rychlost pro jízdu vpřed. Tento způsob je oblíbený pro uživatele autíček.

Adresy lokomotiv jsou zadány v konstantách přímo v programu, nevytvářel jsem žádné rozhraní pro zadávání adres. Jak jsem již poznamenal, v programu jsou také funkce pro ovládání funkcí F1-F4, ale protože se mi nechtělo dávat na destičku tolik spínačů, funkce nejsou aktivní a jsou zakomentované.

Celý program je napsán pouze do jednoho souboru metodou shora dolů. To je pochopitelně z programátorského hlediska naprosto nevhodné. Já jsem tuto metodu zvolil zcel záměrně. Takto napsané programy jsou totiž jednodušší na pochopení a na vysvětlování toho, co se kde děje.

Pokud uvažujete o vážnějším použití Arduina jako centrály, vyplatí se uvažovat nad použitím knihoven CmdrArduino a potažmo PrgmrArduino, které jsou mnohem propracovanější. Nebo se přímo inspirovat u DCC++ (GitHub).

Arduino jako DCC dekodér

Arduino lze stejně dobře použít i jako dekodér. Velikost desky jej trochu diskvalifikuje od použití v lokomotivách a vagónech, ale s vytvořením jednoúčelové desky založené například na Arduino Micro by bylo možné i to. V praxi se ukázalo, že profesionální dekodéry do lokomotiv se prodávají za velice přijatelné peníze, respektive za peníze odpovídající nákladům na domácí výrobu. Proto nemá příliš velkou cenu se snažit tuto výrobu přetlačit. Občas se dají najít projekty vlastních lokomotivních dekodérů založených na ATmega*8, ale většinou se jedná o velice základní dekodéry.
Možnost vlastního programování však člověk docení například pokud se rozhodne používat osvětlené vozy s tím, že preferuje reálný vzhled, kdy se světla v kupé vagónů rozsvěcejí postupně a né vždy všechna. Pak je velmi vhodné si vytvořit dekodér, který je schopen používat rozsáhlejší matice LEDek (například zapojených do charlieplexingu) a tyto pak rozmístit do jednotlivých kupé.

Daleko praktičtější využití však Arduino nachází u dekodérů příslušenství. Tedy v případě výhybkových přestavníků, semaforů, návěstidel, osvětlení domečků a podobně. Tady se dá využít toho, že deska je vybavena větším množstvím vstupů a výstupů, které le poměrně komplexně ovládat a vytvářet tak na kolejišti pěkné animace.

Za tímto účelem založil Alex Shapherd stránku „Model RailRoading with Arduino“, kde se dá najít popis základních funkcí dekodérů pro příslušenství a lokomotivních dekodérů. Také se zde dají najít užitečné knihovny pro čtení DCC signálu. Trochu mrzuté je, (a to osobně považuji za velký nedostatek všech Arduino projektů) že projekty spoléhají na konfiguraci v kódu. To je pro DCC neobvyklé. Protokol předpokládá, že každý dekodér má k dispozici část paměti, která je napěťově nezávislá (eeprom,flash,…) a že si do ní může uložit své konfigurační proměnné. Těchto proměnných může každý dekodér používat až 1024 a uživatel je může měnit. Existuje systém konfigurace v servisním režimu (na programovací koleji), kdy dochází ke čtení/změně hodnot u toho dekodéru, který se nachází na programovací koleji bez ohledu na jeho adresu. A pak také existuje systém konfigurace za provozu (programování na hlavní trati PoM) kdy jsou požadavky na změnu odesílány adresně konkrétnímu dekodéru. Pokud budete vytvářet vlastní dekodér, pokuste se tomuto nešvaru vyhnout a použíejte konfigurační proměnné.

mrrwa

Logo projektu (nebo snad maskot) MRRWA (Model RailRoading With Arduino)

 

 Arduino jako ovladač

Nejrůznější ovladače pro modelovou železnici jsou také velice vděčným tématem pro Arduino. U nás se používají dva hlavní systémy pro připojování ovladačů. První, který je oblíbenější na domácích kolejištích vytvořil Bernd Lenz pod označením XpressNet. Druhý je oblíbený zejména ve vláčkových klubech, vytvořila jej firma Digitrax pod označením LocoNet.

XpressNet je relativně jednoduchá PMP (point to multipoint) síť, velice podobná síti třeba modbus. Fyzická vrstva je RS485 s přenosovou rychlostí netradičních 62500 bps 9N1. Tradičně se bit číslo 9 používá pro označení adresy, jednotlivá zařízení mají adresy 1-31 (5bit adresa). Komunikace je ošetřena prostým X-Or kontrolním součtem a hlavičkový bajt je navíc ošetřen paritou v datech.
Mezi hlavní přednosti XpressNet patří její dobrá zdokumentovanost a možnost vlastního vývoje. Na druhou stranu mezi nedostatky patří uzavřenost rozvoje a poměrně striktní trvání na jediném zdroji informací – centrále. V protokolu není možnost aby ovladač poskytl infomace, které by centrála převzala (třeba informace o obsazení kolejového úseku). (poslední známá verze je v3.6)

LocoNet je mírně komplexnější PtP (Point to Point) síťová struktura, založená na 16660bps CSMA/CD (Carrier Sense Multiple access with Carrier Detect) komunikaci. (Ano, je to ta kterou používal první 10M Ethernet). Síť předpokládá, že existuje pouze jeden server (centrála), na druhou stranu se nebrání PtP komunikaci dvou prvků bez účasti serveru.
Jako hlavní přednost se uvádí robustnost sítě. Bohužel síť je udržovaná jako uzavřená a existuje pouze zjednodušená dokumentace, která se od své verze 1,0 (z října 1997) nikdy nezměnila. Informace se šíří převážně na základě reverzního inženýrství v rámci internetových diskuzních fór, takže existuje větší množství zařízení, které se při komunikaci opírají o nepřesné informace a mají menší kompatibilitu.

Vzhledem ke kvalitě dokumentace považuji za praktičtější se věnovat XpressNetu. Pro vytvoření ovladače existují docela hezké stránky locoduino, bohužel v trochu nevhodném jazyce, nebo jejich GitHub.

Pro připojení k síti XpressNet potřebujeme pouze vytvořit rozhraní RS485. To je velmi jednoduché s použitím obvodu MAX485 nebo jeho ekvivalentů. Síť nedoporučuje používat zakončovací rezistory, napžíklad proto, že není znáná impedance vedení a ani není jisté, jestli daný ovladač bude na konci vedení. Pro některé budiče sběrnice je však doporučeno použít fail safe biasing rezistory. Následující obrázek ukazuje základní schéma připojení k síti.

Arduino_XpressNet

Další části pro ovladač hodně odpovídají fantazii autora, jedná se o různé potenciometry, klávesnice, displaye, přepínače a podobné prvky.
Z pohledu XpressNet je také zajímavé, že rozhraní pro připojení počítače, nebo třeba tabletu je také považováno za ovladač, takže pokud máte raději komunikaci než tvorbu krabiček, můžete se realizovat i v této oblasti.
Svět digitální modelové železnice doposud čeká na solidní ovladač, který bude schopen dostatečně univerzálně stavět vlakové cesty, včetně jejich signalizace.

Buďte první.