schnellst möglicher Kontakt zwischen 2 x Arduino (Flipperprojekt)

Folgender Aufbau:

2 Arduinos sollen die original Elektronik meines Flippers ersetzen.

Was bisher funktioniert:

  • der erste Arduino steuert die 4 Spulen mittels Tastereingaben bzw. Spielfeldkontakten. Da Dieses sehr zeitkritisch ist (5 ms können schon entscheidend sein), habe ich keinerlei delays verwendet und bisher auch auf interrupts verzichtet. 4 taster abfragen und zugehörige Steurung von Output-Pins "gleichzeitig" funktioniert bestens. Die Loop() wird halt sehr schnell durchlaufen und timing passiert mittels millis().

  • der zweite Arduino steuert das bling bling, also LED´s, Soundausgabe, Punktedisplay etc. Hier sind durchaus auch mal delays verwendet worden. funktioniert auch.

Und nu kommts: Jetzt soll der erste arduino aber dem zweiten Punkte-Informationen übermitteln, ohne sich selbst auszubremsen. D.h. z.B. "Schlagturmkontakt wurde ausgelöst, Punktezähler um 1 erhöhen", ohne daß während dessen das Hauptprogramm des 1. Arduinos lange pausiert wird. Die Verzögerung für die Datenübermittlung soll also minnimalst sein!

Eine serielle Kommunikation fällt wohl aus, da diese zu lange dauert? Kann man einfach einen Pin auf High ziehen und damit auf dem 2. Ardu einen interrupt auslösen? Wie lange dauert das Senden eines Kommandos über I2C? Mit interrupts auf dem 1. Ardu kann ich ja verhindern, daß Eingaben "verschluckt" werden. Mir geht es eher um die geringst mögliche Zeitunterbrechung.

Hoffe ich habe das halbwegs nachvollziehbar beschrieben ::) Vielleicht hat ja einer ne Idee oder den entscheidenden Tip (Bei Bedarf kann ich auch programmcode posten)

greets

Warum läßt du nicht alle Funktionen über einen laufen? Das wäre sehr wahrscheinlich schneller.

Hallo,

meine Ideen würden auch auf geänderte Hardware hinauslaufen:

Zumindest den Arduino 1 durch einen Teensy (3.2) ersetzen.

  • Serial1 hat einen 8 Byte FIFO, zumindest kleine Botschaften kann man ohne Zeitverlust raushauen
  • Die UARTs können ohne Problem mit 1 MBit laufen, Senden dauert also nicht lange.

  • Für I2C oder SPI gibt es Libraries, die DMA verwenden können, geht also auch ohne große Verzögerung

  • Für UART mit DMA gibt es zumindest Beispiele, anscheinen keine fertige Lib

Wenn du ein Protokoll implementierst, das alles in kurze Bytefolgen seriell überträgst, kannst du das problemlos seriell übertragen. 3 Byte bei 1 Mbit, ich weiß gar nicht, ob man das schon in ms angeben kann.

Was die uC Power angeht, glaube ich, dass der Arduino locker mit der alten Relaistechnik mithalten kann und meistens nix tut. Wahrscheinlich musst du aber für die Eingangssignale auf IRQ umsteigen. Messen bringt da aber Gewissheit. Wie lange bleibt den ein Kontakt geschlossen, wenn die Kugel drüber donnert?

Nur mal so aus unwissenheit:

Wird Serial nicht via Interupt übertragen? Also ein Puffer im UART gefüllt der den selbst leert und überträgt (so wie der UART 16550) und dann per Interrupt neue Daten anfordert wenn nötig?

Den dann würde das Übertragen nichts verlangsamen. Zudem denke ich das 5ms Zykluszeit schon ein ziemlich großes Programm ist und nicht nur ein paar Spulen und Taster abfragt und steuert.

Wir reden ja von 16MHz und Single Takt Befehlen. 5ms sind dann ca 80.000 Befehle. Allerdings…ohne den Code zu kennen ist das natürlich eher spekulativ. 5ms sind jedoch keine Zeit für einen µController.

chefin: Nur mal so aus unwissenheit:

Wird Serial nicht via Interupt übertragen?

Es würde zumindest der Doku von Serial widersprechen, da gibt es ja Serial.AvailableForWrite() in dessen Doku steht

Get the number of bytes (characters) available for writing in the serial buffer without blocking the write operation.

Aber lange dauern sollte das bei einer hohen Baudrate nicht, da hast du recht.

Wird Serial nicht via Interupt übertragen?

