Millis() help! - display for 5 seconds after 20 seconds repeatedly

Hello, I am having trouble using millis I have never used it before,
basically I want a timer that after every 20 seconds my lcd will display the temperature for 5 seconds and then return to displaying just a word "Temp", then again after 20 more seconds the lcd displays the current temp for 5 seconds and so on,
Can somebody help, thankyou!!

#include <Wire.h>
#include <LiquidCrystal.h>

//rs, en, d4, d5, d6, d7
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5); //pins in the arduino

const int btnTemp = A15;
const int tempSensor = A14;

unsigned long tiempo = 0;
unsigned long tiempo1 = 0;
unsigned long timer1 = 0;
unsigned long timer2 = 0;
unsigned long timer3 = 0;
unsigned long timer4 = 0;
unsigned long timer5 = 0;
unsigned long tiempoSeg = 0;

float tempValue;
float tempC;
int btnState;

bool boolTemp = false;



void setup() {
  pinMode(btnTemp, INPUT);
  pinMode(tempSensor, INPUT); // lm35
  
  
  lcd.begin(20, 4);
  lcd.setCursor(1,0);
  lcd.print("RPMin");
  lcd.setCursor(1,2);
  lcd.print("RPMout");
  lcd.setCursor(12,0);
  lcd.print("Speed");
  lcd.setCursor(12,2);
  lcd.print("Temp");

  Serial.begin(9600);
}

void loop() {
tiempo = millis();

if(tiempo > tiempo1 + 2000){
     tiempo1 = millis();
     tiempoSeg = tiempo1/1000;
     Serial.print("Han transcurrido: ");
     Serial.print(tiempoSeg);
     Serial.println(" seg desde que se encendio el Arduino");
  }
   
   tempValue = analogRead(tempSensor);  //reads lm35
   float millivolts = (tempValue / 1023.0) * 5000;
   float tempC = millivolts / 10; //changes analog voltage from lm35 to celcius
   //Serial.println(tempC);

   btnState = digitalRead(btnTemp); //reads push button 
   
  if(tiempo > timer1 + 10000){
     timer1 = millis();
      Serial.println(" ********************************* ");
      Serial.println(" la temperatura1 es de ");
      lcd.print("    ");
      lcd.setCursor(12,2);
      Serial.println(tempC);
      lcd.print(tempC);
      Serial.println(" ******************************* ");
      boolTemp = true;
    }

    if(tiempo > timer1 + 1000 && boolTemp == true){
     timer2 = millis();
      Serial.println(" ********************************* ");
      Serial.println(" la temperatura2 es de ");
      lcd.print("    ");
      lcd.setCursor(12,2);
      Serial.println(tempC);
      lcd.print(tempC);
      Serial.println(" ******************************* ");
    } 

  if(tiempo > timer2 + 1000 && boolTemp == true){
     timer3 = millis();
      Serial.println(" ********************************* ");
      Serial.println(" la temperatura3 es de ");
      lcd.print("    ");
      lcd.setCursor(12,2);
      Serial.println(tempC);
      lcd.print(tempC);
      Serial.println(" ******************************* ");
    }

    if(tiempo > timer3 + 1000 && boolTemp == true){
     timer4 = millis();
      Serial.println(" ********************************* ");
      Serial.println(" la temperatura4 es de ");
      lcd.print("    ");
      lcd.setCursor(12,2);
      Serial.println(tempC);
      lcd.print(tempC);
      Serial.println(" ******************************* ");
    }

    if(tiempo > timer4 + 1000 && boolTemp == true){
     timer5 = millis();
      Serial.println(" ********************************* ");
      Serial.println(" la temperatura5 es de ");
      lcd.print("    ");
      lcd.setCursor(12,2);
      Serial.println(tempC);
      lcd.print(tempC);
      Serial.println(" ******************************* ");
      boolTemp = false;
    }

  

/*
  if(tiempo > tiempo1 + 5000){
     lcd.setCursor(12,2);
     lcd.print("    ");
     lcd.setCursor(12,2);
     lcd.print("Temp");
  }*/
   
  if (btnState == HIGH) { //display temp if btn is pressed
    lcd.setCursor(12,2);
    lcd.print("    ");
    lcd.setCursor(12,2);
    lcd.print(tempC);
    lcd.setCursor(15,2);
    lcd.print((char)223);
    lcd.setCursor(16,2);
    lcd.print(" C");
    //millis;
    //lcd.print("Temp");
  }
}

If you think about your program you have 2 states.

State 1 - Displaying "Temp"
State 2 - Display the actual temperature.

You change from state 1 to state 2 after 20 seconds, and then back to state 1 after another 5 seconds.

Using millis() to keep track of time is fairly easy, but you should take time to understand what is happening.

the basic code...

unsigned long startTime = millis();  // Take a snap shot of the current time
unsigned long duration = 20000;    // 20 seonds
void loop()
{
  unsigned long currentTime = millis();  // Get the current snapshot

  if (currentTime - startTime > duration)  // Is the current snapshot more than duration since startTime ?
  {
    // 20 seconds has gone by since startTime
    startTime = currentTime;  // Set the new startTime snapshot value.
  }
}

So.. for your problem you just need to combine the 2 concepts above... 2 states, and millis() for timing.

Something like...

unsigned long currentTime;                 // Holds the latest snapshot each loop.
unsigned long startTime = millis();        // Set the timer snapshot.
 
int state = 1;                             // Start in state 1

void setup()
{
  Serial.begin(115200);
  Serial.println("Starting");
}

