Serielle Daten im Hintergrund Empfangen und im Puffer speichern

Hallo,

Ich dachte seriell gesendete Daten werden im Hintergrund empfangen und im Pufferspeicher abgelegt.

ich sende auf Knopfdruck seriell Daten (5Byte) an mein Arduino Mega 2560. Ich verwende die Serial3 Schnittstelle. Die Daten werden einmal in der Loop eingelesen. Anhand der empfangenen Daten wird ein Case aufgerufen. Einige Case sind sehr zeitkritisch da ich sehr viele Daten auf LED-Stripes schreibe. So dass ich nicht öfters die serielle Schnittstelle auslesen kann oder Interrupts verwenden kann.
Ich lese die Daten mit:

Serial3.readBytesUntil(';', data, 5);
nextCase=atoi(data);

ein. Leider erfolgt aber in rechenaufwändigen CASEs keine Änderung. Es werden keine neuen Daten eingelesen. Welche Lösung gibt es?

Danke Marie

readBytesUntil() ist problematisch

Am einfachsten geht es so:

const int SERIAL_BUFFER_SIZE = 10;     //bei mehr Daten die Größe hier anpassen
char serialBuffer[SERIAL_BUFFER_SIZE];

void loop()
{
    if(readSerial() == true)
    {
        //Auswertung hier
    }
}

bool readSerial()
{
  static byte index;

  while(Serial3.available())
  { 
     char c = Serial3.read();
 
     if(c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
     {
        serialBuffer[index++] = c;
     }
     else if(c == '\n')
     {
       serialBuffer[index] = '\0';
       index = 0;
       return true;
     }
  }
  return false;
}

Wichtig ist hier, dass du deine Zeilen mit einem Linefeed abschließt. Sonst funktioniert das nicht! Man kann auch was anderes nehmen, aber LF (oder CR) kann man im Serial Monitor automatisch einstellen.

Dann wird ständig nachgeschaut ob was im Eingangspuffer ist und die Funktion gibt false zurück solange nicht alles da ist. Wenn eine Zeile da ist, hat man true und schickt die Daten durch einen Parser.

Wenn du mehrere Werte hast und diese mit einem Strichpunkt trennen willst, schau dir strtok() an. Damit kann man dann sowas schicken: “123;456;789” und so in drei Zahlen wandeln:

int num1 = atoi(strtok(serialBuffer, ";"));
int num2 = atoi(strtok(NULL, ";"));
int num3 = atoi(strtok(NULL, ";"));

MarieE:
Einige Case sind sehr zeitkritisch da ich sehr viele Daten auf LED-Stripes schreibe.

Was für LEDs sind das?

Bei WS2811/WS2812 LEDs kannst Du es vergessen, irgendwelche Daten gleichzeitig auf Serial zu Empfangen, während Du die LED-Streifen aktualisierst.

Alle Arduino-Libraries zur Ansteuerung von WS2811/WS2812 deaktivieren sämtliche Interrupts auf dem Controller, während die LED-Aktualisierung läuft. Sonst läßt sich das enge Timing auf der Datenleitung nicht einhalten.

Ein Empfang von Daten über Serial funktioniert dann nur, wenn Du Pausen bei der Ansteuerung der LEDs machst. Weil der Empfang von seriellen Daten über Interrupts funktioniert. In den Pausen kannst Du serielle Daten empfangen. Falls Du Deine LEDs "praktisch ständig" neu aktualisierst, ist auf dem Controller der Empfang serieller Daten ebenfalls "praktisch ständig" blockiert.

hi,

wie jurs richtig schreibt, kannst Du es vergessen, daten WÄHREND des sendens zum stripe zu empfangen, aber dazwischen geht es natürlich.

Du schreibst nicht, wer die daten auf knopfdruck sendet. falls es, wie ich annehme, ein anderer arduino ist (oder halt was ähnliches), dann sende diesem seriell ein signal, daß der mega bereit zum empfang ist, sobald die daten auf dem stripe sind, und empfange dann bis zum nächsten senden der led-daten.

gruß stefan

sende diesem seriell ein signal, daß der mega bereit zum empfang ist, sobald die daten auf dem stripe sind, und empfange dann bis zum nächsten senden der led-daten

Software - Handshake hat es in sich.
Noch dazu gehört:
Wenn er "bald" wieder den WS2812-Stripe aktualisieren will, sollte er zuerst ein Signal senden, dass er nichts mehr empfangen kann, und dann noch lange genug warten, falls evtl. währenddessen was reinkommt.
Traditionell werden für so ein Signal gerne die ASCII Zeichen XON (0x11) und XOFF (0x13) verwendet.

Wenn du statt 5 Bytes nur 1 Byte sendest, geht übrigens nichts verloren auf HardwareSerial :wink:
Was wird denn da "per Tastendruck" übertragen?

Oder dein Mega quittiert den Empfang und der andere wiederholt bei fehlender Quittierung.
Oder der Mega sendet jedes Zeichen wieder zurück als Quittung, und der andere sendet das nächste Zeichen erst danach, oder oder oder ...

hi, michael,

das problem sehe ich nicht. B muß A nicht sagen, daß er nichts mehr empfangen kann, sondern im gegenteil nur, wann er zeit zum empfang hat. also direkt nach jedem beschreiben der stripes.

bei 30 fps also 30mal ein, meinetwegen, XON. direkt auf das XON sendet der andere dann die seriellen daten. was Du meinst, ist nur notwendig, wenn die zeitscheiben nicht regelmäßig sind (und natürlich oft pro sekunde).

gruß stefan

stefan:
direkt auf das XON sendet der andere dann die seriellen daten

Wenn er das tut und sonst nicht, ist gut.

Das wäre eher ein Protokoll mit Request/Response, kann man auch machen.
Da ist dann die Frage, wie lange ist die Toleranz für "direkt". Wann kannst du annehmen, dass wohl doch nichts mehr kommt?