LCD Flickering with Wrong Values from Serial Input

I've built a process monitor which uses the psutil library to send data to my arduino formatted comma delimited. I am however encountering a flickering issue with the display in which it displaying the wrong data. I believe it is either shifting the information one character to either side, or picking up erroneous information via the serial.

Data is sent every 0.1 seconds so the update rate is quite quick, but I am confident the arduino can handle this. I have tested the display using a for loop to increment and print as fast as possible to the display and have no flickering issues such as I am experiencing.

As you can see the flicker at the location of the decimal places. It is hard to capture on photo but the flicker is very annoying in person as the whole thing flickers similarly especially the second line.

Data example: 33996,900660

I'm not sure how to troubleshoot this issue aside from trying different approaches and seeing if it fixes it. Due to it only happening at high rates of serial transfer It's hard to troubleshoot what the arduino "sees" because I can not receive the data back via serial in my setup.

My thoughts would be to implement a start and end delimiter, or sprintf formatting to format the floats specifically, however sprintf doesn't support float formatting on the arduino. When I had the text referenced to the numbers with spaces the entire messages moved as well so it has something to do with location referencing or losing a digit somewhere.

Any ideas or suggestions would be appreciated.

/*
 * SerialReceiveMultipleFields sketch
 * This code expects a message in the format: 12,345,678
 * This code requires a newline character to indicate the end of the data
 * Set the serial monitor to send newline characters
 */

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 
byte downArrow[8] = {
	0b01110,
	0b01110,
	0b01110,
	0b01110,
	0b01110,
	0b11111,
	0b01110,
	0b00100
};
byte upArrow[8] = {
        0b00100,
	0b01110,
	0b11111,
	0b01110,
	0b01110,
	0b01110,
	0b01110,
	0b01110
};
 
 
const int NUMBER_OF_FIELDS = 2; // how many comma separated fields we expect
int fieldIndex = 0;            // the current field being received
unsigned long values[NUMBER_OF_FIELDS];   // array holding values for all the fields
float upload = 0;
float download = 0;


void setup()
{
  Serial.begin(115200); // Initialize serial port to send and receive at 9600 baud
  lcd.begin(16,2);
  lcd.createChar(0, downArrow);
  lcd.createChar(1, upArrow);
}

void loop()
{
  if( Serial.available())
  {
    char ch = Serial.read();
    if(ch >= '0' && ch <= '9') // is this an ascii digit between 0 and 9?
    {
      // yes, accumulate the value if the fieldIndex is within range
      // additional fields are not stored
      if(fieldIndex < NUMBER_OF_FIELDS) {
        values[fieldIndex] = (values[fieldIndex] * 10) + (ch - '0'); 
      }
    }
    else if (ch == ',')  // comma is our separator, so move on to the next field
    {
        fieldIndex++;   // increment field index 
    }
    else
    {
      // any character not a digit or comma ends the acquisition of fields
      // in this example it's the newline character sent by the Serial Monitor    
      // print each of the stored fields
      for(int i=0; i < min(NUMBER_OF_FIELDS, fieldIndex+1); i++)
      {
        values[i] = 0; // set the values to zero, ready for the next message
      }
      fieldIndex = 0;  // ready to start over
    }
  }
  writeData(values[0], values[1]);
}

void writeData(long firstLine, long secondLine){
if (firstLine > 0){
 upload = values[0]/1024.0;
 download = values[1]/1024.0;

  lcd.setCursor(0,0); 
  lcd.print(upload);
  lcd.setCursor(9,0);
  lcd.print("MB");
  lcd.setCursor(11,0);
  lcd.write(byte(1));	//Print our up arrow
  }
if (secondLine > 0){
  lcd.setCursor(0,1);
  lcd.print(download);
  lcd.setCursor(9,1);
  lcd.print("MB");
  lcd.setCursor(11,1);
  lcd.write(byte(0));
  }
}

(deleted)

