Sunday, 10 September 2017

The fight to read an ASCII string into Arduino

If you have a terminal program sending characters of a string input at 9600 baud to the USB port of an Arduino, then they arrive in just over 1ms per character. In 1ms the Arduino can do a lot of things.

So a program like this won't work,

//  GET  MESSAGE
// Try to get a message in from the terminal
void getMsg(char *m) }
  int p;
  
  p = 0;
  while (Serial.available() > 0) {
   m[p++] = Serial.read();
  }
}

Why? Because after the first character arrives and Serial.Available() says it has done so, the next line Serial.read() happens very fast, a long time before the next character at 9600 baud arrives. So the next pass of the while loop fails, as there is no character in the RAM buffer.

What to do? Well wait for the next character before trying to read it, of course. Like this

// GET MESSAGE
// get line m (EOL '\n')
bool getMsg(char *m) {
  int p;

  if (Serial.available() > 0) {                 // data available ?
    p = 0;
    while ((m[p] = Serial.read()) != '\n') {    // end of line?
      p++;
      while (!Serial.available());              // wait for next char
    }
    m[p] = '\0';                                // terminate string
    return true;                                // data received
  }
  return false;                                 // no data
}

Here you can see that after the first iteration of the while loop and the Serial.read() we wait for the next character to arrive.

The next problem is to know when all the string's characters have been read, and this is done by marking the end of the input with a special character - in this case the program expects a LF or '\n'. You must make sure your terminal is set up to end the line it sends with this character.

Screen Shot 2017 09 10 at 17 13 15

No comments: