[LCD without delay]

Hi there :), I am using an Arduino Uno R3, with an I2C LCD module connected to an LCD.

I want to display a message on my LCD without using a delay. I want to achieve this using the millis() function.

It works fine with delay() but with millis(), the LCD never displays the 2th message in the loop. So, the if-condition is never met. It seems like I am doing something wrong here. I appreciate your aid.

My research:

Arduino Electrical Diagram:

My code:

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

LiquidCrystal_I2C lcd(0x27, 16, 2);

String gamemodeMessage;

unsigned long previousTime = 0;
long interval;

void setup() {
  lcd.backlight();
  lcd.begin();
  lcd.clear();
  lcd.print("Active Learning");
  lcd.setCursor(0, 1);
  lcd.print("Welcome!");
  delay(1000);
}

void gamemodeControl() {
  unsigned long currentTime = millis();
  interval = 1000;

  gamemodeMessage = "+";
  if ((currentTime - previousTime >= interval) && (millis() - previousTime < (interval * 2))) {
    lcd.setCursor(0, 0);
    lcd.clear();
    lcd.print("Gamemode:");
    lcd.setCursor(11, 0);
    lcd.print("");
    lcd.setCursor(0, 1);
    lcd.print(gamemodeMessage);
  }

  else if (millis() - previousTime > (interval * 2)) {
    interval = millis();
  }
}

void loop() {
  gamemodeControl();
  gamemodeMessage = "gamemode 1"; //testing purpose
  delay(50);
  gamemodeMessage = "gamemode 2";
  delay(50);
  gamemodeMessage = "gamemode 3";
  delay(50);
}

Think about that for a minute or two interval = millis();

Thank you for your reply, I found one problem.

J-M-L:
Think about that for a minute or two interval = millis();

My Serial Monitor shows the interval value being increased by 1000 each time. So every time the loop cycles, the LCD has to wait 1 second longer, until it becomes 50 days long and overflows. So, this isn't the right way.

I disabledinterval = millis();

So, now the problem is still that the if-condition is never met. There is still a problem there.

What’s the purpose of previousTime?

PreviousTime is compared with the CurrentTime. If the difference is greater than the interval. Then the lCD code will execute.

So once it’s triggered, what should previousTime become?
(There is a good tutorial on how to use millis() pinned at the top of the forum. Suggest you read it :slight_smile: )

I appreciate your quick responses. :slight_smile: The previousTime should save the value of the currentTime when the value difference becomes greater than the interval.

My purpose is to implement this with a sensor in the future. Certain values have a unique gamemode assigned to them. Now, the problem is that the gamemode String message doesn’t update. A solution would be to call gamemodeMessage() again after the message string updates, but that causes screen flicker again and it would defeat my purpose of using the millis() function. I would have to add a delay() again.

Possible solution?
-Switch cases with breaks

Are there more practical ways to solve this problem?

I changed my code

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

LiquidCrystal_I2C lcd(0x27, 16, 2);

int liveAmount = 3;
String gamemodeMessage;

unsigned long previousTime = 0;
unsigned long interval = 1000;

void setup() {
  Serial.begin(9600);
  lcd.backlight();
  lcd.begin();
  lcd.clear();
  lcd.print("Active Learning");
  lcd.setCursor(0, 1);
  lcd.print("Welcome!");
  delay(1000);
}

void gamemodeControl() {
  unsigned long currentTime = millis();

  if (currentTime - previousTime >= interval) {
    lcd.setCursor(0, 0);
    lcd.clear();
    lcd.print("Gamemode:");
    lcd.setCursor(11, 0);
    lcd.print("");
    lcd.setCursor(0, 1);
    lcd.print(gamemodeMessage);
    previousTime = currentTime;
  }
}

void loop() {
  gamemodeControl();
  gamemodeMessage = "gamemode 1"; //testing purpose
  Serial.println(gamemodeMessage);
  gamemodeMessage = "gamemode 2";
  Serial.println(gamemodeMessage);
  gamemodeMessage = "gamemode 3";
  Serial.println(gamemodeMessage);
}

You should referesh only the part Of the LCD that needs refresh, when its content has changed... that’s the best way to avoid flickering :slight_smile:

(And yes for previousTime)

I modified the code to work with sensors. I didn’t know you could refresh only a certain part of the LCD. I will have to look into that later. I am happy with this code. I works fine for now :).

Resetting

lcd.setCursor(x, y);
lcd.print(" ");

My code

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

LiquidCrystal_I2C lcd(0x27, 16, 2);

int liveAmount = 3;
int var;
String gamemodeMessage = "None Selected";

unsigned long previousTime = 0;
unsigned long interval = 1000;

void setup() {
  Serial.begin(9600);
  lcd.backlight();
  lcd.begin();
  lcd.clear();
  lcd.print("Active Learning");
  lcd.setCursor(0, 1);
  lcd.print("Welcome!");
  delay(1000);
}

void gamemodeControl() {
  unsigned long currentTime = millis();

  if (currentTime - previousTime >= interval) {
    lcd.setCursor(0, 0);
    lcd.clear();
    lcd.print("Gamemode:");
    lcd.setCursor(11, 0);
    lcd.print("");
    lcd.setCursor(0, 1);
    lcd.print(gamemodeMessage);
    previousTime = currentTime;
  }
}

void loop() {
  gamemodeControl();
  var = 1; //testing purpose
  //var = 2;
  //var = 3;
  switch (var) {
    case 1:
      gamemodeMessage = "gamemode 1"; 
      Serial.println(gamemodeMessage);
      break;
    case 2:
      gamemodeMessage = "gamemode 2"; 
      Serial.println(gamemodeMessage);
      break;
    case 3:
      gamemodeMessage = "gamemode 3"; 
      Serial.println(gamemodeMessage);
      break;
  }
}