Flickering display without using lcd.clear()

Hi all,

I know there's a bunch of posts around which deal with flickering LCD displays, but in my case I'm not even using the lcd.clear() function and I'm only updating the screen under specific conditions.

I'm working with a Finite State Machine. Within the loop() function, within one state, I have the lines below. The number NN can be updated within the same state, which would trigger an update on the LCD screen. I don't understand why my screen is flickering with this code. Even if I didn't use the update condition (NN changed), I believe that the LCD should not be flickering if I don't clear the screen, right?

if (NN==1 || lastNNcount != NN) {  // Update position on LCD only if necessary
        lcd.setCursor(0, 0);
        lcd.print("Press again: Set++.");
        lcd.setCursor(0, 1);
        lcd.print("Or press START.");
        lcd.setCursor(0, 2);
        lcd.print("Set: ");
        lcd.setCursor(6, 2);
        lcd.print(NN, DEC);
      }

Hi.

You're not showing enough code.
Your problem might be related to the update rate of "lastNNcount", which isn't part of this function.
It should be updated, and with the info i have at this moment, you need to update it in this function.
But certainly it absolutely needs to be updated before the next iteration.
I can't tell if it is updated at all.

Hi, thanks for your prompt reply. I'll post the whole state, since it is a very simple one. I hope it gives more info. lastNNcount is updated when the "switch"pushbutton is pressed and NN incremented.

case MENU:  //Check and update value of NN: counts number of switch button presses, records the set number, outputs count to LCD (and serial).

      if (current_state != last_state) {
        Serial.println("State: MENU");
      }

      if (NN == 1 || lastNNcount != NN) { // Update position on LCD only if necessary
        lcd.setCursor(0, 0);
        lcd.print("Press again: Set++.");
        lcd.setCursor(0, 1);
        lcd.print("Or press START.");
        lcd.setCursor(0, 2);
        lcd.print("Set: ");
        lcd.setCursor(6, 2);
        lcd.print(NN, DEC);
      }

      if (isLcdLightOn == 0) {
        digitalWrite(LCD_LIGHT_PIN, HIGH);    //Turn on LCD backlight if not yet on
        isLcdLightOn = 1;
      } //end if


      //check if switch button was pressed, debounce it, and take action (increment)

      if (switch_button_input  != last_switch_button_state) {
        // reset the debouncing timer
        last_switch_DebounceTime = millis();
      }

      if ( (millis() - last_switch_DebounceTime) > debounceDelay) {   //filter out any noise by setting a time buffer (debounce)

        // if the button state has changed:
        if (switch_button_input != switch_button_state) {
          switch_button_state = switch_button_input;

          // only increment SET/DAY if the new button state is HIGH
          if (switch_button_state == HIGH) {
            lastNNcount = NN;
            NN++;                                // increment NN (set/day counter)
            if (NN == 11) NN = 1;
            timestep = 0;                       //set timestep back to 0 because new set/day has started.
          } //end if
        } //end if
      } //end if

      last_switch_button_state = switch_button_input;

      //check if start button was pressed, debounce it, and take action (go to state measure)

      // If the tart button state changed, due to noise or pressing:
      if (start_button_input  != last_start_button_state) {
        // reset the debouncing timer
        last_start_DebounceTime = millis();
      }

      if ( (millis() - last_start_DebounceTime) > debounceDelay) {   //filter out any noise by setting a time buffer (debounce)

        // if the button state has changed:
        if (start_button_input != start_button_state) {
          start_button_state = start_button_input;

          // only start measurements if the new button state is LOW (= ON)
          if (start_button_state == LOW) {
            if (isLcdLightOn == 0) {
              digitalWrite(LCD_LIGHT_PIN, HIGH);    //Turn on LCD backlight if it is turned off
              isLcdLightOn = 1; 
            } // end if
            lcd.clear();                         // Update position on LCD
            lcd.setCursor(0, 0);
            lcd.print("Measurement started.");
            lcd.setCursor(0, 1);
            lcd.print("Set: ");
            lcd.setCursor(6, 1);
            lcd.print(NN, DEC);

            Serial.println();
            Serial.println("-------------------------------------------------------------------");
            Serial.print("Measurement started for following Set/Day: ");
            Serial.println(NN, DEC);
            Serial.println();
            delay(3000); //wait 3 seconds to make it possible to read the message on LCD
            thisCell = 0;
            current_state = MEASURE;
          } //end if
        } //end if
      }//end if

      last_start_button_state = start_button_input;

      last_state = MENU;

      break;

