A better way to update text displays?

I'm working on a proof of concept device for taking inputs intended to light up idiot lights on a gauge cluster and put them on a display. I have a build that's working well enough to do a PoC run, but I wanted to make it a little less crappy. I've got a couple things like a splash screen and a clock because if this works out, a lot of this may go to the final version. I'm also very new at this and playing around.

Originally, I was using the void loop to watch for a digital pin to go high then display a message. That wound up with a lot of clumsy lcd.clear lines, it was slow, and it looked bad. I started looking for another way to do this and found interrupts, but I'm doing it wrong because it's not working.

Here is the tutorial I followed:

Here's what I've got:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <ds3231.h>

LiquidCrystal_I2C lcd(0x27,20,4);
struct ts t; 

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("BMW ///M3: Sheer");
  lcd.setCursor(0,1);
  lcd.print("Driving Pleasure");
  delay(2000);
  lcd.clear();

  Wire.begin();
  DS3231_init(DS3231_CONTROL_INTCN);
  t.hour=12; 
  t.min=30;
  DS3231_set(t); 

  //interrupt setup for better handling of error messages
  attachInterrupt(digitalPinToInterrupt(2),brake_fluid1,RISING);

  attachInterrupt(digitalPinToInterrupt(2),brake_fluid0,FALLING);

  
}


void loop()
{
  DS3231_get(&t);
  lcd.setCursor(0,0);
  lcd.print(t.hour);
  lcd.print(":");
  lcd.print(t.min);
  lcd.setCursor(10,0);
  lcd.print(" ///M3");

}

void brake_fluid1()
{

  lcd.setCursor(0,1);
  lcd.print("Brake Fluid Low"); 
}

void brake_fluid0()
{

  lcd.setCursor(0,1);
  lcd.print("               "); 
}
type or paste code here

edit1: Added link to tutorial I used
edit2: Corrected markdown error that omitted 1 line of my code

Hello
output the values on the LCD that have changed only.

if (oldValue!=newValue) {
    oldValue=newValue;
   lcd.print(newValue); 
}

Avoid using interrupts with writes to the LCD, that takes more time than you want to spend in an interrupt, and you will inevitably have the interrupt occur while doing an unrelated write to the LCD. You are also going to change the position of the LCD cursor in the interrupt, so that an LCD write after returning from the interrupt will go to the wrong position.

The general technique with displaying data on an LCD is to write all the fixed text to the screen once, then (as stated in reply #1) only update the data when it changes. You will need to be careful with positioning when doing this, and making sure the previous data is overwritten by the new data - you likely have already discovered that your method of displaying the hours and minutes will give odd results when the numbers change between single-digit and two-digit numbers, the leading spaces or zeros need to be displayed to keep the data field a constant width.

Hi,
To add to @paulpaulson solution, it would be worth erasing the old data with blank spaces, so when you print the new, if it has less digits/figures than the original print, you will not see the old print in the spaces not occupied by the new.
I hope that makes sense. (Just started my first coffee for the day :coffee:)

if (oldValue!=newValue) {
    oldValue=newValue;
   lcd.setCursor (to where old value is printed);
   lcd.print("         "); // or what ever number of spaces your value occupies.
   lcd.setCursor(to where old value was printed);
   lcd.print(newValue); 
}

Tom... :smiley: :+1: :australia:

1 Like

Thanks for the info, folks! I may wind up at square one here, but I'll figure it out.

That would most likely be because of using interrupts. :grin:

.

Hint: Install Bill Perry's "HD44780" library in the IDE Library manager, go to the I²C section and learn the examples.

Then start writing your code. :+1:

Even better is to format your data so that each time you write it, it always completely overwrites the previous value. This is even more efficient and produces even less flicker.

For example

  DS3231_get(&t);
  lcd.setCursor(0,0);
  lcd.print(t.hour);
  lcd.print(":");
  lcd.print(t.min);

becomes

  DS3231_get(&t);
  lcd.setCursor(0,0);
  char buffer[6];
  sprintf(buffer, "%02d:%02d", t.hour, t.min);
  lcd.print(buffer);

Note that 'buffer' always needs to be one character longer than you expect, because that is needed for the null character that marks the end of a C-string.

There are many useful formatting controls you can use with sprintf(). Here, I used
% ... insert a value at this point in the string
d ... print the value in decimal
2 ... print the value padded to 2 characters. Normally spaces are used but..

0 ... pad the value on the left with zeros rather than spaces

What @Paul_B said... :+1: :+1: :+1: :+1: :+1:

Tom... :smiley: :+1: :coffee: :australia: