[I posted this to the Arduino developer’s mailing list, but figured others might find it useful too]
When I first started with Arduino, I thought Serial.available() was a very loose wrapping of the RXC bit in the USCRA register, i.e. if I didn’t get data out of there fast, it’d be gone. That led to convoluted code like:
if( Serial.available() ) {
val1 = Serial.read();
while( !Serial.available() );
val2 = Serial.read();
// and so on
}
Yuck. So you end up designing protocols that are too terse. Or maybe you think you need to buffer so you don’t lose it:
while( Serial.available() ) {
commandbuffer[i++] = Serial.read();
}
Then parsing becomes a two step process: read serial, parse buffer. Confusing to newbies perhaps, but at least it allows for a better protocol down the line. (And descend into madness as you gaze into the maw of strtok())
Because Serial contains these big comfy buffers, we often don’t need a second buffer to let us easily implement good protocols. My current favorite is to do something like this:
// protocol is "CCaaaa", two bytes of command, four bytes of args
if( Serial.available() >= 6 ) { // command length is 6 bytes
cmd0 = Serial.read();
cmd1 = Serial.read();
arg0 = Serial.read();
arg1 = Serial.read();
// ...etc...
}
I don’t think I’ve seen any Serial examples that check for a specific number of bytes available. It’s really handy.
Implementing a human-friendly protocol like “command arg0 arg1 arg2”, where command and args are space-separated strings like “servo 12 0xff”, is currently hard with Serial. I do this right now with a 2nd buffer and lots of C hackery:
char* cmdbuf; char c; int i;
while( Serial.available() && c!= '\n' ) { // buffer up a line
c = Serial.read();
cmdbuf[i++] = c;
}
int i = 0;
while( cmdbuf[++i] != ' ' ) ; // find first space
cmdbuf[i] = 0; // null terminate command
char* cmd = cmdbuf; //
int cmdlen = i; // length of cmd
int args[5], a; // five args max, 'a' is arg counter
char* s; char* argbuf = cmdbuf+cmdlen+1;
while( (s = strtok(argbuf, " ")) != NULL && a < 5 ) {
argbuf = NULL;
args[a++] = (byte)strtol(s,NULL,0); // parse hex or decimal arg
}
int argcnt = a; // number of args read
This sort of functionality would be great in a library I think. Maybe not in Serial, but a core class.
Any other protocols people like to use and the Arduino code they use to do it?