As far as i can see, this screen is supposed to only be printed when going from NN==0 to NN==1.
I do not know if you can get from an other state to NN==1, but in that case this would also trigger this screen to be printed.

You should check to see if lastNNcount is correctly updated.
Perhaps by printing NN and lastNNcount to serial in every iteration, the latter should have caught up with NN every next iteration.
You can remove that part after debugging.

Actually, i don't think that is what you are doing.
I think you are updating lastNNcount on every next buttonpress, so lastNNcount will lag for each buttonpress.

If so, see if you need lastNNcount for something else.
If not, you should update it immediately after printing your screen.
If you do need it somewhere else, you should use another variable, let's call it screenPrinted and make it a boolean.
Set it to true if the screen is printed, and reset it to false if the screen needs to be printed in the next iteration.

Hi and thanks!

Why do you think that the screen is only supposed to be printed when going from NN==0 to NN==1? NN is initialized at 1 and goes until 10 (whenever it reaches 11, it is set back to 1). NN is updated when a switchbutton is pressed, and before this lastNNcount records the last NN value. I printed the values on the serial and they are correctly updated at every button press.

The blinking is very fast - it seems that it is updating at the pace of the loop() function. Is there a way to avoid this?

Btw - I'm having a similar issue in another state. So basically, again, I'm only updating the screen whenever a timestep is incremented (which happens every 10 seconds), si using the condition if last_timestep != timestep. I checked that both counters are updated correctly. Every 10 seconds, the LCD prints the information, but only during the time of 1 loop, so it is a question of micro/milliseconds, just the time to recognize a flickering of characters. I thought that LCD screens had memory and would only erase what's on their screen if overwritten or explicitly erased?

Nongsai:
Why do you think that the screen is only supposed to be printed when going from NN==0 to NN==1?

      if (NN == 1 || lastNNcount != NN) { // Update position on LCD only if necessary

This checks to see if NN==1.
If that condition isn't met, it will omit the printing of that screen.
You are also checking to see if NN is not equal to lastNNcount.
But somewhere else, you do this:

          if (switch_button_state == HIGH) {
            lastNNcount = NN;
            NN++;                                // increment NN (set/day counter)
            if (NN == 11) NN = 1;

This means lastNNcount is equal to NN for about 0.00000125 seconds (i'm optimistic, that's 2 clock cycles).
When you arrive at the above check to see whether they are equal, they will never be.
So this secondary condition will always be met.
This screen will be blinking if NN == 1.
It will not be printed if NN has any other number.

NN is initialized at 1 and goes until 10 (whenever it reaches 11, it is set back to 1). NN is updated when a switchbutton is pressed, and before this lastNNcount records the last NN value. I printed the values on the serial and they are correctly updated at every button press.

I only saw the ++, and missed the reset to 1.
I can't tell what NN is initialized to, that's in some other part of the sketch.
And i also can't see if there is some other code doing NN -- (perhaps if you press another button), which is why i mentioned that.

The blinking is very fast - it seems that it is updating at the pace of the loop() function. Is there a way to avoid this?

It is indeed updating at the speed of loop(), which is referred to as one iteration.
The reason for that is that you aren't actually doing what you think you are doing, and that's what i've been trying to explain.

I also i asked if you need lastNNcount at some other part in your code.
If you do, you can't use that to reduce the number of prints.
If you don't, you can use it, but you have to update it after you have printed the new value to the screen, and not right before some new value arrives (as you do now).

If you can't use lastNNcount, you need to check whether you need to update the screen.
In contrary to what i told you yesterday, i now would create a boolean called needPrint.
you can then do this:

      if (needPrint) { // Update position on LCD only if necessary
        lcd.setCursor(0, 0);
        lcd.print("Press again: Set++.");
        lcd.setCursor(0, 1);
        lcd.print("Or press START.");
        lcd.setCursor(0, 2);
        lcd.print("Set: ");
        lcd.setCursor(6, 2);
        lcd.print(NN, DEC);
        needPrint = !needPrint;
      }

And of course:

          if (switch_button_state == HIGH) {
            needPrint = !needPrint;
            lastNNcount = NN;
            NN++;                                // increment NN (set/day counter)
            if (NN == 11) NN = 1;
            timestep = 0;                       //set timestep back to 0 because new set/day has started.
          } //end if

This would print any new value to the screen once.

If you are overwriting the contents of the screen with the same contents, those contents are erased and rewritten.
Which creates a blinking effect.