Can someone help me get around this problem with millis?

When using the millis() function, it's important to understand that it works very differently from delay(). In my example below, the code is supposed to turn on the LED after 5 seconds, but it turns on after only 3 seconds. This happens because the condition after delay() becomes true while the code is still waiting for the delay, which means that millis() keeps counting during this time, leading to an incorrect comparison.

I would like to know how to work around this issue. I know that a simple solution would be to add a 5-second timer, but what would I learn from that? Sooner or later, I would encounter the same problem again.

Making it very clear that the objective is not to mix millis with delay, the example is merely didactic

The goal is for the code to work in such a way that the time in millis waits for the delay, because currently the function becomes true even before the code finishes the delay

This way the Led turns on in 3s, when it should turn on in 5s

Here is the code I am using:

unsigned long previousMillis = 0;  
// Defined outside the loop  

void setup() {  
  pinMode(LED_BUILTIN, OUTPUT);  
}  

void loop() {  
  delay(3000); // Waits 3 seconds before starting  

  if (millis() - previousMillis >= 2000) {  // Waits 2 seconds after the delay  
    digitalWrite(LED_BUILTIN, HIGH);  // Turns on the LED after 5 seconds (3s delay + 2s millis)  
    // Do not update previousMillis here to avoid resetting the count  
  } else {  
    digitalWrite(LED_BUILTIN, LOW);  
  }  
}

Well, don’t use delay and instead of 2000, make it 5000. Keep in mind, this will only briefly flash the LED. You should also consider how long it stays lit before turning off.

If you are using millis to keep track of your time by comparing it to previousMillis, you should then update previousMillis inside that IF statement, otherwise it will only be true once or until it rolls over.

Actually in your case it will always be true until it rolls over which may take a while.

Well, I had even talked in the text about why I didn't do this, but in short it's because this happens even without the use of delay and I want to learn how to get around this problem

Then offset previousMillis by 3000. Though if you are doing anything with timers, it’s best not to mix delay with millis.

There is an example sketch called “Blink Without Delay” that we tell everyone who are just starting out, to learn.

  • Always provide us with a written preamble on how your sketch is to operate (exactly).
  delay(3000); // Waits 3 seconds before starting

  if (millis() - previousMillis >= 2000)    // Waits 2 seconds after the delay
  • Are you aware previousMillis was zero at powerup time and when the if(. . .) is first executed, 3 seconds has gone by already ?

Study this excellent tutorial: https://www.baldengineer.com/blink-without-delay-explained.html

Write a millis timer method in a class.
Where MillisStart is set to milllis() at when timer is created...

Im read this tutorial

What is the task of your sketch in real life?

Check out this program code mods:

unsigned long previousMillis = 0;
const unsigned long intervalMillis[] {2000, 3000};

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  //  delay(3000); // Waits 3 seconds before starting
  unsigned long currentMillis = millis();

  if (currentMillis  - previousMillis >= intervalMillis[digitalRead(LED_BUILTIN)])
  {
    previousMillis = currentMillis;
    digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) ? LOW : HIGH);
    /*
      digitalWrite(LED_BUILTIN, HIGH);  // Turns on the LED after 5 seconds (3s delay + 2s millis)
      // Do not update previousMillis here to avoid resetting the count
      } else {
      digitalWrite(LED_BUILTIN, LOW);
      }
    */
  }
}

You must to learn a simple thing - do not combine a delay() and millis() approaches managing the same time interval.