void loop()
{
  currentTime = millis();                   // Get the current time
  
  if (state == 1)                           // Are we in state 1?
  {
    if (currentTime - startTime > 20000)    // Have we been in this state for 20 seconds?

    {
      Serial.println("State 1 done");       // Display message
      state = 2;                            // Move to state 2
      startTime = currentTime;              // Reset the timer snapshot
    }

    // Do state 1 stuff here.
  }
  else if (state == 2)                      // Are we in state 2?
  {
    if (currentTime - startTime > 5000)     // Have we been in this state for 5 seconds?
    {
      Serial.println("State 2 done");       // DIsplay message.
      state = 1;                            // Move back to state 1 
      startTime = currentTime;              // Reset the timer snapshot.
    }
      // Do state 2 stuff here.
  }
  else
  {
    // If you ever have more states
  }
}
2 Likes

It didn't worked exactly I had to modifiy it for it to work, but thankyou very much!!! :slight_smile:

Hello how can I implement millis to display for 5 seconds something every 20 seconds while still doing other stuff in the background, I have this but it doesnt work. The first loop does repeat every 10 seconds but then the other loop I am trying to implement of 5 seconds doesnt work.
I want something like this:
1,2,3,4,5,6,7,8,9,15, 16, 17,18,19temp,temp,temp,temp,temp,25,26,.....,38,39, temp,temp,temp,temp,temp and so on.


unsigned long tAntes1 = 0;
unsigned long tAntes2 = 0;
unsigned long tAhora  = 0;
unsigned long tNow  = 0;

#define seconds5 5000
#define seconds10 10000


bool display = false;
void setup()
{
   Serial.begin(9600);
   Serial.println("Inicio programa:\n");
}


void loop()
{
   tAhora = millis();
   
   // Se ejecuta cada 5 segundos:
   if( tAhora - tAntes2 > seconds10 )
   {
      tAntes2 = tAhora;
      Serial.print("Temperature ("); 
      Serial.print(tAhora/1000); 
      Serial.println(")");
      tNow = millis();

      display = true;
   }   
   if(tAhora - tAntes2 < tNow+seconds5){
        Serial.print("Temperature....");
      }
       tAntes2 = tAhora;
   }

Did you read the reply I posted on your duplicate post?

1 Like

Hello, i thought I answered I'm sorry!!!!!
it didn't work exactly I had to modify it but I wanted to see if there was a shorter version, but id worked!!! thankyoy very much!!! :slight_smile: :slight_smile: :slight_smile:
Do you by any change know how could I have another function that justs does something for 5 seconds, (i need a button that when I press the temperature will always show for 5 seconds (even when the 20 secons are not up))

I have this: (old state is a button press state)


  if (oldState == 1) { //display temp if btn is pressed
    oldState = 1;
      if ( second == true){
        tempActual = tempC;
         timePeriod = millis + 50000;
        second = false;
      }
Serial.println(oldState);
         currentTime = millis();
         if (currentTime - startTime > 5000)    {
                startTime = currentTime;              // Reset the timer snapshot

    
            lcd.setCursor(10,3);
            lcd.print(tempActual);
            lcd.setCursor(15,3);
            lcd.print((char)223);
           lcd.setCursor(16,3);
            lcd.print(" C");
    } else {
      oldState = 0;
    }
}
      
}  

I have merged your overlapping topics @adrianate. Please only create one topic for each distinct subject matter.

The reason is that these tend to produce parallel discussions, which can waste the time of the people trying to help. Someone might spend a lot of time investigating and writing a detailed answer on one topic, without knowing that someone else already did the same in the other topic. As in this case, one topic might provide valuable context that responders to the other topic will not necessarily be aware of.

Is this as well as the existing functionality OR instead of?

Post ALL your code... part of the code is pretty useless to anyone trying to help.

unsigned long prMillis = 0;

void loop()
{
     prMillis = millis();
     while(millis() - prMillis < 20000)
     {
           //do your tasks
     }
   
     prMillis = millis();
     while(millis() - prMillis < 5000)
     {
           //do your other tasks
     }
}

@GolamMostafa This code is blocking... the while loops don't allow anything else to run.

Not a great example of how to use millis().

The OP has asked for:

Temp: 23.7 degC       // message (for example) for 5-sec
Temp:                 //message for 20-sec
repeat

The above tasks can be done using delay() function; but, the OP wants the use of millis() function where he can do do some other tasks (post #10) along with displaying the said messages.

How does your solution allow other tasks to be done? You have basically written a delay function with millis.

while(millis() - prMillis < 5000)
{
     acquire Temperature and show on LCD.
     refresh multiplexed display unit if any.
     check if fire alarm is ON.
}

In the above, are 4 tasks not being carried out simultaneously (time sharing)?

Yes within the while loop... BUT... if you wanted to acquire the temperature outside of the while loop, or check a button, or check a sensor ... then the code needs to be repeated in every while loop, and then again in the main loop. If you have 10 timed events then you repeat the common code 10 times !

That is a terrible example of how to use millis.

1 Like

You are right and then the approach of "blink without delay" is to be applied.

1 Like

How is this one?

Typical Example:

bool processState = false;
unsigned long previousMillis = 0;
unsigned long interval = 5000; //process1; will be changed to 20000 for process2

void setup()
{
  Serial.begin(9600);
  showTempDegC();   //acquire and show: Tem: 25 degC for 5-sec
}

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;
    if (processState == false)
    {
      processState = true;
      interval = 20000;
      showTempMsg();     //stays for 20-sec
    }
    else
    {
      processState = false;
      interval = 5000;
      showTempDegC();   //stays for 5-sec
    }
  }
  else
  {
    //other tasks should be done in less than 5-sec
  }
}

void showTempDegC()
{
  Serial.println("Temp: 25 degC");
}

void showTempMsg()
{
  Serial.println("Temp:");
}

Better.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.