Ja!

Das Schreiben blockiert erst, wenn der Buffer voll ist.
Das Lesen, wenn er leer ist.

Ich würde es mit serieller Übertragung einfach mal ausprobieren. Probleme sehe ich höchstens auf Empfängerseite, wenn dort die Loop mit Delay und Co. zu lange braucht.

Geht das Übertragen von Daten tatsächlich schneller als mal eben nebenbei ne LED auf high oder auf low zu setzen?

Ne, weil bei 9600 Baud ein HIGH ja 50µs lang ist, aber dein digitalwrite bei 16MHz ungefähr 0,0625 µsec braucht (Taktlänge).

Zu Deutsch, eigentlich nicht zu vergleichen. Das einen schreibt ein Byte (1 Takt), das andere muss ein Timing einhalten zwischen High und Low um am Empfänger verstanden zu werden. Es soll ja schon jemand geschafft haben 500.000 Baud zu fahren, wäre also 1µsec Impulslänge. Oder 16 Ein-Takt Befehle.

Ist so als fragst du ob der Golf schneller als der ICE ist. Nein ist er nicht, aber meinstens kommt er früher an in Deutschland. Ohne also weitere Daten wie Strecke, Uhrzeit, usw zu kennen kann man die frage nicht eindeutig beantworten. So auch bei µController

Dann komm ich nochmal zu meiner ursprünglichen Frage zurück, warum man das Ansteuern von ein paar LEDs und dem Pieper einen 2. Arduino verwenden sollte… Es wäre doch unkomplizierter und tendenziell schneller alles in einem Arduino zu machen. Wenn es wirklich so zeitkritisch sein sollte wäre es sinnvoller, wie es AduFE schon schrieb, einen Teensy zu nehmen…

MaHa76: Geht das Übertragen von Daten tatsächlich schneller als mal eben nebenbei ne LED auf high oder auf low zu setzen?

Das geht am schnellsten. Allerdings muss der Empfänger mitbekommen, ob ein Signal und wie oft ein Signal anliegt. Im Endeffekt bräuchte man noch einen Rückkanal zur Empfangsbestätigung. Seriell könnte man auch komplexere Informationen übertragen, z.B. verschiedene Punktewerte je nach Aktion.

Ich würde jetzt nicht ohne die Übertragung mal praktisch ausgetestet zu haben, das ganze Projekt auf Teensy ummodeln. Zum einen muss das ganze Sketch auf einen Controller umgeschrieben werden und auch die Elektronik angepasst werden.

Alles auf "nur" einem Ardu(Teensy) laufen zu lassen funktioniert meiner Meinung nach nicht, weil auf dem zweiten zu viele (und langsame) Prozesse ablaufen.

  • Keybard-Ausgaben über USB (zum triggern eines PC-Soundboard)
  • verschiedenste Annimationen der Spielfeld LED´s (hier habe ich zwar auch weitestgehend auf delay´s verzichtet, aber eben nicht überall möglich, sonst explodiert der code vor lauter "blink ohne delay" Klassen)
  • serielle Kommunikation mit dem 14 Segment Display-modul

Man müsste auch alle Befehle an die Magnetspulen zwingend innerhalb jeweils einer ISR ablaufen lassen, mit den daraus resultierenden Problemen. (Spulen sollen z.B. nach 100 ms geringeren Strom bekommen, also oftmals mehrere millis() Vergleiche in der ISR, andere interrupts während dieser zeit blockiert etc.)

Die klassische Vorgehensweise mit 1. setzen eines flags in der ISR 2. auswerten des flags im laufenden Programm durch Polling

funktioniert dann auch nicht mehr, da zu langsam

Arduino 1 soll bei jedem definiertem Kontakt ein Signal zu Arduino 2 übertragen. Kann ich einfach mit dem 1. Arduino einen interrupt pin am zweiten triggern? Wie müsste man diese verkabeln?

ach was ich noch vergessen habe: Die Spielfeld LED´s werden auch nicht über High/LOW an einem Pin des Arduino gesteuert, sondern es handelt sich um seriell angesteuerte RGB led´s (komplett) samt seriellem Übertragungsprotokoll und timing (die bekannten WS2812B "Neopixel")

das soll nicht heissen, das der teensy das nicht könnte (habe auch einen DUE hier rumliegen). Es geht eher um den dann notwendigen kompletten Verzicht auf delays mit damit einhergehenden programmier-Einschränkungen

