Hello everyone,
for a device I made, I need to use a "sliding (or Ring) buffer to compare incoming data against a given string.
Hoever, I tend to lose characters if the opposite side is sending continuously. I know the serial buffer of the Atmega328P should be internally 64 byte, and I can receive up to 75 or 76 characters in a row without problems. Then it starts to skip single characters on reception, and I will miss my expected string to react upon.
Here is the related piece of code - note there is a "setupMode" path that's uncritical, since I have to switch between a "Setup" mode where I can enter configurations interactively via serial line, that will be parsed for commands and parameters, and a "Run" mode that does no parsing but just looks for the one expected string and reacts to it if found - only the latter one is of interest here.
...
// some globals used:
#define SER_LEN 20
String strbuf="";
String ser_expect = "expected_string";
String ser_send = "some_answer";
...
void doSerialPort() {
char ch = ' ';
// read one character from serial: ...
while (Serial.available()) {
ch = Serial.read();
if ( setupMode ) {
// ...
// ... do parsing etc.
// ... clear "strbuf" in the end again
// ... not of interest, works well ...
}
else {
// Run Mode - fill buffer to SER_LEN maximum, else rotate left:
if ( strbuf.length() < SER_LEN ) {
strbuf += ch;
}
else {
strbuf = strbuf.substring(1, strbuf.length()) + ch;
}
if (ser_expect != "") {
// try to find "ser_expect" in serial read buffer:
if ( (strbuf.indexOf(ser_expect) >= 0 ) || ( ser_expect == "*") ) {
// expected string found - check if some timer needs notification
for (int i=0; i<NUM_TIMERS; i++) {
if ( tmr[i].assign & B00000100) {
tmr[i].events |= B00000100;
}
}
// then clear serial read buffer:
strbuf = "";
if (ser_send != "") {
// if there is something defined to send after having received the matching code, send it now:
Serial.println(ser_send);
}
}
}
}
}
}
From pure logic, the code does work like it should. If characters come in one by one, everything is fine.
Now, I'd expect that a) using the convenient but bloaty "String" variables make things slow, and b) the shifting around of "strbuf" in general is too slow and will cause characters to be missed.
I'd be glad to see some hints how to squeeze the most performance out of this "else ...." code section, in order to not miss a character (at 115200Bd).
BR
stargar