Habe dazu einige Fragen? Das Teil wurde auf die schnelle nachgebaut. Hat sofort funktioniert. locoSpeed = (127L * analogRead(AN_SPEED))/1023; Was bedeutet 127L ? Adressen kann ich zur Laufzeit inzwischen ändern und auch mehrere, vorläufig 3 Loks damit Steuern. Leider ist es mir noch nicht gelungen die F- Tasten zu senden. Beleuchtung(F0)wäre auch nicht schlecht. Habe einen Arduino Selbstbau Lok Decoder der auch die F1-F20 Tasten aus decodiert. Wurde mit einer Industriellen Zentrale getestet. Das DCC Protokoll habe ich schon längere Zeit "studiert" bin aber mit den F-Tasten nicht weitergekommen. Die F-Tasten Befehle müssten doch mit dem Struct gesendet werden können Den LMD18200 habe ich gegen den L298N ausgetauscht und mit einen DL000 die Signale angepasst. http://www.ebay.de/itm/Neu-L298N-Stepper-Motor-Driver-Board-L298N-Motortreiber-Board-Schrittmotor-Modul/391279750306?_trkparms=aid%3D222007%26algo%3DSIM.MBE%26ao%3D1%26asc%3D20150313114020%26meid%3D3bb03dde46fd4543abf0971a7b0fb73a%26pid%3D100338%26rk%3D3%26rkt%3D30%26sd%3D201057615570&_trksid=p2141725.c100338.m3726 ====================================================================== struct Message { unsigned char data[7]; unsigned char len; } ; #define MAXMSG 2 // for the time being, use only two messages - the idle msg and the loco Speed msg struct Message msg[MAXMSG] = { { { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg { { locoAdr, 0x3F, 0, 0, 0, 0, 0}, 4} // locoMsg with 128 speed steps }; ===========================Originalprogramm============================ // 23. November 2009 // works well with LMD18200 Booster !!!!! /*Copyright (C) 2009 Michael Blank This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #define DCC_PIN 4 // Arduino pin for DCC out Vor/rueck // this pin is connected to "DIRECTION" of LMD18200 #define DCC_PWM 5 // must be HIGH for signal out // connected to "PWM in" of LMD18200 #define DCC_THERM 7 // thermal warning PIN am ARDU Input #define AN_SPEED 2//16 // analog reading for Speed Poti #define AN_CURRENT 0 // analog input for current sense reading nicht verwendet //Timer frequency is 2MHz for ( /8 prescale from 16MHz ) #define TIMER_SHORT 0x8D // 58usec pulse length #define TIMER_LONG 0x1B // 116usec pulse length unsigned char last_timer=TIMER_SHORT; // store last timer value unsigned char flag=0; // used for short or long pulse unsigned char every_second_isr = 0; // pulse up or down // definitions for state machine #define PREAMBLE 0 #define SEPERATOR 1 #define SENDBYTE 2 unsigned char state= PREAMBLE; unsigned char preamble_count = 16; unsigned char outbyte = 0; unsigned char cbit = 0x80; // variables for throttle int locoSpeed=0; int dir; //digi Input int last_locoSpeed=0; int last_dir; int dirPin = 12; //Digi input int FPin[] = { 8,9,10,11}; // 4FTasten int maxF =3; //4 FTaster int locoAdr=4;//40; // this is the (fixed) address of the loco // buffer for command struct Message { unsigned char data[7]; unsigned char len; } ; #define MAXMSG 2 // for the time being, use only two messages - the idle msg and the loco Speed msg struct Message msg[MAXMSG] = { { { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg { { locoAdr, 0x3F, 0, 0, 0, 0, 0}, 4} // locoMsg with 128 speed steps }; // loco msg must be filled later with speed and XOR data byte int msgIndex=0; int byteIndex=0; //Setup Timer2. //Configures the 8-Bit Timer2 to generate an interrupt at the specified frequency. //Returns the time load value which must be loaded into TCNT2 inside your ISR routine. void SetupTimer2(){ //Timer2 Settings: Timer Prescaler /8, mode 0 //Timmer clock = 16MHz/8 = 2MHz oder 0,5usec TCCR2A = 0; TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20; //Timer2 Overflow Interrupt Enable TIMSK2 = 1<<TOIE2; //load the timer for its first cycle TCNT2=TIMER_SHORT; } //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; // get next message msgIndex++; if (msgIndex >= MAXMSG) { msgIndex = 0; } 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; } 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; } } } void setup(void) { //Set the pins for DCC to "output". pinMode(DCC_PIN,OUTPUT); // this is for the DCC Signal pinMode(DCC_PWM,OUTPUT); // will be kept high, PWM pin digitalWrite(DCC_PWM,1); pinMode(DCC_THERM, INPUT); digitalWrite(DCC_THERM,1); //enable pull up pinMode(dirPin, INPUT); digitalWrite(dirPin, 1); //enable pull-up resistor !! for (int i=0 ; i<=maxF; i++){ pinMode(FPin[i], INPUT); digitalWrite(FPin[i], 1); //enable pull-up resistor } read_locoSpeed_etc(); assemble_dcc_msg(); //Start the timer SetupTimer2(); } void loop(void) { delay(200); if (read_locoSpeed_etc()) { // some reading changed // make new dcc message assemble_dcc_msg(); ; } } boolean read_locoSpeed_etc() { boolean changed = false; // read the analog input into a variable: // limit range to 0..127 locoSpeed = (127L * analogRead(AN_SPEED))/1023; if (locoSpeed != last_locoSpeed) { changed = true; last_locoSpeed = locoSpeed; } dir = digitalRead(dirPin); if (dir != last_dir) { changed = true; last_dir = dir; } return changed; } void assemble_dcc_msg() { int i; unsigned char data, xdata; if (locoSpeed == 1) { // this would result in emergency stop locoSpeed = 0; } // direction info first if (dir) { // forward data = 0x80; } else { data = 0; } data |= locoSpeed; // add XOR byte xdata = (msg[1].data[0] ^ msg[1].data[1]) ^ data; noInterrupts(); // make sure that only "matching" parts of the message are used in ISR msg[1].data[2] = data; msg[1].data[3] = xdata; interrupts(); }
:
Bearbeitet durch User
Al. K. schrieb: > Habe dazu einige Fragen? > > Das Teil wurde auf die schnelle nachgebaut. > Hat sofort funktioniert. > > locoSpeed = (127L * analogRead(AN_SPEED))/1023; > Was bedeutet 127L ? https://www.arduino.cc/en/Reference/IntegerConstants Es handelt sich um "Typehint" "L" Format um einen Datentyp zu erzwingen. > U & L formatters > By default, an integer constant is treated as an int with the attendant > limitations in values. To specify an integer constant with another data type, > follow it with: > > a 'u' or 'U' to force the constant into an unsigned data format. Example: 33u > a 'l' or 'L' to force the constant into a long data format. Example: 100000L > a 'ul' or 'UL' to force the constant into an unsigned long constant. > Example: 32767ul Leider kann ich persönlich nicht viel mit DCC Protokoll anfangen. Wahrscheinlich meinst du https://de.wikipedia.org/wiki/Display_Data_Channel. Was fehlt, wäre ein Schaltplan, ggf. bestenfalls Datenblätter und Bilder. Wie hast du den Stepper angeschlossen? (Schaltplan/Bilder)
:
Bearbeitet durch User
H. E. schrieb: > Leider kann ich persönlich nicht viel mit DCC Protokoll anfangen. > Wahrscheinlich meinst du > https://de.wikipedia.org/wiki/Display_Data_Channel. Nein, es handelt sich um https://de.wikipedia.org/wiki/Digital_Command_Control Eine digitale Modellbahnsteuerung.
Al. K. schrieb: > Das DCC Protokoll habe ich schon längere Zeit "studiert" bin aber mit > den F-Tasten nicht weitergekommen. Ich hab das mal in einer Tabelle zusammengefasst.
struct Message msg[MAXMSG] = { { { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg { { locoAdr, 0x3F, 0, 0, 0, 0, 0}, 4} // locoMsg with 128 speed steps }; Thomas E. schrieb: > Ich hab das mal in einer Tabelle zusammengefasst. Wenn meine Schlussfolgerung jetzt auch noch richtig ist, das ich nur das Datenbyte nach dem logoAdr Byte durch das Funktionsbyte Byte ersetze, dann hast du mir das richtige genannt. Würde dadurch das Zeitlimit zum Club schaffen.;-))
..meine Folgerung scheint richtig zu sein. Auf zwei Adr. habe ich mal die F_Tasten , alle F0-F4 Ein Aus geschaltet. werde morgen die Versuche weitermachen. Dank an Thomas, man könnte sagen ,fast ohne Worte!
Habe mal ein wenig weiter getestet. Kann jetzt erst mal mit der Zentrale 3 Adressen ansprechen die F1-F7 Tasten sowie F0 Licht betätigen . Dies klappt aber nur bei meinen Eigenbau Arduino Decoder. Habe eine Lok digital welche aber nur auf die Fahrgeschwindigkeit und Vor/Rück reagiert.(Kein licht) Auf der gleichen Adr liegt zum Test ein Decoder, welcher auf alles exakt reagiert. von meiner anderen Industriellen Zentrale kann ich das Licht der Lok ein und ausschalten, was auch der Eigenbau Decoder welcher auf der gleichen Adresse liegt anzeigt. Jetzt die Frage? Könnte es sein das die Lok auf einer Langen Adresse Programmiert ist und dadurch mit meiner Eigenbau Zentrale nicht korrekt arbeitet oder ?? Kann die Lok z.Z. nicht auslesen.
Normalerweise erkennt der Dekoder, ob er mit kurzer oder lange Adresse adressiert wird und reagiert entsprechend auf beide. Bit7 im 1. Byte=0 >> kurze Adr., Bit6 u.7=11 >> lange Adr. Man kann das aber auch fest einstellen im Dekoder, sodaß er eben nur auf kurze oder lange Adressen reagiert. Es kann aber auch am Timing liegen. Zwischen den einzelnen Datensätzen, die auf die selbe Adresse gehen, muß eine Pause von ein paar ms liegen. Den genauen Wert habe ich jetzt nicht im Kopf. Vielleicht macht die Arduinozentrale das nicht. Die meisten Dekoder stört das nicht. Aber dem Dekoder muß natürlich auch Zeit gegeben werden, seinen Job zu erledigen. Kann natürlich bei älteren, langsamen Controllern zum Problem werden.
:
Bearbeitet durch User
Der Lok Decoder ist einer der neuesten. Wie müsste ich nach deiner Meinung Vorgehen, um vielleicht zu erfahren warum Das licht nicht schaltbar mit meiner Arduino Zentrale ist. Der Code oben ist ja alles. Meine gebastelten Arduino Decoder verarbeiten die Befehle ja richtig. Will jetzt auch erst mal testen mit dem PC die Arduinozentrale zu steuern. Es soll nur eine Kleinanlage mit max 4 Loks aber vielen Funktionen werden.
:
Bearbeitet durch User
Ich würde erstmal die Zentrale normgerecht machen. Was passiert denn, wenn du der Lok nur die Funktionsdaten ohne den Fahrbefehl sendest?
:
Bearbeitet durch User
Thomas E. schrieb: > Ich würde erstmal die Zentrale normgerecht machen. Da hast du Recht! ..aber wie , wenn man noch keinen Ansatz hat was es sein könnte. Mit meinen Arduinodecoder kann ich Schieberegister,MP3-Player,Grafikanzeige gut ansteuern. > Was passiert denn, wenn du der Lok nur die Funktionsdaten ohne den > Fahrbefehl sendest? Es passiert nichts, die Lok fährt ohne Störung sauber weiter. Habe mit meiner Industriellen Zentrale das Licht eingeschaltet und dann auf die Arduinozentrale umgeschaltet. Das Licht bleibt an. Der Fahrbefehl wird sauber angenommen. Aber kein Lichtwechsel bei Richtungsänderung. Es ist als wenn die F-Tasten völlig ignoriert werden.
Al. K. schrieb: > Der Fahrbefehl wird sauber angenommen. > Aber kein Lichtwechsel bei Richtungsänderung. Nun weiß ich nicht, wie die Lok konfiguriert ist. Aber das ist in Werkseinstellung eine Funktion der Lok. Man kann das natürlich auch anders einstellen. Aber sende mal mit dem Arduino: Idle Fahrdaten Idle Funktionen Und dann wieder zurück auf Anfang.
Thomas E. schrieb: > Nun weiß ich nicht, wie die Lok konfiguriert ist. Aber das ist in > Werkseinstellung eine Funktion der Lok. Man kann das natürlich auch > anders einstellen. Mit meiner Industriellen Zentrale kann ich Licht einschalten und ddas Licht wechselt bei Fahrtrichtungs-Änderung. So wie es sein soll und programmiert wurde. > Aber sende mal mit dem Arduino: > > Idle > Fahrdaten > Idle > Funktionen Das mache ich ja. Meine Eigenbau Arduino Decoder werten bis jetzt Fahrbefehl und Funktionstasten bis F20 Aus. Mit meiner Arduino Zentrale bis jetzt Fahrbefehle und F-Tasten bis F12. Idle Fahrdaten Pause ? Idle Funktionen Pause ? Werde das mal mit verschiedenen Zeiten versuchen.
Al. K. schrieb: > Das Teil wurde auf die schnelle nachgebaut. Meinst du dies Teil? http://mrrwa.org/dcc-decoder-interface/
Hallo Das ist mein Decoder, welcher auch alles macht und zusätzlich Grafik,Sound BitAusgabenF0-F12 und Schieberegister möglich. Das Andere ist meine Primitiv Zentrale mit der ich ein wenig experimentiere.
:
Bearbeitet durch User
..so nach vielen Versuchen kein Erfolg. Bin zwar ein wenig schlauer geworden, aber die Problemlösung habe ich noch nicht gefunden. Heute wird erst mal gefeiert. Das Gehirn ein wenig durchspülen damit ich am Montag vielleicht die zündende Idee habe.;-))
Habe hier etwas gefunden.http://dcc-arduino.weebly.com/dcc-central.html http://dcc-arduino.weebly.com/uploads/1/2/5/1/12515203/dcc_simple_controller.ino Die Zeichnung hat nach meinen Verständnis aber nichts mit dem folgenden Programm zu tun,oder? dcc_simple_controller.ino In diesen Programm ist zu sehen wie die Lockbeleuchtung angesteuert wird. Habe das versucht in mein jetziges einfaches Programm einzubinden, leider erfolglos. Das Prinzip: // ------------------- buffer for command ------------------- struct Message {unsigned char data[7];unsigned char len;} ; #define MAXMSG 3 struct Message msg[MAXMSG] = { { { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg { { locoAdr, 0x3F, 0, 0, 0, 0, 0}, 4}, // Advanced operation instruction with 128 speed steps and direction (b7) in next byte { { locoAdr, 0x80, 0, 0, 0, 0, 0}, 3}, // Function group one instruction : 0x80 means light off }; // loco msg must be filled later with speed and XOR data byte int msgIndex=0; //---------------------------------------------------------------------- // -----ASSEMBLE DCC MESSAGELIGHT ------------------- ///////////////////////////////////////////////////// void assemble_dcc_msglight() { int i; unsigned char data, xdata; if (dir2) {data = 0x90;} else {data = 0x80;} // add XOR byte xdata = (msg[2].data[0]) ^ data; noInterrupts(); // make sure that only "matching" parts of the message are used in ISR msg[2].data[1] = data; msg[2].data[2] = xdata; interrupts();} // End routine //
:
Bearbeitet durch User
Hallo Jetzt geht es weiter, obwohl es mit dem Arduino direkt nichts mehr zu tun hat. Habe festgestellt das meine ESU Zentrale das Loklicht mit einer schaltetBefehlsfolge ADR 4 Befehl 0x90 (Licht ein(NL) F1-F4 Bit0-Bit3) Prüfsumme ADR 4 Befehl 0x80 (Licht Aus(NL) F1-F4 Bit0-Bit3) Prüfsumme Das sendet meine Arduinozentrale nicht(noch nicht) Diese sendet ADR 4 Befehl 0x3F Andere Werte setzen die die F1 bis F20 speed mit Bit 7 als Vor/Rück Prüfsumme Die Struct Ausgabe scheint in der Arduinozentrale auf 4 Byte festgelegt zu sein. Präambel und das Ende nicht erwähnt! Habe mir extra einen DCC Monitor mit einen Arduino gemacht welcher die Daten lesen kann.
:
Bearbeitet durch User
Diese sendet ADR 4 Befehl 0x3F Andere Werte setzen die die F1 bis F20 speed mit Bit 7 als Vor/Rück Prüfsumme Und ADR 4 Befehl FN(0) 0x90/0x80 + unteres Nible F1-F4 danach Geschwindigkeitsbyte Prüfbyte Glaube ich muss versuchen das Geschwindigkeitsbyte herauszunehmen . weis bloß noch nicht wie ich es mache. ADR 4 Befehl FN(0) 0x90/0x80 + unteres Nible F1-F4 Prüfbyte So sollte es aussehen!
:
Bearbeitet durch User
struct Message msg[MAXMSG] = { { { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg { { locoAdr, 0x3F, 0, 0, 0, 0, 0}, 4} // locoMsg with 128 speed steps }; Al. K. schrieb: > ADR 4 > Befehl FN(0) 0x90/0x80 + unteres Nible F1-F4 > Prüfbyte > So sollte es aussehen! Habe das jetzt getestet und im Struct von 4 auf 3 Byte Ausgabe gestellt! Aufruf Licht((FN) void assemble_dcc_msg_Licht() { unsigned char data, xdata; data |= Lichtbyte; // add XOR byte xdata = (msg[1].data[0]) ^ data; noInterrupts(); // make sure that only "matching" parts of the message are used in ISR msg[1].data[1] = data; msg[1].data[2] = xdata; interrupts(); } Wie ändere ich aber zur Laufzeit die vier auf 3 ?!
Mache jetzt zum eigenen Verständnis hier weiter. Habe diese Beiträge mal verlinkt, da ja passend dazu! Beitrag "Digitalbahn mit Arduino" Beitrag "Variable in Struct zur laufzeit schreiben" Beitrag "#define This_Decoder_Address zur Laufzeit verändern"
struct Message msg[MAXMSG] = { { { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg { { locoAdr, 0x3F, 0, 0, 0, 0, 0}, 4} // locoMsg with 128 speed steps }; senden des Lokbefehl (Speed+ Vor/rück) z.B. msg[1].len = 4; locoAdr, 0x3F,speed,Prüfbyte Licht/F0(FN)+ F1-F4 msg[1].len = 3; Befehl locoAdr, Funktionsbyte FN(0) 0x90/0x80 + unteres Nible F1-F4 Prüfbyte xdata = (msg[1].data[0] ^ data; Dies muss im Aufruf noch beachtet werden damit die Prüfsumme über 2Byte gebildet wird!! Damit kann ich jetzt weitermachen. Werde mal vom PC die Befehle oder Code senden. Wie muss das Struct verändert werden damit ich Testweise Geschwindigkeit und Funktionstasten senden Kann??
:
Bearbeitet durch User
Hallo Al. Kn. Wie muss das Struct verändert werden damit ich Testweise Geschwindigkeit und Funktionstasten senden Kann?? struct Message msg[MAXMSG] = { { { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg { { locoAdr, 0x3F, 0, 0, 0, 0, 0}, 4} // locoMsg with 128 speed { { locoAdr, 0x90, Prüfbyte, 0, 0, 0, 0}, 3} // Function Group One Instruction ( NMRA Standard S-9.2.1 Zeile 257) { { locoAdr, 0xA0, Prüfbyte, 0, 0, 0, 0}, 3} // Function Group Two Instruction ( NMRA Standard S-9.2.1 Zeile 270) // 0x90 => FL und F1 bis F4 Aus // 0x91 => nur F1 AN // 100DDDDD // 76543210 Bit // Bit 7 bis 5 : Instruction 001 // Bit 4 : FL ( abhängig von CV 29 Bit1 ) // Bit 3 : F4 // Bit 2 : F3 // Bit 1 : F2 // Bit 0 : F1 }; { locoAdr, 0xA0, Prüfbyte, 0, 0, 0, 0}, 3} // Function Group Two Instruction // Function Group Two Instriction: // 101SDDDD // Bit 7 bis 5 : Instruction 101 // Bit 4 : 1 = F5 bis F8 0 = F9 bis F12 // Bit 3 : F8 oder F12 // Bit 2 : F7 oder F11 // Bit 1 : F6 oder F10 // Bit 0 : F5 oder F9 für jedes "Extendet Packet" musst du einen neuen "Lockbefehl" absetzen. Du solltest MAXMSG erhöhen. Für Geschwindigkeit und F0 bis F12 benötigst du 3 msg[] Einträge. Wenn du noch "Lockbefehle" für F13 bis F28 senden möchtest benötigst du 5 msg[] Einträge für ein und dieselbe Lockadresse. Gruß Stephan
..so jetzt habe ich das Struct einigermaßen verstanden. Auch in Verbindung mit dem Arduino Programm der DCC Mini Zentrale. Hallo Stefan, deine Erläuterungen werde ich später testen. jetzt sende ich nur idle und locoMsg with 128 speed Dies msg verändere ich zur Laufzeit und kann dadurch F0(fN)-F4 F5-F8 F9-F12 F13-F20 F21-F28 erreichen. Getestet und mit Arduino Monitor bildhaft gemacht! Jetzt baue ich erst mal in Ruhe ein Vorzeigemuster Zentrale mit Booster. Zentrale soll auch mit PC gesteuert werden können.(schon getestet) Werde erst mal nur mit Tastern arbeiten,Speed(T+ T-) Licht F1-F8 4 Taster Adressumschaltung Kleines Grafikdisplay wird noch eingebunden. Wie kann ich CVs senden?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.