Ich habe mir gerade mal erlaubt das hier auf dem Uno zu testen
ergibt auch bravCode:void setup() { // put your setup code here, to run once: Serial.begin(9600); int a,b,c; String test = "1 2 3"; sscanf(test.c_str(), "%d %d %d",&a, &b, &c); Serial.print("a = "); Serial.println(a); Serial.print("b = "); Serial.println(b); Serial.print("c = "); Serial.println(c); } void loop() { // put your main code here, to run repeatedly: }
Nachteil: Der kleine Sketch belegt bereits 4780 Bytes Flash und 228 Bytes RAM.a = 1
b = 2
c = 3
Normalerweise nehme ich sprintf usw. nur auf dem Teensy. Da gehen aber auch C++ strings und die Konvertierungsfunktionen aus C++14.
dass das so funktioniert, ist schon klar, die Frage war, wie der OP seinen buffer string generieren soll (bei dir ist er ja fix und heißt test, also kein kontinuierlicher Serial stream).
Das Konvertieren der Einzel-Tokens zu Zahlen dann wäre das geringere Problem.
Ich hatte dazu ja \n als Trennzeichen der Gruppen vorgeschlagen - dann müsste man in Tokens aufteilen und umwandeln, wie ich ebenfalls bereits schrieb
- wie auch immer man das tun will, entweder über Arduino Funktionen oder meinetwegen auch über sscanf.
Aber ohne eindeutige Gruppen-Trennung wird das kaum zuverlässig funktionieren.
Das stimmt, die Gruppentrennung kann aber auch am Anfang der Daten stehen.
Ich hatte schon mal industrielle Sensoren wo das so aussah:
- Paketanfang mit Steuerzeichen STX (Start of Text oder Start of Transmission, siehe ASCII-Tabelle)
- Zeichen das Pakettyp beschreibt
- Je nach Pakettyp unterschiedlich viele Daten
Wahrscheinlich stammt das noch aus Zeiten wo Speicher sehr knapp war. Sowas kann man in der Tat auch "on the fly" parsen, ohne alle Daten im Arbeitspeicher zu behalten.
also warum dann nicht
String buffer=Serial.ReadStringUntil('\n');
und dann den String teilen und umwandeln?
Geändert von HaWe (15.10.2017 um 08:23 Uhr)
Ich bevorzuge eigentlich das Lesen einzelner Zeichen, die ich dann selbst in Array oder string hinzufüge.
+ Man kann da einen Timeout einbauen
+ Falls die Gegenseite mal das \n vergisst, kann man aufhören wenn es zuviel wird (die Teensy Implementierung von readStringUntil hat im Gegensatz zu Arduino eine einstellbare Maximallänge)
+ Man kann auch Zeilenenden wie \r\n beachten
+ Steuerzeichen kann man ignorieren, z.B. Falls da jemand auf der Gegenseite von Hand tippt
+ Spezialprotokolle wie das obige mit STX kann man gut behandeln, einfach erst mit dem Lesen anfangen, wenn man ein Startzeichen gesehen hat
- - - Aktualisiert - - -
Ok, immerhin einen Timeout haben sie bei Arduino
beim Teensy sieht die Funktion so ausCode:String Stream::readStringUntil(char terminator) { String ret; int c = timedRead(); while (c >= 0 && c != terminator) { ret += (char)c; c = timedRead(); } return ret; }
Das ist ist ja fast wie bei dem Bug in der Arduino map Funktion ...Code:String Stream::readStringUntil(char terminator, size_t max) { String str; size_t length = 0; while (length < max) { int c = timedRead(); if (c < 0) { setReadError(); break; // timeout } if (c == 0 || c == terminator) break; str += (char)c; length++; } return str; }
man kann vieles tun, auch ein eigenes TCP programmieren, aber hier heißt es doch: KISS, und trotzdem halbwegs sicher!
Problem bei Serial/UART sind Datenübertragungsfehler, und kaum ist mal 1 Trennzeichen falsch übertragen/gelesen, sind die ganzen Daten async.
Also ein definiertes Ende, was auch dann den neuen Start synced!
Also was ist einfacher als
String buffer=Serial.ReadStringUntil('\n');
und dann den String teilen und umwandeln?
Geändert von HaWe (15.10.2017 um 08:22 Uhr)
Lesezeichen