Poste mal bitte deinen Sketch. Wenn man für die LEDs FastLed nimmt ist das eigentlich sehr schnell... letztendlich werden da die Daten an die LEDs so gesendet wie du sie auch an einen 2. Arduino senden würdest....

Anbei 2 Prozesse (von insgesamt 4), die "zeitgleich" laufen müssen, da ich ja einen Flipperfinger anziehen können möchte, obwohl die Kugel grade zwischen den slingshots "bounced"

Momentan eben simuliertes Multitasking, durch sehr schnelles durchlaufen der loop. jede Verzögerung ist da gift.

Heisst auf dem ersten Arduino darf nichts weiter (zumindest kein einziges delay) laufen. Im Hauptprogramm (auf dem 2. Ardu) komplett auf delays zu verzichten ist imho nicht oder nur mit unverhältnismäßigem Aufwand möglich.

//==================SLINGSHOT CONTROL=====================  

    if (digitalRead(Sling_pin_in) == HIGH && SlingTriggered == 0)
    {
        SlingTriggered = 1;
        SlingMillis = millis();
        digitalWrite(Sling_pin_out, HIGH);
    }     
    if (SlingTriggered == 1 && (millis() - SlingMillis) > 60) digitalWrite(Sling_pin_out, LOW); //Spulen-Impuls
    if (SlingTriggered == 1 && (millis() - SlingMillis) > 333) SlingTriggered = 0; //debounce
     

//==================LEFT FLIPPER CONTROL=====================  


   if (L_Flip_Triggered == 0 && digitalRead(Lflip_pin_in) == HIGH)
   {
     L_Flip_Triggered = 1;
     L_Flip_Millis = millis();
     digitalWrite(Lflip_pin_out, HIGH); // 100% voltage to flipper coil.
    }     
  

    if (L_Flip_Triggered == 1 && (millis() - L_Flip_Millis) > 100) // nach 100ms Impuls die Spannung reduzieren oder komplettt abschalten 
    {
        if (digitalRead(Lflip_pin_in) == HIGH) analogWrite(Lflip_pin_out, 80); // PWM drops voltage to flipper coil to 30%, around 7V.
      if (digitalRead(Lflip_pin_in) == LOW)
        {
            digitalWrite(Lflip_pin_out, LOW); //Spule abschalten
            L_Flip_Triggered = 0;
        }
     }

Ich seh das auch so wie der Threadstarter (der ja inzwischen wohl schon ne ganze Menge am Flipper umgebaut hat)

Hier ist es besser 2 oder 3 Controller zu nehmen und die kommunizieren zu lassen

@Dennis

Arduinos haben IRQ-Eingänge, man kann das triggern durch den Ausgang des anderen. Hast halt wenig Möglichkeiten etwas zu übergeben. Allenfalls eben eine Aufgabe dann machen lassen, von mir aus einen Zähler hochzählen. Für 10 Punkte muss man dann eben 10x auslösen.

Also ja, geht, es gibt sogar 2 solcher IRQ-Leitungen, was möglich macht 2 Dinge auszulösen.

http://playground.arduino.cc/Code/Interrupts

also einfach high impuls von 1. Arduino an einen Interrupt pin des 2. Arduino? und die masseleitungen beider verbinden?

1 simpler impuls (Bumper bzw. Slingshot wurde getroffen) würde mir schon reichen. mehr infos muss der 1. Arduino nicht übergeben.

Zeig mal bitte den Kompletten Sketch für alles. Die kürzeste Zeitspanne die ich jetzt gesehen habe sind 60ms.

In welchem Zeitrahmen bewegen sich den die mechanischen Abläufe? Was ist die kritischste Zeit?

Das ist quasi der ganze Sketch. Rest sind nur Variablen Deklaration sowie Festlegung der Pins(Input/output).

lass dich von den 60 ms nicht täuschen, in dieser Zeit wird (und muss auch) die gesamte loop 100e (oder sogar 1000e ?) Male durchlaufen werden, sonst ist das simulierte Multitasken mit den notwendigen schnellen Reaktionszeiten eines Flippers nicht möglich. Es wird ja hier kein 60 ms delay eingelegt!

Kritisch ist, das alles gleichzeitig funktionieren muss. Z.B. halte ich den linken flipperfinger oben, die kugel wird vom slingshot weggeschleudert und gleichzeitig möchte ich den rechten Flipperfinger anziehen. Da sind 50 ms delay, so unglaublich das jetzt klingen mag, eine Ewigkeit. D.h. es ist nicht mehr vernüftig spielbar.