Help with using millis()

I started a similar post in the hardware forum but thought it should be here instead. I asked a moderator to remove the post from the hardware forum.

In any case, I made an LED script that pulses an LED like a heartbeat. The script is as follows:

/*
  Heart Beat for Start Button
  Jaguar Start Button blinks like a heartbeat with KOEO( Key on Engine off )
  until pressed to start car
 */
  int heartLED = 10;
  int time = 2;
  int pulsewidth; 
  
  void setup() {                
  // Nothing needed for analoge pwm 
  }

void loop() {
  
 for (pulsewidth=0; pulsewidth <= 255; pulsewidth++){  
     
       analogWrite(heartLED, pulsewidth);  
     
       delay(time/3); 
       
     }  
     // slowly dim the LEDs  
     for (pulsewidth=255; pulsewidth >= 0; pulsewidth--){  
     
       analogWrite(heartLED, pulsewidth);  
    
       delay(time/2);  
     }  
     for (pulsewidth=0; pulsewidth <= 255; pulsewidth++){  
     
       analogWrite(heartLED, pulsewidth);  
     
       delay(time/2); 
       
     }  
     // slowly dim the LEDs  
     for (pulsewidth=255; pulsewidth >= 0; pulsewidth--){  
     
       analogWrite(heartLED, pulsewidth);  
    
       delay(time*2);
         
     }  
     delay(200);
  
}

I asked if the delays in the script would inhibit any other things I want to add to the script later and I was advised that it would, and was directed to a millis() and blink without delay example on the arduino site.

My problem is, Even after reading those examples and trying to change my code, I am NOT understanding millis() or how to use them properly. When I tried to implement them in my code and commented out my delays, the LED just stayed on solid.

So if someone here could break this down for me ( spoon feed me) so that I can substitute delay(), for... count(millis and wait than continue)

I would appreciate the help.

millis() simply returns the current value of a counter that automatically increments 1000 times per second.
So rather than calling delay() which hangs you program during the delay, you could take the current value of millis() and add the number of milliseconds you wanted to wait.
Then, your code can check, every once in a while, if millis() has reached that precomputed value. The advantage is that the code then can do other things as well.

Yes, Richard explained that to me, I just can't seem to write the code to make that reality. I tried cutting and pasting from the examples, and also tried writing what I thought was correct to no avail.

So a working code snippet of how I should modify my code is requested, than once it works I can learn to manipulate it and figure out how it worked as I'm a hands on learner, more than a reading and comprehension learner.

       delay(time/3);

This would wait for 2/3 of a millisecond, it delay took floats as input. Since it doesn't, this is equivalent to delay(0).

Think of millis() as you having a watch, rather than an alarm clock. delay is like an alarm clock. Nothing happens until it goes off. With a watch, on the other hand (although who wears an alarm clock on their wrist, and why does it matter which hand the watch is on), you have to check it frequently to see if it's time to do something.

So, you need to separate the decision making from the action. Decide, based on switch input, potentiometer settings, etc. what needs to be done. Then do it.

In your case, there is no decision making. All the code is action code.

So, you need to set up some states (one for each for loop that you have), and a way of keeping track of which state you are in.

int state = 0;
void loop()
{
   unsigned long now = millis();
   switch(state)
   {
      case 0:
        // First for loop stuff
        break;
     case 1:
        // Second for loop stuff
        break;
     case 2:
        // Third for loop stuff
        break;
     case 3:
        // Fourth for loop stuff
        break;
   }
}

Now let's look at one case. We need to know the value to set the pin to, at the appropriate time. This should be a global (or static local) variable.
int pulseWidth = 0;

We also need to keep track of WHEN the value was last written to the pin, and how long the pin should retain that value, as global variables:
unsigned long pulseChange = 0;
unsigned long interval = 1;

The case 1 code looks like this:

if(now - pulseChange >= interval)
{
   // It's time to change the pulseWidth
   pulseWidth++;
   
   // Is pulseWidth still valid?
   if(pulseWidth <= 255)
   {
      analogWrite(heartLED, pulsewidth);
      pulseChange = now;
   }

   // It's not, so it's time to change state
   else
   {
      state++;
      if(state > 3)
         state = 0;
   }
}

With this, it should be easy to figure out how to change the other loops.

If you want a fifth state, case 4, that does nothing (to emulate the delay(200)), that's easy. Be sure to change the "> 3"s to "> 4"s.

This would wait for 2/3 of a millisecond, it delay took floats as >input. Since it doesn't, this is equivalent to delay(0).

I had "time" as an integer and assigned it "2". I thought that made the word "time" equal to "2" seconds. It did seem to wait that long in the code, and I divided the time or multiplied the time accordingly to get the pulsing rate I liked. I didn't realize I was setting the delay to "0". Thanks for the heads up.

I will work on what you gave me and see if I run into any other problems. Thank you for your time.

I had "time" as an integer and assigned it "2". I thought that made the word "time" equal to "2" seconds.

No. The input to delay is a duration in milliseconds, not seconds.

The time/3 calculation is performed using integer arithmetic, since both values are integers. 2/3 = 0.