For a while, I have been receiving serial data the same way. Serial data is often a control mechanism for a ATmega328P that in terms of priority, 1) keeps accurate time, 2 multi-plexes an LED matrix and 3 receives serial and everything else. The timekeeping is done using ISR, but the matrix update happens every 1388 micros(). For this reason, I can't dwell on any part of the rest of the program for too long. Serial commands have thus far been fixed width, partly for compatibility, but also to eliminate delimiter characters and reduce the overall string width. So, to do this, I count characters and compare each one against a condition. The width is usually 6-9 characters, an initializing byte, 1-3 parameter bytes, and a numerical value in ASCII. It looks like this...
void updateBCD() {
static unsigned long serialInTimestamp;
static byte charsRead = 0;
static char serialBuffer[6] = {'\0'};
if (charsRead > 0) {
if (millis() - serialInTimestamp >= 100UL) {
memset(serialBuffer, '\0', sizeof serialBuffer);
charsRead = 0;
}
}
if (Serial.available()) {
int c = Serial.read();
if (charsRead == 0) {
if (c == 'T') {// initializer
serialInTimestamp = millis();
serialBuffer[charsRead] = c;
charsRead++;
}
else {
memset(serialBuffer, '\0', sizeof serialBuffer);
charsRead = 0;
}
}
else if (charsRead == 1) {
if (c == 'D') {// parameter
serialBuffer[charsRead] = c;
charsRead++;
}
else {
memset(serialBuffer, '\0', sizeof serialBuffer);
charsRead = 0;
}
}
else if (charsRead >= 2 && charsRead <= 5) {
if (c >= '0' && c <= '9') {
serialBuffer[charsRead] = c;
charsRead++;
}
else {
memset(serialBuffer, '\0', sizeof serialBuffer);
charsRead = 0;
}
}
}
if (charsRead > 5) {
if (serialBuffer[0] > 0) {
byte receivedBcdValue[4];
receivedBcdValue[0] = (serialBuffer[2] - '0');
receivedBcdValue[1] = (serialBuffer[3] - '0');
receivedBcdValue[2] = (serialBuffer[4] - '0');
receivedBcdValue[3] = (serialBuffer[5] - '0');
if (receivedBcdValue[0] != bcdValue[0] || receivedBcdValue[1] != bcdValue[1] || receivedBcdValue[2] != bcdValue[2] || receivedBcdValue[3] != bcdValue[3]) {
bcdValue[0] = receivedBcdValue[0];
bcdValue[1] = receivedBcdValue[1];
bcdValue[2] = receivedBcdValue[2];
bcdValue[3] = receivedBcdValue[3];
}
}
memset(serialBuffer, '\0', sizeof serialBuffer);
charsRead = 0;
}
}
Each time the project changes function, or control, the command string changes, and so each project I have to code this a little different. it can be time consuming to code.
Ideally, I would like to write an object class with a constructor that will establish the fixed width and valid pattern, and have a method that is called, like this function to receive each byte of serial and validate it.
I have looked at various regular expression tutorials, but most of them seem to have the goal of returning the pattern match in a large body of text.
Can the way I am doing this be imrpoved?