Datenverlust beim Schreiben auf serielle Arduino-Schnittstelle. Überlauf?

Ich habe ein Arduino mit einer Linux-Box (einem Raspberry Pi) verbunden. Ich lese einen analogen Pin und schreibe ihn zusammen Serial.println()mit dem Wert von millis()The serial port is running at 9600bps

Etwas in der Art von:

void Setup() {
Serial.begin(9600)
}
void loop() {
    Serial.print(analogRead(A0));
    Serial.print("\t");
    Serial.println(millis());
}

Auf der Empfängerseite sehe ich einen kontinuierlichen Strom von 5 oder 6 Sekunden, dann eine Lücke von 2 Sekunden ohne Daten, dann weitere 5 oder 6 Sekunden voller Daten. Ich habe es nicht live "gesehen", sondern den Wert von millis () mit Daten gezeichnet, die von der seriellen Schnittstelle gelesen wurden.

Ich denke, es könnte sein, dass die Daten im Schreibpuffer des Arduino verloren gehen oder dass etwas anderes alle 5 oder 6 Sekunden Prozessorzeit benötigt (es ist ein unbenutztes Ethernet-Schild angebracht) oder vielleicht schreibt die serielle Schnittstelle in Bursts.

Wenn ich die Baudrate auf 115200 erhöhe, bekomme ich immer noch Zeitlücken, aber sie scheinen zufälliger zu sein.

Aktualisieren:

Durch Erhöhen der Baudrate auf 38400 wurden die Lücken in den Samples entfernt (Lücken gemessen in Arduino Millis () Zeit)

Eine andere seltsame Sache war:

Auf der Empfängerseite habe ich cat gemacht /dev/ttyACM0und es geleitet, awkwodurch die Systemuhr zu jeder empfangenen Zeile hinzugefügt wurde. Dann habe ich die empfangene Zeit gegen die Systemzeit aufgetragen, und es war keine gerade Linie, sondern eine leiterartige Darstellung. Unnötiges entfernt catund die Zeit war wieder normal.

Es stellt sich heraus, cat /dev/ttyACM0 | awk {print}ist nicht dasselbe wie </dev/ttyACM0 awk {print}. Es scheint, dass die Katze eine seltsame Pufferung durchführt.

Jetzt scheine ich jeden vom Arduino gelesenen Wert zu bekommen.

Ich bin mir nicht ganz sicher, was du mit live gesehen und dem Plotten meinst. Ist der Abstand zwischen allen Zeilen ungefähr gleich oder gibt es auch Lücken? Welches Linux-seitige Tool / Befehlszeile verwenden Sie zum Lesen der Daten? Können Sie ein Beispiel für die gedruckten Daten geben?
Trennen Sie zuerst die Ethernet-Abschirmung. Zweitens überlaufen Sie möglicherweise den seriellen Puffer. Setzen Sie am Ende Ihrer Schleife einen 10-ms-Schlaf. Ändern Sie dann den Schlafwert je nach Ergebnis nach oben oder unten.
Ich habe die Baudrate auf 38400 geändert und die Zeitlücken scheinen verschwunden zu sein.

Antworten (2)

analogRead() gibt 2- bis 3-stellige Werte zurück, sagen wir 3. millis() wird schnell auf 4- und 5-Zeichenwerte anwachsen, und mit dem Tabulator und dem Zeilenumbruch sind das ungefähr 10 Zeichen, die bei jeder Ausführung der Schleife generiert werden.

Bei 9600 Baud kann Ihre serielle Schnittstelle etwas weniger als 1000 Zeichen/Sek. oder knapp 100 10-Zeichen-Zeilen/Sek. schreiben. Ihre Schleife könnte leicht schneller als 100 Mal / Sekunde laufen, und wenn dies der Fall ist, läuft der serielle Ausgangspuffer zweifellos über. Sie müssen 10 ms oder mehr in der Schleife verzögern, damit der serielle Anschluss aufholen kann. 115K Baud ist 12-mal so schnell, sodass Sie die Verzögerung (sobald Sie wissen, wie viel Sie benötigen) um diesen Faktor für die höhere Baudrate reduzieren können.

9600 bps = 960 char/sec (nicht 96 wie Sie vorschlagen)
Meine Güte (aber was ist eine Null unter Freunden? <erröten>) Danke für den Haken - zur Behebung editiert.
Ich denke, die seriellen Routinen sollten blockieren, anstatt den Puffer zu überlaufen, aber angesichts der Schrottigkeit vieler anderer Arduino-Code-Interna würde es mich nicht überraschen.

Zwei Möglichkeiten wie ich sehe:

  1. Ihr Programm ist tatsächlich viel größer als das, was Sie uns zeigen, und tatsächlich erleben Sie eine Art Stapelüberlauf, der effektiv zu zufälligen Neustarts führt

  2. Viel wahrscheinlicher ist, dass Ihr "Problem" auf dem RasPi liegt und der eingehende serielle Datenverkehr gepuffert wird, bevor er an Ihre (ganz oben im Anwendungsstapel), vermutlich Python, Anwendung geliefert wird

Wenn Sie sicher sein wollen, dass die Bytes so schnell wie möglich aus dem Arduino herauskommen, rufen Sie Serial.flush() am Ende jeder Schleife (oder nach jedem Serial.print*) auf.

Das Programm ist nur ein bisschen länger als das, aber nicht viel, und keine Neustarts, da dies dazu führen würde, dass millis() auf 0 zurückgesetzt wird.