Serielle Daten einlesen

Hallo,

ich möchte (zum ersten mal) serielle Daten von einem Gerät in einen Arduino Mega einlesen und verarbeiten.

die Daten werden vom Quell-Gerät Zeilenweise ausgegeben und enden immer mit LF/CR

Sie kommen kontinuierlich mit 57600 baud.

Die Daten sehen z.B. so aus:

DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00000030,000014A6,,,00001D2C,BF
BT3,0000,00000AC0,,,0000043C,00000158,00053FC0,00000030,000014A6,00004578
usw...

Mit diesem Code lese ich die Daten ein, was unter “manuellen” Testbedingungen auch einwandfrei funktioniert (Manuell heißt ich schicke dem Mega per Terminal immer eine längere Zeile und schaue, ob er sie als Zeile erkennt):

int ndx = 0; //Index für eingelesene Zeichen
char rc; // Zeichen als Char
int rcint; // Zeichen als ascii
int i;  // Zähler

char receivedChars[200]; // Array für die Zeichenkette

boolean newData = false;

void setup() {
    Serial.begin(57600);     // Serieller Monitor
    Serial1.begin(57600);    // Eingang Daten
    Serial.println ("Start...");
}

void loop() 
{
    while (Serial1.available()) 
    {
        rc = Serial1.read(); //Zeichen einlesen
        rcint=rc; //ascii wert des aktuellen Zeichens 
        receivedChars[ndx] = rc; //Zeichen in Array ablegen
        ndx++;
        if (rcint==13)  // Prüfen, ob Zeilenende erreicht ist, dann Zeile Auswerten
        {
           newData = true;
           Serial.println ("Zeile empfangen: ");
        }
     }
    
     while (newData) // Auswertung wenn neue Daten da sind
     {
        i=0;
        while (i<ndx)
        {
           Serial.print (receivedChars [i]);
           i++;
        }
        Serial.println ();
        ndx=0;
        newData = false;
     }
}

Ergebnis (fünf mal ein und die selbe Zeile per Hand geschickt):

Start...
Zeile empfangen: 
DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00000030,000014A6,00004578,0000090C,00001D2C,BF

Zeile empfangen: 

DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00000030,000014A6,00004578,0000090C,00001D2C,BF

Zeile empfangen: 

DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00000030,000014A6,00004578,0000090C,00001D2C,BF

Zeile empfangen: 

DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00000030,000014A6,00004578,0000090C,00001D2C,BF

Zeile empfangen: 

DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00000030,000014A6,00004578,0000090C,00001D2C,BF

So weit alles bestens, aber wenn ich jetzt an das Gerät gehe, werden die Daten nicht vernünftig hintereinand eingelesen. Nach einer Weile hängt der Arduino dann ganz an irgend einer Stelle.
Hier habe ich zum Testen einmal den oben benutzten String fünf mal hintereinander über eine Datei an den Arduino geschickt. Die erste Zeile liest er noch richtig, dann fehlen plötzlich Stellen aus dem String:

Start...
Zeile empfangen: 
DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00000030,000014A6,00004578,0000090C,00001D2C,BF

Zeile empfangen: 
DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00030,000014A6,00004578,0000090C,00001D2C,BF

Zeile empfangen: 
DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,00004578,0000090C,00001D2C,BF

Zeile empfangen: 
DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,0004578,0000090C,00001D2C,BF

Zeile empfangen: 
DT1,0000,00000AC0,FFFFFFFF,FFFFFFFF,0000043C,00000158,00053FC0,0004578,0000090C,00001D2C,BF

Wer hat einen Tipp, was ich da falsch mache?

Vielen Dank und viele Grüße

Ernst

Ich vermute mal, daß es die Ausgabe ist, die zu Fehlern beim Einlesen neuer Daten führt. Der Ausgabepuffer von Serial hat AFAIR nur 64 Byte, danach muß der Controller warten, bis ein weiteres Zeichen in den Ausgabepuffer paßt. Dann sollten die Probleme mit einer ausreichenden Pause zwischen zwei Zeilen an den Arduino verschwinden. Deine Handeingabe hat auch genug Zeit für das Echo gelassen, deshalb ging da alles gut.

Setze mal die Baudrate der Ausgabe auf 250.000 oder 500.000

Wenn du mit dem String danach was machen willst musst du den übrigens mit Null terminieren. Mit der Ausgabe Zeichen für Zeichen geht das auch so, aber für mehr taugt es nicht

DrDiettrich hat Recht mit seiner Vermutung.
Das Problem ist das “kontinuierlich” im Satz

Sie kommen kontinuierlich mit 57600 baud.

Vermutlich hättest du genug Zeit für eine Auswertung und eine zusammenfassende Ausgabe (< 64 Zeichen), oder -wenn die komplette Ausgabe tatsächlich erforderlich ist- das Weiterleiten jedes einzelnen Zeichens sofort und mit z.B. 115200 Baud

Danke!!!

Das ging ja schnell und war auch promt die Lösung :slight_smile:

Ausgabe-Baudrate ist jetzt 115200 und nun kommen die Daten hintereinanderweg auf dem Monitor an (meist).

"maximal 64 Zeichen Ausgabepuffer", da muss ich jetzt noch einmal fagen:

Die Serielle Ausgabe auf dem Monitor brauche ich nur für Testzwecke, später soll das Programm jede Zeile auswerten, sich einige Daten aus jeder Zeile herausnehmen und diese z.B. über ein LCD Display darstellen oder eine Mail schicken, wenn irgend etwas kritisch ist.

Ich wollte jeden String erst einmal einzeln in das Array einlesen (z.B. wären manche dann aber auch 100 Zeichen lang), dann in einer Subroutine die Daten aus dem String herausziehen, sie weiter verarbeiten und dann wieder zum Einlesen des nächsten Strings zurückkehren.

Kommen mir dabei dann auch die maximalen 64 Zeichen in die Quere? Ich würde den String ja nicht mehr seriell zum Monitor schicken wollen)

Viele Grüße

Ernst

Nein, das geht schon. Auch der Eingangspuffer hat 64 Bytes. Das passt auch wenn man ihn schnell genug ausliest

Ales klar, DANKE an alle für die superschnelle Hilfe!

Ernst