Článek popisuje nové možnosti nastavení rozšířené verze programu určeného pro TCO pult pro ovládání digitálního kolejiště systému DCC. Popis zapojení naleznete v předchozím článku s návodem na stavbu “Arduino TCO – ovládací pult s Arduinem na XpressNet“. Tato verze není žádnou pouze opravnou verzí, ale jde o rozšíření funkcí, není tedy třeba nahrazovat původní, pokud vám její funkcionalita vyhovuje. Verze obsahuje dvě nové možnosti nastavení časů spínání výstupů v pulzním režimu. Je tedy možné si určit, jak dlouhý stisk tlačítka je simulován. Prvních 50 tlačítek je možné nastavit na dobu do 2sec a posledních dalších 10 tlačítek je možné nastavit na dlouhé časy až do 51 sec.
První rozšíření umožňuje volbu délky pulzu v rozsahu 200ms až 2s v krocích po 200ms. Teto rozsah by měl být dostatečný pro případné přizpůsobení pro většinu i atypických dekodérů výhybek. Po aktivaci vstupu (tlačítka), se čeká na jeho dočasování a teprve poté lze provádět obsluhu dalších. Toto platí pro vstupy (tlačítka) číslo 1 až 50.
Druhá úprava se týká vstupů (tlačítek) číslo 51 až 60. Ty vám umožní ovládání i dlouhých časů od 200ms do 51s. Dále jsou pravě pro tyto dlouhé časy tlačítka upravena do multitaskingu, kdy se nečeká na jejich dočasování a je možné volit další volby na tlačítkách. K samotnému přepnutí zpět dojde na pozadí, po dočasování. To umožní ovládat různé dekodéry například pro přejezdy a zařízení, kde je potřeba dlouhého času.
Co se týká konfigurace, došlo jen ke změně hodnot zadávaných na řádku u proměnné “byte mode[]“.
1 2 |
byte mode[]={ 5, 5, 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, 60, 60}; // mod reakce (pulzni nebo stiskovej) // 0-podle delky drzeni, 1-10 pulzni ( x*0.2sec) [10*0.2sec = 2sec], vstupy 51 až 60 možno pulz v rozsahu 1-255 v rezimu multitask |
Význam je podobným jako v předchozí verzi:
- 0 – znamená, že výstup je spínán podle délky držení tlačítka, platí pro všechny vstupy (tlačítka)
- 1-10 pro vstupy (tlačítka) číslo 1-50, určuje dobu sepnutí v rozsahu 200ms až 2s s krokem po 200ms.
například pro první dvě tlačítka je nastaveno “5” to je tedy “5 x 0.2 = 1sec“. Volba dalších přepnutí je možná až po dočasování zvoleného. - 1-255 pro vstupy (tlačítka) číslo 51-60, určuje dobu sepnutí v rozsahu 200ms až 51s s krokem po 200ms.
Zde v režimu multitasking, kde se nečeká na dočasování a lze další volby provádět i při běhu času.
například pro dvě poslední tlačítka je nastaveno “60” to je tedy “60 x 0.2 = 120sec (2 minuty)“.
Ostatní nastavení zůstává totožné jako v návodu pro stavbu s popisem první verze programu v článku Arduino TCO – ovládací pult s Arduinem na XpressNet.
Co se týká nahrání nové verze software, postupujete stejně, jako v případě nahrávání do prázdné desky Arduina Mega. Opět vše podrobně popsáno v předchozím článku s návodem ke stavbě.
Celý program je zde, včetně komentářů u důležitých částí.
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 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
/* * TCO PULT V0.22 * * 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 * V0.22 - add config delay time, memory optimization * */ #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" byte 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 byte mode[]={ 5, 5, 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, 60, 60}; // mod reakce (pulzni nebo stiskovej) // 0-podle delky drzeni, 1-10 pulzni ( x*0.2sec) [10*0.2sec = 2sec], vstupy 51 až 60 možno pulz v rozsahu 1-255 v rezimu multitask #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)); byte 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 byte StateOld; boolean ledState = 0; unsigned long previousMillis = 0; // will store last time LED was updated unsigned long nextMillisButton[10]; // will store next time button reaction boolean changeButton[10]={0,0,0,0,0,0,0,0,0,0}; // state control time to button reaction #define interval 500 // interval snimani stavu DCC const byte LEDC = 12; // pin cervene ledky const byte 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 #define WaitingDEBUG 0 //Waiting for //#endif #if SerialDEBUG // nastaveni vystupu pro debuging unsigned int printRam = 8; #include <SoftwareSerial.h> SoftwareSerial Debug(0, 1); // RX, TX #endif void setup() { for(byte 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 (byte x = 0; x < 50; x++) { #if WaitingDEBUG delay(500); Debug.println(x); #endif if(bouncer[x].onPressed()) { XAddress = (addresses[x] - 1); if(turn[x] == 1) { sendGfunction(); if (mode[x] != 0) { if (mode[x] > 10) {mode[x]=10;} delay((waiting*mode[x])); sendGfunctionOff(); } else { while (bouncer[x].onReleased()==false) {} sendGfunctionOff(); } } else { sendRfunction(); if (mode[x] != 0) { if (mode[x] > 10) {mode[x]=10;} delay((waiting*mode[x])); sendRfunctionOff(); } else { while (bouncer[x].onReleased()==false) {} sendRfunctionOff(); } } } } // cyklus pro poslednich 10 tlacitek byte y = 0; for (byte x = 50; x < 60; x++) { #if WaitingDEBUG delay(500); Debug.print(x); Debug.print(" : "); Debug.println(y); #endif XAddress = (addresses[x] - 1); if (changeButton[y]) { // bezi cas u tohoto tlacitka? if (nextMillisButton[y] <= millis()) { // vyprsel cas? if(turn[x] == 1) { // jaky smer tlacitka to byl? sendGfunctionOff(); } else { sendRfunctionOff(); } changeButton[y] = false; bouncer[x].onPressed(); // smazani priznaku } } else { if(bouncer[x].onPressed()) { if(turn[x] == 1) { sendGfunction(); if (mode[x] != 0) { nextMillisButton[y] = ((mode[x] * waiting) + millis()); changeButton[y] = true; } else { while (bouncer[x].onReleased()==false) {} sendGfunctionOff(); } } else { sendRfunction(); if (mode[x] != 0) { nextMillisButton[y] = ((mode[x] * waiting) + millis()); changeButton[y] = true; } else { while (bouncer[x].onReleased()==false) {} sendRfunctionOff(); } } } } y++; } // 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 |
Pozorné oko čtenáře si ještě může povšimnout změn v deklaraci velikosti proměnných, to má vliv pouze na lepší používání prostředků procesoru a pak v případě, že uživatel při konfiguraci provede změnu mimo rozsah (chybu), nemělo by jít přeložit takto upravený kód a tím je uživatel varován, že někde udělal chybu.
Raději to uvádím, aby to nemátlo případné zájemce o úpravu kódu.
Zdrojový kód je možné stáhnout zde na konci článku, jako i přeložený soubor HEX.
————————————————————————————————————————————————-
Soubory ke stažení:
————————————————————————————————————————————————-
______________________________________________________________________________________
______________________________________________________________________________________