(deleted)

Hi,

I can't see in your code if you load the display area for your figure with blanks before loading your figures.

Another option is to pad the value with leading zeros, so the Dec point is always in the same location.

Excellent suggestion, your numbers won't jump around.

Tom... :slight_smile:

I solved it!!!

The problem was a bug in the code. The serial connection had no issues resolving the proper numbers.

I was able to invoke serial readline on my script side using just a delay to handle the initialization of the arduino and then it printed out the info. What is happening is the if statement checks for sums > 0 what happens is that the float gets populated one digit at a time due to the character by character reading of the arduino. This causes the information to be padded with zeros and the data is written before the full information has been received.

All I did was add my lcd printing command before it cleared the information. See updated code below. This completely removed the flickering and the LCD updates insanely fast now. My script is sending updates every 0.05 seconds with no flickering.

This problem has been solved. Thanks kindly for the assistance!

/*
 * SerialReceiveMultipleFields sketch
 * This code expects a message in the format: 12,345,678
 * This code requires a newline character to indicate the end of the data
 * Set the serial monitor to send newline characters
 */

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 
byte downArrow[8] = {
	0b01110,
	0b01110,
	0b01110,
	0b01110,
	0b01110,
	0b11111,
	0b01110,
	0b00100
};
byte upArrow[8] = {
        0b00100,
	0b01110,
	0b11111,
	0b01110,
	0b01110,
	0b01110,
	0b01110,
	0b01110
};
 
 
const int NUMBER_OF_FIELDS = 2; // how many comma separated fields we expect
int fieldIndex = 0;            // the current field being received
unsigned long values[NUMBER_OF_FIELDS];   // array holding values for all the fields
float upload = 0;
float download = 0;


void setup()
{
  Serial.begin(115200); // Initialize serial port to send and receive at 9600 baud
  lcd.begin(16,2);
  lcd.createChar(0, downArrow);
  lcd.createChar(1, upArrow);
}

void loop()
{
  if( Serial.available())
  {
    char ch = Serial.read();
    if(ch >= '0' && ch <= '9') // is this an ascii digit between 0 and 9?
    {
      // yes, accumulate the value if the fieldIndex is within range
      // additional fields are not stored
      if(fieldIndex < NUMBER_OF_FIELDS) {
        values[fieldIndex] = (values[fieldIndex] * 10) + (ch - '0'); 
      }
    }
    else if (ch == ',')  // comma is our separator, so move on to the next field
    {
        fieldIndex++;   // increment field index 
    }
    else
    {
      // any character not a digit or comma ends the acquisition of fields
      // in this example it's the newline character sent by the Serial Monitor    
      // print each of the stored fields
      writeData(values[0], values[1]);
      for(int i=0; i < min(NUMBER_OF_FIELDS, fieldIndex+1); i++)
      {
        values[i] = 0; // set the values to zero, ready for the next message
      }
      fieldIndex = 0;  // ready to start over
    }
  }
}

void writeData(long firstLine, long secondLine){
if (firstLine > 0){
 upload = values[0]/1024.0;
 download = values[1]/1024.0;

  lcd.setCursor(0,0); 
  lcd.print(upload);
  lcd.setCursor(9,0);
  lcd.print("MB");
  lcd.setCursor(11,0);
  lcd.write(byte(1));	//Print our up arrow
if (secondLine > 0){
  lcd.setCursor(0,1);
  lcd.print(download);
  lcd.setCursor(9,1);
  lcd.print("MB");
  lcd.setCursor(11,1);
  lcd.write(byte(0));
//  Serial.print(upload);    #Troubleshooting
//  Serial.print(",");
//  Serial.println(download);
  }
  }
}

Hi,
Good to hear, and thanks for posting your solution.
Can you please go and edit your subject title of this thread and add [SOLVED] to it.

This will help anyone looking for solutions to similar problems.

Thanks.. Tom.. :slight_smile: