LCD reset, or how do I get a non flashing display?

I wasn't sure if I should post this here or in LCD, but it seemed more appropriate here to me.

I'm trying to a handle on Arduino programming, since I have a number of ideas to use these for. I've started with a rather elaborate display that will connect to the ECM in my car, but decided that it was well beyond my programming skill level, so I decided to do something that should be much simpler, and it is... sort of.

What I decided to do was make a simple LCD display that will show a few different functions of my car, and plan to add to it in the future.

What I have started is something that will display the left and right turn signal display, along with a "CHECK ENGINE" message that can be displayed on the LCD (16x2). The three inputs are triggered right now from a button on a breadboard, using the button example circuit.

So far, for only working this for a few hours (Still very new to programming), I have a 95% successful item.

My biggest issue is getting the items to display on the screen without appearing to be flashing, or almost scrolling reset, might be more accurate description. I am using "<---" for left turn, "--->" for right turn and "CHECK ENGINE" for, well... check engine. lol What happens is that each item when displayed will flash almost as if each pixel is being reset from left to right. I can stop this by not using the "lcd.clear" command, but then once each item is triggered, they just stay on the LCD, I need them to blank when the input is not present. I would also eventually like to display other messages in the same areas, so writing to the same locations of the LCD with something like " " won't work in the long run. Eventually I'd like to use some large digits as well, that uses more than one line of the display for an item displayed. I also have an LED illuminating when the "CHECK ENGINE" light pin is triggered.

I've looked at the "switch case" examples, and some threads on here, but I'm not sure if that's what I need to use, and I haven't grasped it's use or implementation yet.

I know I'm missing something, I just can't figure out what, so I am asking for a bit of guidance on this.

I have tried only using a single "lcd.clear" statement at the end of the loop, which worked, but still had the same flickering message display.
I have also tried using "lcd.noDisplay" and had nothing displayed on the LCD at all. If I trigger all 3 inputs at the same time, the flashing doesn't occur, I would suspect this would be due to the "true" IF statements bypassing the "else" statements.

Please be gentle, I have tried searching and just trying some things both from examples and just some random ideas I though may or may not work. I'm just starting in this programming and I actually feel pretty good about my progress so far, mostly started from scratch, though much of the code was copied and modified from example sketches, I have made something work almost the way I want it to. I know there are probably some shortcuts to cleaning up the sketch, and making it more efficient, but taking the long route works for me for now, once I understand it, then I will worry about shortcuts and using more advanced programming. :slight_smile:

Here is the code:

/*
 
 This is a display that will take dedicate inputs and display their function 
 on an LCD.
 
 The list of functions so far:
 - Right Turn Signal
 - Left Turn Signal
 - Check Engine Light (message?)
 
 The circuit:
 * LED attached from pin 4 to ground (CHECK ENGINE indicator)
 * pushbutton attached through buttons from +5V
 * 10K resistor attached to pin 2 from ground
 * Right turn input to pin 2
 * Left Turn Signal to pin 3
 * Check Engine light to pin 5

 
 This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/Button
 */

// constants won't change. They're used here to 
// set pin numbers:
const int rightturnPin = 2;     // the number of the pushbutton pin
const int lefttturnPin = 3;     // the number of the pushbutton pin
const int celPin = 5;     // the number of the pushbutton pin
const int ledPin =  4;      // the number of the LED pin

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 8, 9, 10);
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  lcd.begin(16, 2);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT); 
  // initialize the pushbutton pin as an input:
  pinMode(rightturnPin, INPUT);  
  pinMode(lefttturnPin, INPUT);
  pinMode(celPin, INPUT);
  
}

void loop(){
    
    // read the state of the pushbutton value:
  buttonState = digitalRead(rightturnPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) { 
    lcd.setCursor(12, 1);
    // write to LCD:    
    lcd.print("--->"); 
  } 
    
    else {
      //clear LCD
      lcd.clear();
    
  } 
 
    
    // read the state of the pushbutton value:
  buttonState = digitalRead(lefttturnPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) { 
    lcd.setCursor(0, 1);
    // write to LCD:    
    lcd.print("<---"); 
  }
  else {
    // clear LCD
    lcd.clear();
  }
  {
   
  // read the state of the pushbutton value:
  buttonState = digitalRead(celPin);
  

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) { 
    // turn LED on:    
    digitalWrite(ledPin, HIGH);
    lcd.setCursor(2, 0);
    // write to LCD:    
    lcd.print("CHECK ENGINE"); 
    
  }    
    else {
      //clear LCD
      lcd.clear();
     // turn LED off:
    digitalWrite(ledPin, LOW);
   
   } 
  } 
  }

