Carerra Digital Codierer

Hallo zusammen

bin neu in diesem Forum habe in sachen Arduino schon ein bisschen Erfahrung gesammelt und schon einige kleine Projekte realisiert
aktuell möchte ich gerne für die Carrera Digital meine eigene CU basteln

und zwar möchte ich gene die Funktion void manchesterEncode() in einen interrupt setzen
sie soll alle 7500 microsekunden ausgeführt werden habe schon einiges probiert aber es hat nichts funktioniert vl kann mir ja jemand helfen

const int dataOutPin = 3;                                   // connection to MOSFET driver circuit
const long wordRateMicros = 7500;                           // send a new data word every 7,5 ms

unsigned long intervalWordMicros = 0;                       // will store the time difference to last word(microseconds)
unsigned long previousWordMicros = 0;                       // will store last time when a word has been send (microseconds)
unsigned long currentMicros  = 0;                           // will store the current runtime (microseconds)

void setup() {                                              //////
  Serial.begin(115200);                                     // initialize serial bus 
  pinMode(dataOutPin, OUTPUT);                              // initialize the dataPin as an output
  digitalWrite( dataOutPin, HIGH );                         // set output Pin to HIGH, racetrack voltage is default 20 V  
}                                                           //////
                                           
void loop() {                                               //////
  currentMicros = micros();                                 // store current runtime
  intervalWordMicros = currentMicros - previousWordMicros;  // calculate interval
  if (intervalWordMicros > wordRateMicros) {                // is time to start a new data word?
    previousWordMicros = currentMicros;                     // new data word starts
    manchesterEncode( 648 );}                               //binary:0000001010001000,controller2, 

}                                                           
  
void manchesterEncode(word dataWord){                       //////
  const int halfClockMicros = 40;                           // experimental value for half clock rate of 50 microseconds on 16 MHz Arduino Uno
  int bitPos = 13;                                          // bit counter for position of bit in dataWord
  int currentBit = 0;                                       // store current bit
  while ( !currentBit ){                                    // 
    currentBit = ( dataWord >> bitPos ) & 1;                // store bit on position bitPos in currentBit, currentBit becomes 0 or 1
    bitPos--;}                                              // switch to next postion
  bitPos++;                                                 // get back to start bit
  do{                                                       // 
    currentBit = ( dataWord >> bitPos ) & 1;                // store bit on position bitPos in currentBit, currentBit becomes 0 or 1
    if ( currentBit == 1 ){                                 //
      digitalWrite( dataOutPin, HIGH );                     //
      delayMicroseconds ( halfClockMicros );                //
      digitalWrite( dataOutPin, LOW);                       //
      delayMicroseconds ( halfClockMicros );}               //
    else{                                                   //
      digitalWrite( dataOutPin, LOW );                      //
      delayMicroseconds ( halfClockMicros );                //
      digitalWrite( dataOutPin, HIGH );                     //
      delayMicroseconds ( halfClockMicros );}               //
    bitPos --;                                              // goto next bit
  } while ( bitPos >= 0 );                                  // until all bits are processed
  digitalWrite(dataOutPin, HIGH );                          // make sure to leave subroutine always with digital level HIGH
}

Hi

CU? (control unit ??)

Was passt an Deinem Programm nicht?
Grob überflogen sollte der Aufruf regelmäßig erfolgen - wo hakt's und wie hast Du Das festgestellt?

MfG

genau Control Unit

also das Programm läuft aber ich möchte den loop teil ja noch erweitern und dazu muss ich um einen zuverlässigen Ablauf zu gewährleisten die Funktion manchesterEncode() in einen Interrupt setzen welcher alle 7500 ms ausgelöst wird ! nun kenne ich mich mit interrupts nicht aus ich weis nur das eine Funktion im Interrupt sehr kurz sein muss und auch keine delays enthalten darf da hätte ich gene einen Lösungsansatz wie ich das machen kann ...

Hi

Da sind 'die Kollegen' gerade schwer am Basteln:
http://forum.arduino.cc/index.php?topic=516321.msg3519075 Klick

Wie genau müssen diese 7500ms (?? 7,5 Sek, vorhin eher 7,5µs) eingehalten werden?
7,5µs (7500ns) ist aber schon 'echt kurz' - da bleibt nicht viel Zeit für großartig Befehle zwischen drin.
Pro µs 16 Takte (bei 16MHz) - macht knapp 100 1-Takt-Befehle in einer Hochsprache - ich habe Da Bedenken.

MfG

die 7500 microsekunden entsprechen den Zeitabstand zwischen zwei Datenwörtern wie genau diese eingehalten werden müssen kann ich nicht sagen da die Carrera Autos die Datensätze dekodieren .
müsste man testen ..

