Reliable Serial Read with Arduino

I’ve refactored my weather station project significantly in the last few days, having found the RF based communications between the the two Arduinos too unreliable for my purposes. So I’ve invested in a WiFi shield instead, specifically an Adafruit CC3300. It was quite expensive, but I have to say it’s working fantastically well. I am now posting data directly to my JSON interface from the externally located Arduino. This has freed up the second Arduino [and Raspberry Pi] for what I originally intended: some sort of permanent internal display. I’ve actually got this working pretty well in conjunction with an Adafruit 1.8″ colour TFT [lovely piece of kit]. A Perl script on the Pi is in a constant loop, pulling down various piece of data, such as an RSS feed from the BBC, and the latest weather data. I combine this with the time and, based on string prefixes, position it on the screen accordingly.

It’s brought a problem that I’ve struggled with in the past back into play: the reliability of Serial.Read(), and I’ve found a stable solution which I’ve not come across elsewhere:

char inByte = Serial.read();
if (inByte != '^')
{
   // serialText string is defined earlier, and overwritten each time through the main event loop:
   serialText = serialText + inByte;
   delay(20);
}

That delay() is enough to allow the serial buffer to refill and for me to reliably read the next character, up to the point that I hit the termination symbol I’m using. This has worked consistently for me now with the sending Perl script / receiving sketch merrily interplaying for days on end now, on 9600 baud. The serial comms are extremely sensitive to timing issues: for instance, before I put this delay in I was seeing different results on the Arduino between sending the data from the serial monitor on my Mac versus sending the same data from the Pi, via the Perl script. Suffice to say that your mileage may vary…

One other approach I’ve tried out is with the displaying of text. The TFT library doesn’t appear to support a delete function without zapping the entire display, so when I update the time display, which I send down the serial port every 10 seconds, I hold the prior value in a string, then display that in the background colour [black], display the new value, and finally set that for the buffer for deletion next time round:


// This is the prefix identifying that the string is the time:
String msgCheck = serialText.substring(0,5);
if (msgCheck == “TIME:”)
{
// There is a space so shuffling the substring over 1. Could take the space out but…!
String timeString = serialText.substring(6);
tft.setTextSize(3);
tft.setCursor(0,10);
// delete the displayed time:
tft.setTextColor(ILI9340_BLACK);
tft.println(lastTimeMessage);
tft.setTextColor(ILI9340_BLUE);
tft.setCursor(0,10);
tft.println(timeString);
// set the value to the current time for the next delete operation
lastTimeMessage = timeString;
timeString = “”;
}

A final observations on the TFT library: the very accurate placement of the background colour text for deletion only seems to work if all of the text being displayed is the same size: so a write / delete cycle will only work with the correct placement of the cursor if all other interim writes around the screen are the same size text.