I think the problem is that the mechanical switch bounces and you also come back and read it too fast and then immediately write to the LCD again.
Put a delay of a quarter of a second after each lcd.print. I think the problem you are seeing will go away.

I added a a delay after the lcd.print commands, it did reduce the flickering, but did not totally remove it. This definitely will not work for the intended application. Any two or all 3 of these inputs may be on at the same time, or turn on at any time. With the delay in place, what seems to happen is that there is a delay between looking at the next command set in the loop, and causes the displayed functions to either be delayed or not displayed at all.

I need a way for any of the inputs (I do plan on adding more, this is just to figure out how to make a few items work right now), to write to the LCD at any time without delay. It's important that there's no delay on the CEL, since a rapidly flashing CEL in my case is an indication of a serious issue, if there is a delay in response of that being displayed, it would be easy to miss what is actually going on. Turn signals are less important to have react right away, but even the delay added to them affects the CEL display.

For some testing, I'm holding the button for an extended period, so I don't think switch bounce is really an issue here.

Thanks for the idea, I'm sure that will come in handy on some other projects. :slight_smile:

Six_Shooter:
If I trigger all 3 inputs at the same time, the flashing doesn't occur, I would suspect this would be due to the "true" IF statements bypassing the "else" statements.

This is indeed the issue. What is happening is that if any of the inputs are not "true" then the lcd is cleared.
To avoid flicker, you need to avoid using lcd.clear(). It is a very slow operation relative to other commands.
For example, you can home the cursor and write spaces to the entire display many times in the same amount
of time it takes for library/lcd to process lcd.clear().

What you need to do is only clear the portion of the display that is associated with that input.
For example you could do this:

// check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH)
  {     
    lcd.setCursor(12, 1);
    // write to LCD:    
    lcd.print("--->"); 
  } 
  else 
  {
    lcd.setCursor(12, 1);
    // write to LCD:
    lcd.print("    ");  // clear right arrow
  }

(You could even do a single setCursor() and then just print the correct text based on the if statement)

Another thing you could do is replace the LiquidCrystal library that ships with the IDE with
a faster & better library.
You can get that replacement library here:
https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
This library is a drop in replacement for the library that ships with the IDE.
For the 4 bit parallel mode, it is currently about 3.5 times faster.
This alone can help reduce flicker as the original library could update a full 16x2 display
about 87 times/sec and this library can update the display about 300 times/sec.

But the real answer is simply to not clear the display but rather only clear (overwrite)
the needed portion of the display. Once you do that, all the flicker should stop even with
the original/stock LiquidCrystal library.

--- bill

I had thought about clearing the screen in that way, but I'm afraid I'll run into a similar situation when I add more functions that need to display in the same space.

I'll give it a try when I get home tonight, and report back.

I know I had a thought about how to make this work laying in bed last night, I knew I should have write it down. LOL

Eventually I want use this as an auxilliary display for not so commonly used or displayed items in the car, or secondary displays, for items I want to keep an eye on, for diagnostics and tuning.

I also have a non code related issue now, the UNO doesn't reset at power up IF the LCD display is attached to the shield, else resets perfect. Hehe I'm not sure if I possibly damaged the LCD display yesterday when I inadvertantly placed the shield onto the UNO wrong. :oops: It works fine once the reset button is pressed. I will go into more detail later.

Thanks for the help, it's very appreciated.

Six_Shooter:
I had thought about cleating the screen in that way, but I'm afraid I'll run into a similar situation when I add more functions that need to display in the same space.

If you will have additional information using the same area on the display, then
there will probably be some sort of state or "mode".

You will need to keep track of what state you are in.
Depending on what state you are in, that will determine what you
paint and what you erase.

--- bill

One last follow-up.
The key to avoiding flicker is to avoid erasing something that will be re-drawn.
For example if you re-draw the exact same thing over and over again with
no erase, there will be no flicker.
However if you erase an area before you re-draw something even if it is
the exact same thing that was previously on the display, there will be flicker.

