[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?