Strings sind ein klasse Sache, wenn es um solche Dinge geht. Aber sie sind wohl sehr speicherintensiv. Ich habe noch nicht so viel Erfahrung, was das angeht, aber ich glaube, dass Du Eingaben besser in Form von C-Strings (char-Arrays, die mit 0 aufhören) händeln (oder Beethoven könntest.
Das könnte die Lösung Deines Problems, wenn sie denn gefunden wird, erheblich schneller machen.
Nachtrag: Ups, ich sehe gerade den letzten Satz Deines letzten Postings. Ich würde eher das Problem lösen, die Eingabe als C-String zu erfassen, als zu gucken, wie Du den String zerschnippeln kannst.
Dann machst du was falsch.
Aber leider kann ich nicht erkennen, was..
Ja, die Stringklasse macht Sorgen auf kleinen AVRs.
Je kleiner der Heap, desto problematischer.
Genauer: Die dynamische Speicherverwaltung bereitet die Sorgen.
Selbst bei sorgfältiger Programmierung neigt der Speicher(Heap) zur Fragmentierung.
Und dann knallts irgendwann...
Erst mal eine Funktion mal um Text allgemein einzulesen (geht nicht nur mit Serial, sondern auch mit SD oder Ethernet!):
const int SERIAL_BUFFER_SIZE = 20;
char serialBuffer[SERIAL_BUFFER_SIZE];
bool readSerial(Stream& stream)
{
static byte index;
while (stream.available())
{
char c = stream.read();
if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
{
serialBuffer[index++] = c;
}
else if (c == '\n' && index > 0)
{
serialBuffer[index] = '\0';
index = 0;
return true;
}
}
return false;
}
Dann diese Verwenden und eine Parser dazu schreiben:
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (readSerial(Serial))
{
Serial.print("Read: "); Serial.println(serialBuffer);
parseSerial();
}
}
void parseSerial()
{
char* cmd = strtok(serialBuffer, ":");
if (strcasecmp_P(cmd, PSTR("time1:")) == 0)
{
int hour = atoi(strtok(NULL, ":"));
int minute = atoi(strtok(NULL, ":"));
int second = atoi(strtok(NULL, ":"));
Serial.println(cmd);
Serial.println(hour);
Serial.println(minute);
Serial.println(second);
Serial.println("---");
}
}
Die Zeit kann man allerdings auch anders machen, solange man immer 2 Stellen pro Teil macht:
void parseSerial()
{
if (strncasecmp_P(serialBuffer, PSTR("time1:"), 6) == 0)
{
char* ptr = serialBuffer + 6;
int hour = atoi(ptr);
int minute = atoi(ptr + 3);
int second = atoi(ptr + 6);
Serial.println(hour);
Serial.println(minute);
Serial.println(second);
Serial.println("---");
}
}
Also einfach Ausnutzen dass die Position der Teile bekannt ist wenn man sich genau daran hält. Dann darf man aber auch keine Abweichungen bei der Angabe machen. strtok() ist da flexibler. Und braucht auch kaum Speicher.
Den SerialMonitor dabei ein LF/newline am Ende senden lassen! Sonst geht es nicht
Da werde einige nette Sachen gezeigt wie man Integer direkt einlesen kann ohne erst mal über einen String zu gehen. Sollte man mal gemacht haben und ihn manchen Fällen ist es von Vorteil.
Ich finde aber mit einem String ist man flexibler. Da kann viel leichter das Format anpassen ohne viel am Code zu ändern. Die Einlese-Funktion bleibt immer gleich und man muss nur den Parser ändern. Und man kann mehrere verschiedene Parser im gleichen Programm haben.
Wenn man Text + Daten kombiniert, geht es gar nicht anders. Also wie hier:
time:xx:xx:xx
oder:
date:xx.xx.xx
Eine Sache mit der man sich hier das Leben etwas vereinfachen kann ist wenn man statt eines ganzen Wortes nur einen Buchstaben voranstellt. Also hier 't' oder 'T'. Dann reicht ein switch/case für die Abfrage.