Another thing to keep in mind is that clear() and home() are very slow.
It is much faster to set the cursor position to 0,0 than to use home().
(As long as you are not using the right/left scrolling capability as home() is used to reset that)
And it is much faster to write to the full display rather than clear(),
particularly if you use the alternate LiquidCrystal library I mentioned above.

--- bill

I had thought about clearing the screen in that way, but I'm afraid I'll run into a similar situation when I add more functions that need to display in the same space.

There is no reason to clear out the old information if you are going to display new information in the same space. All you have to do is position the cursor and write your new information.

Don

bperrybap:

Six_Shooter:
If I trigger all 3 inputs at the same time, the flashing doesn't occur, I would suspect this would be due to the "true" IF statements bypassing the "else" statements.

This is indeed the issue. What is happening is that if any of the inputs are not "true" then the lcd is cleared.
To avoid flicker, you need to avoid using lcd.clear(). It is a very slow operation relative to other commands.
For example, you can home the cursor and write spaces to the entire display many times in the same amount
of time it takes for library/lcd to process lcd.clear().

What you need to do is only clear the portion of the display that is associated with that input.
For example you could do this:

// check if the pushbutton is pressed.

// if it is, the buttonState is HIGH:
 if (buttonState == HIGH)
 {    
   lcd.setCursor(12, 1);
   // write to LCD:    
   lcd.print("--->");
 }
 else
 {
   lcd.setCursor(12, 1);
   // write to LCD:
   lcd.print("    ");  // clear right arrow
 }




(You could even do a single setCursor() and then just print the correct text based on the if statement)

Another thing you could do is replace the LiquidCrystal library that ships with the IDE with
a faster & better library.
You can get that replacement library here:
https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
This library is a drop in replacement for the library that ships with the IDE.
For the 4 bit parallel mode, it is currently about 3.5 times faster.
This alone can help reduce flicker as the original library could update a full 16x2 display
about 87 times/sec and this library can update the display about 300 times/sec.

But the real answer is simply to not clear the display but rather only clear (overwrite)
the needed portion of the display. Once you do that, all the flicker should stop even with
the original/stock LiquidCrystal library.

--- bill

While this works, with the current simple displayed items, it has the issue I thought it would, if I try to write something to the same space that is also used for another displayed function, what ever is first listed in the loop, gets priority, for whichever state the input is in.

In the long run this won't work, since I plan to have different things displayed in the same areas as other items to be displayed, I need to figure out a way to clear what was just displayed from the screen, until another input goes true.

Eventually I may even have it turn off the backlight and only turn on when there is information to display, or display a generic message or symbols, while waiting for an input to do something.

Back to reading more examples...

In the long run this won't work, since I plan to have different things displayed in the same areas as other items to be displayed, I need to figure out a way to clear what was just displayed from the screen, until another input goes true.

In that case you do not have to clear the entire screen. Just reposition the cursor and display enough spaces to cover up the old information.

Eventually I may even have it turn off the backlight and only turn on when there is information to display ...

Why don't you just turn off the display when there is no information to display? When new information is available you can send this updated information to the display and then turn it back on.

Don

floresta:

In the long run this won't work, since I plan to have different things displayed in the same areas as other items to be displayed, I need to figure out a way to clear what was just displayed from the screen, until another input goes true.

In that case you do not have to clear the entire screen. Just reposition the cursor and display enough spaces to cover up the old information.

Is that not what I was doing with the last code update?

