Need help with using millis() with lcd

Hi I am trying to use the function millis() with my lcd. What I want my code to do is display two sentences on the same line with a 3000 millis delay for each. However, I can not use the delay() function as I also have to use the keypad. With my code now when the cursor is at (0,2) the sentences keep overlapping and changing very quickly. Any suggestions on what I can add to my code to have that 3000 millis difference? Thank you.


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

LiquidCrystal_I2C lcd(0x27,20,4); 
#include <Keypad.h>

const long interval = 3000;
unsigned long currentMillis = 3000;

const byte ROWS = 4; 
const byte COLS = 4; 


char keys[ROWS][COLS] = {

  {'1','2','3', 'A'},
  {'4','5','6', 'B'},
  {'7','8','9', 'C'},
  {'*','0','#', 'D'}
};

byte rowPins[ROWS] = { 9,8,7,6 };
byte colPins[COLS] = { 5,4,3,2 }; 

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); 


 long Num1,Num2,Number;
 char key,action;
 boolean result = false;
 
void setup() {
  lcd.init();  
  lcd.begin(20,4);                 
  lcd.backlight();  
}


void loop() {

  unsigned long currentMillis = millis();

  lcd.setCursor(0,2);             
  lcd.print("Dry Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("10");
  millis();
  lcd.print(" ");
 
  lcd.setCursor(0,2);             
  lcd.print("Wet Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("30");
  millis();
  lcd.print(" ");

  lcd.setCursor(0, 0);
  lcd.print("Enter Duct Size(in): ");
  
key = kpd.getKey(); 

if (key!=NO_KEY)
DetectButtons();

if (result==true)
CalculateResult();

DisplayResult();   
}


void DetectButtons()
{ 
    lcd.clear(); 
    if (key=='C') 
    {Serial.println ("Clear"); Number=Num1=Num2=0; result=false;}
    
    if (key == '1')
    {Serial.println ("Button 1"); 
    if (Number==0)
    Number=1;
    else
    Number = (Number*10) + 1; 
    }
    
     if (key == '4') 
    {Serial.println ("Button 4"); 
    if (Number==0)
    Number=4;
    else
    Number = (Number*10) + 4; 
    }
    
     if (key == '7') 
    {Serial.println ("Button 7");
    if (Number==0)
    Number=7;
    else
    Number = (Number*10) + 7; 
    } 
  

    if (key == '0')
    {Serial.println ("Button 0"); 
    if (Number==0)
    Number=0;
    else
    Number = (Number*10) + 0; 
    }
    
     if (key == '2') 
    {Serial.println ("Button 2"); 
     if (Number==0)
    Number=2;
    else
    Number = (Number*10) + 2; 
    }
    
     if (key == '5')
    {Serial.println ("Button 5"); 
     if (Number==0)
    Number=5;
    else
    Number = (Number*10) + 5; 
    }
    
     if (key == '8')
    {Serial.println ("Button 8"); 
     if (Number==0)
    Number=8;
    else
    Number = (Number*10) + 8; 
    }   
  

    if (key == '#')
    {Serial.println ("Equal"); 
    Num2=Number;
    result = true;
    }
    
     if (key == '3')
    {Serial.println ("Button 3"); 
     if (Number==0)
    Number=3;
    else
    Number = (Number*10) + 3; 
    }
    
     if (key == '6')
    {Serial.println ("Button 6"); 
    if (Number==0)
    Number=6;
    else
    Number = (Number*10) + 6; 
    }
    
     if (key == '9')
    {Serial.println ("Button 9");
    if (Number==0)
    Number=9;
    else
    Number = (Number*10) + 9; 
    }  

      if (key == '*') 
  {
    Num1 = Number;    
    Number =0;
    if (key == '*')
    {action = '*';}
    delay(100);
  }
  
}

void CalculateResult()
{
  if (action=='*')
    Number = Num1*Num2;
}

void DisplayResult()
{
  lcd.setCursor(2, 1);   
  lcd.print(Num1); lcd.print(action); lcd.print(Num2); 
  
  if (result==true)
  {lcd.print(" Area = "); lcd.print(Number/12); lcd.setCursor(17,1); lcd.print("ft");}

}





Hello zxames12
Take a view at the BlinkWithOutDelay exmple from the IDE, based on this example you are able to design and build your own timers for your project.
Have a nice day and enjoy coding in C++.

Thank you for your help. I tried this but I am still getting the same result where the sentences are changing really fast. I would like the first sentence to change to the second one after 3000 millis. Is there anything else I can try?


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

LiquidCrystal_I2C lcd(0x27,20,4); 
#include <Keypad.h>

unsigned long previousMillis = 0;
const long interval = 3000;  

const byte ROWS = 4; 
const byte COLS = 4; 


char keys[ROWS][COLS] = {

  {'1','2','3', 'A'},
  {'4','5','6', 'B'},
  {'7','8','9', 'C'},
  {'*','0','#', 'D'}
};

byte rowPins[ROWS] = { 9,8,7,6 };
byte colPins[COLS] = { 5,4,3,2 }; 

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); 


 long Num1,Num2,Number;
 char key,action;
 boolean result = false;
 
void setup() {
  lcd.init();  
  lcd.begin(20,4);                 
  lcd.backlight();  
}


void loop() {

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
  }
  
  lcd.setCursor(0,2);             
  lcd.print("Dry Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("10");
  millis();
  lcd.print(" ");
 
  lcd.setCursor(0,2);             
  lcd.print("Wet Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("30");
  millis();
  lcd.print(" ");

  lcd.setCursor(0, 0);
  lcd.print("Enter Duct Size(in): ");
  
key = kpd.getKey(); 

if (key!=NO_KEY)
DetectButtons();

if (result==true)
CalculateResult();

DisplayResult();   
}


void DetectButtons()
{ 
    lcd.clear(); 
    if (key=='C') 
    {Serial.println ("Clear"); Number=Num1=Num2=0; result=false;}
    
    if (key == '1')
    {Serial.println ("Button 1"); 
    if (Number==0)
    Number=1;
    else
    Number = (Number*10) + 1; 
    }
    
     if (key == '4') 
    {Serial.println ("Button 4"); 
    if (Number==0)
    Number=4;
    else
    Number = (Number*10) + 4; 
    }
    
     if (key == '7') 
    {Serial.println ("Button 7");
    if (Number==0)
    Number=7;
    else
    Number = (Number*10) + 7; 
    } 
  

    if (key == '0')
    {Serial.println ("Button 0"); 
    if (Number==0)
    Number=0;
    else
    Number = (Number*10) + 0; 
    }
    
     if (key == '2') 
    {Serial.println ("Button 2"); 
     if (Number==0)
    Number=2;
    else
    Number = (Number*10) + 2; 
    }
    
     if (key == '5')
    {Serial.println ("Button 5"); 
     if (Number==0)
    Number=5;
    else
    Number = (Number*10) + 5; 
    }
    
     if (key == '8')
    {Serial.println ("Button 8"); 
     if (Number==0)
    Number=8;
    else
    Number = (Number*10) + 8; 
    }   
  

    if (key == '#')
    {Serial.println ("Equal"); 
    Num2=Number;
    result = true;
    }
    
     if (key == '3')
    {Serial.println ("Button 3"); 
     if (Number==0)
    Number=3;
    else
    Number = (Number*10) + 3; 
    }
    
     if (key == '6')
    {Serial.println ("Button 6"); 
    if (Number==0)
    Number=6;
    else
    Number = (Number*10) + 6; 
    }
    
     if (key == '9')
    {Serial.println ("Button 9");
    if (Number==0)
    Number=9;
    else
    Number = (Number*10) + 9; 
    }  

      if (key == '*') 
  {
    Num1 = Number;    
    Number =0;
    if (key == '*')
    {action = '*';}
    delay(100);
  }
  
}

void CalculateResult()
{
  if (action=='*')
    Number = Num1*Num2;
}

void DisplayResult()
{
  lcd.setCursor(2, 1);   
  lcd.print(Num1); lcd.print(action); lcd.print(Num2); 
  
  if (result==true)
  {lcd.print(" Area = "); lcd.print(Number/12); lcd.setCursor(17,1); lcd.print("ft");}

}





Hello zxames12
Check your code again.
You have coded a timer but the timing function migth not be implemented correct.
Have a nice day and enjoy coding in C++.

Sorry can you show this on my code because I am having trouble understanding exactly what is wrong.

Tell us what you think is happening here ?


  if (currentMillis - previousMillis >= interval) 
  {
    previousMillis = currentMillis;
  }

if the currentmillis - previousmillis is greater than or equal to the interval then they both equal each other?

As it is, these lines of code don’t do anything useful.

If, on the other hand, you add some code between the braces, then that code would run every 3 seconds.

example:


interval = 3000;
. . .

  if (currentMillis - previousMillis >= interval) 
  {
    //restart this TIMER
    previousMillis = currentMillis;

    digitalWrite( myLED, !digitalRead(myLED);  // toggle myLED every 3 seconds
  }

Oh ok so if I were to add my lcd code between the braces then it should print every 3 seconds?

Give it a try.

:wink:

1 Like

Thank you! I am getting closer to what I am wanting however, with this new change the lcd.print("Wet Bulb Temp ( C): "); line stays on the lcd and the lcd.print("Dry Bulb Temp ( C): "); line is going so fast I can't see it. I tried chaning the previousMillis = 0; and interval = 1000; values to a higher millis but the results are the same.


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

LiquidCrystal_I2C lcd(0x27,20,4); 
#include <Keypad.h>

unsigned long previousMillis = 0;
const long interval = 1000; 


const byte ROWS = 4; 
const byte COLS = 4; 


char keys[ROWS][COLS] = {

  {'1','2','3', 'A'},
  {'4','5','6', 'B'},
  {'7','8','9', 'C'},
  {'*','0','#', 'D'}
};

byte rowPins[ROWS] = { 9,8,7,6 };
byte colPins[COLS] = { 5,4,3,2 }; 

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); 


 long Num1,Num2,Number;
 char key,action;
 boolean result = false;
 
void setup() {
  lcd.init();  
  lcd.begin(20,4);                 
  lcd.backlight();  
}


void loop() {

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
  lcd.setCursor(0,2);             
  lcd.print("Dry Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("10");
  lcd.print(" ");
 
  lcd.setCursor(0,2);             
  lcd.print("Wet Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("30");
  lcd.print(" ");
    previousMillis = currentMillis;
  }
  

  lcd.setCursor(0, 0);
  lcd.print("Enter Duct Size(in): ");
  
key = kpd.getKey(); 

if (key!=NO_KEY)
DetectButtons();

if (result==true)
CalculateResult();

DisplayResult();   
}


void DetectButtons()
{ 
    lcd.clear(); 
    if (key=='C') 
    {Serial.println ("Clear"); Number=Num1=Num2=0; result=false;}
    
    if (key == '1')
    {Serial.println ("Button 1"); 
    if (Number==0)
    Number=1;
    else
    Number = (Number*10) + 1; 
    }
    
     if (key == '4') 
    {Serial.println ("Button 4"); 
    if (Number==0)
    Number=4;
    else
    Number = (Number*10) + 4; 
    }
    
     if (key == '7') 
    {Serial.println ("Button 7");
    if (Number==0)
    Number=7;
    else
    Number = (Number*10) + 7; 
    } 
  

    if (key == '0')
    {Serial.println ("Button 0"); 
    if (Number==0)
    Number=0;
    else
    Number = (Number*10) + 0; 
    }
    
     if (key == '2') 
    {Serial.println ("Button 2"); 
     if (Number==0)
    Number=2;
    else
    Number = (Number*10) + 2; 
    }
    
     if (key == '5')
    {Serial.println ("Button 5"); 
     if (Number==0)
    Number=5;
    else
    Number = (Number*10) + 5; 
    }
    
     if (key == '8')
    {Serial.println ("Button 8"); 
     if (Number==0)
    Number=8;
    else
    Number = (Number*10) + 8; 
    }   
  

    if (key == '#')
    {Serial.println ("Equal"); 
    Num2=Number;
    result = true;
    }
    
     if (key == '3')
    {Serial.println ("Button 3"); 
     if (Number==0)
    Number=3;
    else
    Number = (Number*10) + 3; 
    }
    
     if (key == '6')
    {Serial.println ("Button 6"); 
    if (Number==0)
    Number=6;
    else
    Number = (Number*10) + 6; 
    }
    
     if (key == '9')
    {Serial.println ("Button 9");
    if (Number==0)
    Number=9;
    else
    Number = (Number*10) + 9; 
    }  

      if (key == '*') 
  {
    Num1 = Number;    
    Number =0;
    if (key == '*')
    {action = '*';}
    delay(100);
  }
  
}

void CalculateResult()
{
  if (action=='*')
    Number = Num1*Num2;
}

void DisplayResult()
{
  lcd.setCursor(2, 1);   
  lcd.print(Num1); lcd.print(action); lcd.print(Num2); 
  
  if (result==true)
  {lcd.print(" Area = "); lcd.print(Number/12); lcd.setCursor(17,1); lcd.print("ft");}

}

Since you are reusing the same LCD locations You need to come up with a design that switches between displays alternately.

Example:

Let’s say you have a variable called oddFlag

byte oddFlag = 0;

When oddFlag is == to 0 you print to the LCD Wet Bulb Temp
When oddFlag is == to 1 you print to the LCD Dry Bulb Temp

In your 3 second TIMER oddFlag needs to be changed between 0 and 1.
Therefore, the first 3 seconds you get Wet Bulb and then the next 3 seconds you get Dry Bulb etc.

Thank you that helped. How would i change oddFlag from 0 to 1 without manually typing it in?

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

LiquidCrystal_I2C lcd(0x27,20,4); 
#include <Keypad.h>

unsigned long previousMillis = 0;
const long interval = 100; 

byte oddFlag = 0;


const byte ROWS = 4; 
const byte COLS = 4; 


char keys[ROWS][COLS] = {

  {'1','2','3', 'A'},
  {'4','5','6', 'B'},
  {'7','8','9', 'C'},
  {'*','0','#', 'D'}
};

byte rowPins[ROWS] = { 9,8,7,6 };
byte colPins[COLS] = { 5,4,3,2 }; 

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); 


 long Num1,Num2,Number;
 char key,action;
 boolean result = false;
 
void setup() {
  lcd.init();  
  lcd.begin(20,4);                 
  lcd.backlight();  
}


void loop() {

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {

  
  if (oddFlag==0)
    {
  lcd.setCursor(0,2);             
  lcd.print("Dry Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("10");
  lcd.print(" ");
  
    }  

  if (oddFlag==1)
  {
  lcd.setCursor(0,2);             
  lcd.print("Wet Bulb Temp ( C): ");
  lcd.setCursor(15,2);
  lcd.print((char)223);
  lcd.setCursor(1,3);
  lcd.print("20");
  lcd.print(" ");
  
  }
  previousMillis = currentMillis;
  }

You need something like this (to be tested):

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

LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <Keypad.h>

unsigned long previousMillis = 0;
const long interval = 100;

byte oddFlag    = 0;

const byte ROWS = 4;
const byte COLS = 4;


char keys[ROWS][COLS] =
{

  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = { 9, 8, 7, 6 };
byte colPins[COLS] = { 5, 4, 3, 2 };

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


long Num1, Num2, Number;
char key, action;
boolean result = false;


//***************************************************************************
void setup()
{
  lcd.init();
  lcd.begin(20, 4);
  lcd.backlight();
  
} //END of   setup()


//***************************************************************************
void loop()
{
  unsigned long currentMillis = millis();

  //**************************************************
  if (currentMillis - previousMillis >= interval)
  {
    //restart this TIMER
    previousMillis = currentMillis;

    //**********************
    if (oddFlag == 0)
    {
      lcd.setCursor(0, 2);
      lcd.print("Dry Bulb Temp ( C): ");
      lcd.setCursor(15, 2);
      lcd.print((char)223);
      lcd.setCursor(1, 3);
      lcd.print("10");
      lcd.print(" ");
    }

    //**********************
    else
    {
      lcd.setCursor(0, 2);
      lcd.print("Wet Bulb Temp ( C): ");
      lcd.setCursor(15, 2);
      lcd.print((char)223);
      lcd.setCursor(1, 3);
      lcd.print("20");
      lcd.print(" ");
    }

    //toggle the Flag
    oddFlag = 1 - oddFlag;

  }

} //END of   loop()

That worked!! Thank you so much!

You need to make interval = 3000; //3 seconds

Do you know why it works ?

Yes i changed it to 3000. Thank you again!

Do you know why it works ?

yes I had to make it an if else statement to have the print change.

And you have to:

    //toggle the Flag
    oddFlag = 1 - oddFlag;

When it is 0, it changes to 1 (Odd)

When it is 1, it changes to 0 (Even)