ok also wenn das so schwierig ist dann werde ich einen zweiten Arduino weitere berechnungen machen lassen und die Datenwörter dann Seriell an meinen Codierer senden

Danke für die Antworten und den interessanten Link

Bereite die zu sendenden Kommandos doch auf (incl. Kodierung) und mache im zeitkritischen Bereich nur noch das Senden.

Gruß Tommy

könntest du mir da ein Beispiel geben wie ich das machen kann

Sorry, war ein Denk- und Lesefehler von mir.
Die Kodierung macht ja schon den Bitversand, deshalb ist meine Idee falsch.

Gruß Tommy

sonst hat niemand einen Lösungsvorschlag wie man das Problem angehen kann ?

Mit einem Interrupt alle 7,5ms wirst Du nicht auskommen.
Du willst 16Bit in Manchestercodierung rausschieben, wobei pro Bit 80µs benötigt werden. Das macht insgesamt 1280µs für die Übertragung des Datenwortes. So lange darf keine Interruptroutine dauern.

Ich habe etwas ähnliches mal für die Erzeugung eines Digitalsignals bei der Modellbahn (DCC) gemacht. Da ist die Codierung aber etwas einfacher. Du wirst einen Timer benötigen, mit dem Du das Signal erzeugst, und eher einen Interrupt pro Bit. Wenn Dein Loop schnell genug ist, kannst Du das Ganze alle 7,5ms aus dem Loop heraus anstoßen.

Ein Interrupt pro Taktflanke wäre alle 40µs ein Interrupt, das ist für einen ATMega schon recht sportlich. Aber an jeder Taktflanke ( halfClockMicros ) könnte ja eine Flanke im Ausgangssignal auftreten.
Beim Decodieren meines DCC-Signals gab es während der Präambel kurzzeitig ca. alle 60µs einen Interrupt - das ging noch.

Mit weniger Interrupts kommst Du aus, wenn Du das Signal über die PWM-Funktion des Timers erzeugst. Dann brauchst Du pro Impuls einen Interrupt. Den Timer musst Du dann aber nach jedem Impuls umprogrammieren. Um den Interrupt kurz zu halten, sollten die Daten schon passend für die Timerprogrammierung vorbereitet werden. Damit sollte es auch möglich sein, das Timing recht exakt - unabhängig von kurzen IRQ-Verzögerungen - zu erzeugen.

Sind erstmal alles nur so Gedanken aus meiner Erfahrung heraus, ohne dass ich da irgendetwas schon probiert hätte.

P.S. vielleicht solltest Du auch mal mehr Info's zu dem Carrera-Digitalsignal geben - oder einen Link, wo das beschrieben ist.

Ein ESP32 verfügt über eigene Hardware (eigentlich) für IR die sich zum Erzeugen solch eines Signals nutzen ließe.

https://esp-idf.readthedocs.io/en/latest/api-reference/peripherals/rmt.html

In gewisser Weise (er lässt sich mit Arduino IDE programmieren) ist da ja auch ein "Arduino".

Hier noch zwei Links für die Datenübertragung der Carrera Digital falls da jemand Interesse hat

http://www.wasserstoffe.de/carrera-hacks/
http://www.slotbaer.de

Ich habe es jetzt so gelöst indem ich die Datenworte von einem zweiten Arduino an meinen Codierer schicke und meine Funktionen mit den zweiten Arduino berechne

Hi

Hört sich so an, als ob das Zeug läuft :slight_smile:
Dabei war ich mir jetzt noch unsicherer, als je zuvor, da jetzt erneut von 7,5ms geschrieben wurde - dabei kann der Arduino noch nebenbei Kaffee machen und die Bude saugen.
Auch habe ich in den beiden Links beim Überfliegen keine Info zum Protokoll und/oder zur Bitzeit gefunden.
(Das macht selbst der ATtiny45 mit Seinen 1MHz RC-Takt noch mit - mit 7500 Takten sollte man die 80Bit wohl raus bekommen)

Würdest Du Deine Erkenntnisse hier zur Verfügung stellen?
Vll. gibt's ja noch weitere Slot-Car-Fahrer (oder wie Ihr Euch nennen mögt)

MfG

wenn ich mit dem Projekt fertig bin stelle ich natürlich alles zur verfügung wird aber eine Zeit dauern da ich noch nicht sehr viel Erfahrung habe in der Programmierung aber ich kämpfe mich durch :wink:

die Autos habe ich schon zum laufen gebraucht mit Geschwindigkeitreglung; Weichenstellung
und die Programmierung er Autos für den jeweiligen Regler Tank und Bremsverhalten läuft auch schon ...

Hi

Klingt echt interessant - gerne Mehr, aber das Basteln nicht vergessen :wink:

MfG

Gibt es schon was neues von deinem Projekt?

Das würde mich auch interessieren!