if (buttonState == HIGH) { 

lcd.setCursor(0, 1);
    // write to LCD:   
    lcd.print("<---");
  }
    else {
    lcd.print("    ");




This didn't work, because when I tried to write something else to the same location (farther down in the loop), the information was flickering, like using the lcd.clear() command.




> Eventually I may even have it turn off the **backlight** and only turn on when there is information to display ...


Why don't you just turn off the **display** when there is no information to display? When new information is available you can send this updated information to the display and then turn it back on.

Don
-

That was another thought after I wrote my previous reply... All in due time.

I need to get the LCD refresh/clearing working properly before I worry about adding new features...

... when I tried to write something else to the same location (farther down in the loop), the information was flickering ...

You have the advantage of being able to see your entire sketch, we are just getting to look at pieces of it.

Don

I always try to avoid using clear(), like you say the flickering becomes annoying unless you are doing it slowly. I just print info onto, with enough empty spaces to cover up any chars that might not be used on the new data to print

floresta:

... when I tried to write something else to the same location (farther down in the loop), the information was flickering ...

You have the advantage of being able to see your entire sketch, we are just getting to look at pieces of it.

Don

The entire sketch was posted in the first post.

In that sketch and currently I have information writing to different parts of the LCD, only because that's how I want these particular items to display, but eventually I want to be able to display other things sharing the same locations on the LCD. I'm trying to get just a few inputs working first, after that anything new should be pretty easy.

It seems if I don't use lcd.clear or lcd.write (" "), the information does not clear when the input goes false, and I want the displayed info to clear when the input goes false, otherwise it won't be current to what is happening with the inputs.

If I use either the lcd.clear or write spaces to overwrite that information, when I do (in testing) write something new to that same location, I get the displayed information flickering. For testing all I did was change where the left arrow (leftturnpin) to display where the right arrow (rightturnpin) was displayed. I did this as a quick test to try and get this working the way I want before adding any more features, inputs, etc.

Eventually I would like this to be able to display scrolling information, that will change based on what is happening in the car, and be blank otherwise, maybe even turn off the backlight or the power to the LCD when there is nothing to display.

Ideally I'd like to use custom symbols to display a logo when there is nothing to display, but I need to get this working properly first.

Is there something better than if/else to use for this? From the description switch case sounded like it might work, but I'm not sure how to translate from the example into something usable here. I also haven't had much time this week to look at it in depth, but hope to in the next few days.

Right now you are writing three strings to the display each time you go around the loop, even if the information that you are writing is the same as what is already there. With no extra delays in the loop you are doing this very frequently. You should consider changing your logic a bit so that if you test a switch, and it is the same as it was the last time around the loop, then nothing concerning that switch is written to the display.

Don

Maybe you are not understanding that once you write to the LCD the LCD will display that forever until you change it.

It is up to your code to determine what to write to the display and when to write it.

In your test, you write something to a location on the display, you then erase it or overwrite it with spaces, then
write something else to the same location.
And repeat this over and over again, MANY times per second.

I don't understand what you are expecting to happen other than the "flicker" or clobbered/garbled text you are getting.

If you want to share the same lcd screen area with more than one message, you will have to write code that
keeps track of some sort of state or mode you are in so that you don't keep writing multiple things to the
same location.

--- bill

In your test, you write something to a location on the display, you then erase it or overwrite it with spaces, then write something else to the same location.
And repeat this over and over again, MANY times per second.

Sometimes (most times?) the information is overwritten with the same information that was previously there. This is what Bill is referring to in his first sentence and what I was referring to in my previous post.

Don

bperrybap:
Maybe you are not understanding that once you write to the LCD the LCD will display that forever until you change it.

I understand that.

It is up to your code to determine what to write to the display and when to write it.

Uh huh, No new information here.

In your test, you write something to a location on the display, you then erase it or overwrite it with spaces, then
write something else to the same location.
And repeat this over and over again, MANY times per second.

Yep...

I don't understand what you are expecting to happen other than the "flicker" or clobbered/garbled text you are getting.

I expect to be able to use the same LCD area for multiple messages, somehow, but so far no one has pointed me to how to do this, and I have not been able to understand the examples enough, to know how to set it up to do this or look at other peoples sketches to do figure out how to manipulate the code. I know there is a way, I just don't quite understand the code yet, and I'm trying to figure it out

If you want to share the same lcd screen area with more than one message, you will have to write code that
keeps track of some sort of state or mode you are in so that you don't keep writing multiple things to the
same location.

Uh huh...

Exactly what I've been trying to find or figure out how to do.

I literally have less than 10 hours into using this code (Arduino), a little more into reading about it, so to give me generalizations are not going to help, pointing me in a direction will however.

No one has answered yea, or nay about maybe using switchcase, or some other scheme to get this to work how I want. I'm not asking for someone to do this for me , or even hold my hand, but a little more direction with less generalized replies will be much more helpful. Maybe an example code of an existing project that does something similar, writes to the LCD with something, then clears it waiting for something to change to display something again.

I can get message after message to write to the screen, but only in a loop, without having influence from an input to change something, or clear the LCD. I want the LCD to be black when there are no inputs that are "true." Eventually I'd like to display a logo or some basic "stand by" message when no inputs are true, but I just want this to work with the 3 inputs and a blank LCD for now, I'll add more once I figure this out.

It would seem to me that if/else made the most sense, because I want something displayed on the screen anytime and for as long as an input is active or true, and not any other time.

I had tried using a single "else" at the end of the loop, looking at all 3 (currently) inputs, with the same results.

The only way I don't currently get flickering is if I use the lcd.write(" ") and only have the ability to display one item in each area of the LCD, but that won't be useful in the long run, and simple LEDS, like I currently have in the car will be much more cost effective for such a display. I'm trying to end up with basically a message center here, that can display multiple things, so far I've been marginally successful.

Exactly what I've been trying to find or figure out how to do.

Start out by considering just one of the three message pairs that you are currently dealing with, the 'right turn'.
There are two possible messages to display at location (12,1), either "--->" or " ".

Let's assume that your push button switches generate a logic '0' when they are pressed and a logic '1' when they are released.

You should create a 'flag' (variable) that your program can test to represent which of these two messages was last displayed, perhaps '0' for "--->" and '1' for " ".
Now, when you send a "---->" to the display you also set the 'flag' to '0', and when you send a " " to the display you also set the 'flag' to '1'.

Now, each time you read a switch you compare the switch reading to the flag. If they are the same you don't make any changes to the LCD display but if they are different then you display the appropriate message.

Don

I think perhaps you are not picking up on the concept of "state" or "modes".
You have a situation where you are trying to indicate information from multiple inputs
in the same place.

In order to do this kind of thing you must create some sort of rules of what to display when
and what takes priority because there will be situations where there are multiple things to indicate
and yet only a single place to display information.

For example consider a case of trying to share a portion of the LCD between a right blinker an an emergency indicator.
So in this case you have 4 things you need to indicate and only a single place to show it.

  • blinker on
  • blinker off
  • emergency on
  • emergency off

The current loop is very simple, it simply looks at each input and reflects its status.

  • look at blinker indicator (indicate on or off)
  • look at emergency indicator (indicate on or off)

When you do it this way, you can see that the second check for the emergency indicator and display
of its status will clobber the first display of the blinker status
and the first check of the blinker indicator and display of status
will clobber the second display status when this operation is done in a loop.

In order to prevent this, you have to come up with a way to prioritize the display and potentially
ignore some of the inputs to favor others.

For example, should an emergency indicator take over the full display?
Should the blinker status be ignored when the emergency indicator is active or
should it alternate between blinker and emergency status?

These kinds of things can get complicated but they all come down to tracking some sort of state or mode information.
For example, in a simplistic approach emergency indicators could take priority over everything.
In this case you could set a state/mode flag when the emergency indicator is active.
This flag would then be used to tell all the other code not display their status since the emergency
display code is now "active" and in control of the display.

Another simple way would be to create a status variable for each portion of the display.
Say you have 4 portions of the display that indicate status.
UpperLeft, UpperRight, LowerLeft, LowerRight. You create a status variable for each that gets set to 0
at the top of your loop. Each time you write to that area, you set its flag.
At the bottom if a flag that area is not set you clear the area.

This might still cause flicker if two sensors are active at the same time that both use the same area of the LCD.
To cure that you would need a way to prioritize them.
You could do something simple like the closer to the top of the loop the higher
the priority. Then when its time to display something, you look to see if that portion of the display
is already "active"/"busy" by looking at its state flag. If it is already set, then you can't display anything
in that portion of the display.

In more complex implementations, the state/mode information could be changing based on time passing.
So perhaps an emergency indication is important but you you still want/need to indicate the turn signal
status. In this case, there would have to be mechanism to share the display space. This could be based on time.
Perhaps when there were 2 indicators wanting to use the same region of the display that each one gets the region
for 1 or 2 seconds of time. The display would then flip between each status.
This method is obviously more complex and requires a lot more state information.

The thing to think about is that if you are going to share the same portion of the display
with multiple messages from multiple sensors/inputs, you need a way to control what is displayed
and when. In order to do that you will need to have some sort of state information that is looked
at to determine how to react. And that state will need to change though time depending on conditions or
simply by the passage of time.

--- bill