Strana článku … 2/4 — Popis programu TCO a nastavení vstupů
————————————————————————————————
Změny v nastaveni Arduino TCO se provádí přímo v programu a následně se za pomocí propojovacího kabelu USB přenášení společně s programem do Arduino desky. Nad nastavování pomocí CV či podobným způsobeb jsem ani nepřemýšlel, protože mi to přijde jako kdybych chtěl posílat dlouhý text za pomoci “dálnopisu”, když mi vedle leží FAX
Ale zpět k návodu. Uvedu zde program pro Arduino, ale není třeba rozumět všemu, jde jen o přehled, abych zde nevypisoval pouhé kousky a čitatel se pak ztratil v odkazech. I tak je program z pohledu programátora jednoduchý, většinu funkcí obstarávají knihovny (takové zásuvné moduly vytvořené pro nějakou konkrétní práci).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
/* * TCO PULT V0.21 * * Ovladaní příslušenství pomocí pultu s tlačítky připojeného na XpressNet * * by BorgMcz site: http://www.dccmm.cz * license GPLv2 * * Library: Arduino RBD Button Library Example v2.1.0, by Alex Taujenis - https://github.com/alextaujenis/RBD_Button * Arduino Timer Library v1.2.0, by Alex Taujenis - https://github.com/alextaujenis/RBD_Timer * XpressNet slave, pgahtow.de by Philipp Gahtow - http://sourceforge.net/projects/pgahtow/files/Arduino%20%28v1.0%29%20libaries/XpressNet.zip * * V0.1 - test and debug default function * V0.2 - new definition this data * V0.21 - funkce malloc a zjednoduseni cyklu * */ #define waiting 200 // doba sepnuti vystupu // buttons number 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 // realy pins 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 17, 16, 15, 14, 3, 4, 5, 6, 7, 8, 22, 24, 26, 28, 30, 32, 36, 34, 44, 42, 40, 38, 46, 48, 50, 52, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20 // realne piny arduina zmena mozna v "buttonPins" unsigned int addresses[]={ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30}; // adresa dekoderu boolean turn[]={ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}; // realce vyhybky rovne/odbocka boolean mode[]={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}; // mod reakce (pulzni nebo stiskovej) // 1-pulzni 0-podle delky drzeni #include <RBD_Timer.h> #include <RBD_Button.h> #define NO_OBJECTS 60 // realny pocet tlacitek ktera se pouziji, musi se pocitat i vynechana RBD::Button *bouncer = (RBD::Button*)malloc(NO_OBJECTS * sizeof(RBD::Button)); unsigned int buttonPins[NO_OBJECTS] = {54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,17,16,15,14,3,4,5,6,7,8,22,24,26,28,30,32,36,34,44,42,40,38,46,48,50,52,53,51,49,47,45,43,41,39,37,35,33,31,29,27,25,23,21,20}; #include <XpressNet.h> XpressNetClass XpressNet; // XpressNet address: must be in range of 1-31; must be unique. Note that some IDs // are currently used by default, like 2 for a LH90 or LH100 out of the box, or 30 // for PC interface devices like the XnTCP. #define XNetAddress 26 // Adresse im XpressNet #define XNetSRPin 2 // Max485 Busdriver Send/Receive-PIN // rucni zapis, tlacitka ovladani napajeni RBD::Button buttonOn(10); // power ON RBD::Button buttonOff(11); // power OFF RBD::Button buttonEme(9); // power Emergency unsigned int StateOld; boolean ledState = 0; unsigned long previousMillis = 0; // will store last time LED was updated #define interval 500 // interval snimani stavu DCC const int LEDC = 12; // pin cervene ledky const int LEDZ = 13; // pin zelene ledky // #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #define SerialDEBUG 0 //For Serial Port Debugging (Arduino Mega only) , 0 znamena vypnuti debugingu //#endif #if SerialDEBUG // nastaveni vystupu pro debuging unsigned int printRam = 8; #include <SoftwareSerial.h> SoftwareSerial Debug(0, 1); // RX, TX #endif void setup() { for(int i = 0; i < NO_OBJECTS; i++){ bouncer[i] = RBD::Button(buttonPins[i]); } pinMode(LEDC,OUTPUT); // nastaveni vystupu ledek a test pinMode(LEDZ,OUTPUT); digitalWrite(LEDC,HIGH); digitalWrite(LEDZ,HIGH); delay(800); digitalWrite(LEDC,LOW); digitalWrite(LEDZ,LOW); #if SerialDEBUG Debug.begin(115200); Debug.println("Start TCO"); #endif XpressNet.start(XNetAddress, XNetSRPin); //inicializace XNet-Bus } byte XAddress; void loop() { //zde toto se bude opakovat podle poctu tlacitek max. 60 XpressNet.receive(); //permernet update the library #if SerialDEBUG unsigned long timerMicros = micros(); // zacatek mereni smycky #endif for (int x = 0; x < NO_OBJECTS; x++) { if(bouncer[x].onPressed()) { XAddress = (addresses[x] - 1); if(turn[x] == 1) { sendGfunction(); if (mode[x] != 0) { delay(waiting); sendGfunctionOff(); } else { while (bouncer[x].onReleased()==false) {} sendGfunctionOff(); } } else { sendRfunction(); if (mode[x] != 0) { delay(waiting); sendRfunctionOff(); } else { while (bouncer[x].onReleased()==false) {} sendRfunctionOff(); } } } } // snimani tlacitek ovladani stavu DCC if(buttonOn.onPressed()) { XpressNet.setPower(csNormal); #if SerialDEBUG Debug.println("Button 100 Normal run"); #endif } if(buttonOff.onPressed()) { XpressNet.setPower(csTrackVoltageOff); #if SerialDEBUG Debug.println("Button 101 Track Voltage Off"); #endif } if(buttonEme.onPressed()) { XpressNet.setPower(csEmergencyStop); #if SerialDEBUG Debug.println("Button 102 Emergency Stop"); #endif } #if SerialDEBUG timerMicros = (micros()-timerMicros); // konec mereni casu smycky #endif unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; notifyXNetPower (XpressNet.getPower()); #if SerialDEBUG if(printRam >= 10) { // pri preteceni vypise volnou ram a delku smycky printRam = 0; Debug.print("RAM: "); Debug.println(freeRam()); // volna ram Debug.print(timerMicros); // cas smycky jednoho snimani tlacitek Debug.println(" smycka"); } else { printRam++; } #endif } } //-------------------------------------------------------------------------------------------- void notifyXNetPower (uint8_t State){ #if SerialDEBUG if (State != StateOld) { Debug.print("Power: "); Debug.println(State); StateOld = State; } #endif switch (State) { case csNormal: // Debug.println("ON"); digitalWrite(LEDC,LOW); // sviti zelena digitalWrite(LEDZ,HIGH); break; case csTrackVoltageOff: // Debug.println("OFF"); digitalWrite(LEDC,HIGH); // sviti cervena digitalWrite(LEDZ,LOW); break; case csEmergencyStop: // Debug.println("EmStop"); ledState = !ledState; // blika zelena digitalWrite(LEDC,LOW); digitalWrite(LEDZ,ledState); break; case csShortCircuit: // Debug.println("SHORT"); ledState = !ledState; // blika cervena digitalWrite(LEDZ,LOW); digitalWrite(LEDC,ledState); break; case csServiceMode: // Debug.println("PROG"); digitalWrite(LEDZ,LOW); // sviti cervena digitalWrite(LEDC,HIGH); break; case 255: // Debug.println("ERROR"); ledState = !ledState; // blikaji obe digitalWrite(LEDZ,ledState); digitalWrite(LEDC,ledState); break; default: // Debug.println("OTHER"); ledState = !ledState; // blika cervena digitalWrite(LEDZ,LOW); digitalWrite(LEDC,ledState); break; } } void sendGfunction() { XpressNet.setTrntPos(0, XAddress, B1000); #if SerialDEBUG Debug.print("Button Green ON, Address: "); Debug.println(XAddress); #endif } void sendGfunctionOff() { XpressNet.setTrntPos(0, XAddress, B0000); #if SerialDEBUG Debug.println("Button Green OFF"); #endif } void sendRfunction() { XpressNet.setTrntPos(0, XAddress, B1001); #if SerialDEBUG Debug.print("Button Red ON, Address: "); Debug.println(XAddress); #endif } void sendRfunctionOff() { XpressNet.setTrntPos(0, XAddress, B0001); #if SerialDEBUG Debug.println("Button Red OFF"); #endif } //-------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------- #if SerialDEBUG int freeRam () { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); } #endif |
Pro uživatele jsou zajímavé pouze řádky 20 až 26. Z toho jsou řádky 20, 21 a 26 pouze komenty, které nic nenastavují a slouží pouze k lepšímu pochopení nastavení. V případě potřeby se budou upravovat pouze řádky 23, 24, 25. Pro lepší orientaci teď uvedu pouze tyto řádky, které vás budou zajímat.
20 21 22 23 24 25 26 |
// buttons number 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 // realy pins 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 17, 16, 15, 14, 3, 4, 5, 6, 7, 8, 22, 24, 26, 28, 30, 32, 36, 34, 44, 42, 40, 38, 46, 48, 50, 52, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20 // realne piny arduina zmena mozna v "buttonPins" unsigned int addresses[]={ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30}; // adresa dekoderu boolean turn[]={ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}; // realce vyhybky rovne/odbocka boolean mode[]={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}; // mod reakce (pulzni nebo stiskovej) // 1-pulzni 0-podle delky drzeni |
Na řádku č. 20 jsou uvedeny čísla vstupů, tak jak jsou označeny na DPS (popis svorkovnic). Na řádku č. 21 pak vstupy, jak jsou označeny na desce Arduina. Tyto řádky jsou za znaky ” // ” které říkají překladači programu, že jsou to jen popisky programátora (stejně tak ještě řádek č. 26).
Mnohem zajímavější je řádek č. 23, kde je uvedena již adresa v systému. To znamená, že pokud ovládáte výhybku např. za pomoci MultiMouse, kde zadáte “1” pro ovládání výhybky s adresou “1“, tak v prvním sloupečku zadáte také číslo “1” a to samé pro druhý sloupeček, protože potřebujeme dvě tlačítka pro tuto adresu (rovně a do odbočky, stejně jako na MultiMouse máte dvě tlačítka).
O řádek níže (tedy řádek programu č. 24) nám definuje zda se bude jednat o tlačítko rovně nebo do odbočky. Zadáváme tedy “1” rovně nebo “0” do odbočky.
V posledním řádku říkáme, zda výstup se bude chovat pulzně nebo na délku stisku tlačítka. A to následovně “1” pulz nebo “0” dle délky stisku. To je vhodné třeba pokud máme na nějaké dekodéru nastaveno na výstupu ovládání např. závor. Tedy dokud držím, mám závory dole (sepnutý výstup).
Pokud si to tedy shrneme máme nastaveno takto:
– vstup prvního tlačítka je nastaven na adresu “1” stav rovně “1” a pulzní stav “1“
– vstup druhého tlačítka je nastaven na adresu “1” stav odbočka “0” a pulzní stav “1“
– vstup třetího tlačítka je nastaven na adresu “2” stav rovně “1” a pulzní stav “1“
– vstup čtvrtého tlačítka je nastaven na adresu “2” stav odbočka “0” a pulzní stav “1“
– atd. …. až do tlačítka 60
– u posledních čtyř tlačítek (56-60) si můžete povšimnout, že mají pro ukázku nastavenu reakci na délku stisku tlačítka.
Zde se nám projevují hned dvě zajímavé vlastnosti tohoto provedení TCO, prvním je možnost definování adres pro jednotlivé tlačítkové vstupy plně dle libosti. A druhou je pak možnost nezávislého nastavení chování rekce tlačítka.
Další zajímavou možností je jako přepínací prvky použít přímo přepínače, které budou rovnou zobrazovat stav výhybky. To je vhodné, pokud budeme používat pro ovládání výhybek pouze TCO. V případě použití přepínačů je třeba jen dodržet nastavení na “pulzní stav” tedy hodnotu “1” v posledním řádku nastavení. Při používání přepínačů místo tlačítek má ještě jednu zajímavou vlastnost a tou je po spuštění systému (připojení TCO), dojde k přenastavení výhybek do nastaveného stavu podle přepínačů na TCO.
Myslím, že tento systém je to nejjednodušší co se dalo vymyslet. Samotný překlad je také velice snadný. Pokud by však někdo měl obavy, zkuste napsat, na kterém vstupu jakou adresu chcete a já se vám pokusím odpovědět nebo přímo přeložit program.
Jinak pokud nepoužijete některé vstupy (tím je míněno, že nebudou připojena tlačítka), tak i přesto je třeba je mít obsazeny adresou, klidně stále stejnou, třeba “1”. Z tohoto je dále patrné, že adresy se klidně mohou opakovat. Více vstupů/tlačítek může mít stejnou adresu.
Jako oddělovač jednotlivé hodnoty (čísla) slouží “,“(spodní čárka) , “mezery” jsou pouze pro zarovnání hodnot pod sebou a v programu nemají význam. Jde jen o lepší orientaci v kódu.
Tímto je doufám všem jasné, jak je možné s kódem zacházet a jak TCO nastavovat. Na další stránce se zaměříme na samotný překlad programu a následné nahrání do Arduina TCO.
______________________________________________________________________________________
______________________________________________________________________________________