
Making the move to millis()-based code can be daunting. You have to rethink your logic, implement flags, program a state machine — and more importantly, start using millis(). Generally in forums and on IRC people will just point to the “blink without delay” example, hoping the commented code is enough for a new user. It’s not enough.
I have a growing list of millis()-based tasks posted in my millis() cookbook. But sometimes that those examples might be too simple or not close enough to your project’s end target. That got me thinking about different ways to help explain how millis() works. I thought “wow, you need to understand every line of an example” which leads me to: line-by-line.
Give this “blink without delay line by line” tutorial a shot if you’ve had trouble understanding other millis() examples.
If you aren’t familiar with the blink without delay example, here is a stripped-down version.
const int ledPin = 13; int ledState = LOW; unsigned long previousMillis = 0; unsigned long interval = 1000; void setup() { pinMode(ledPin, OUTPUT); } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis > interval) { previousMillis = currentMillis; if (ledState == LOW) ledState = HIGH; else ledState = LOW; digitalWrite(ledPin, ledState); } }
Global Variables
const int ledPin = 13;
Like many example scripts, this code uses the Arduino onboard LED. If you’re using a LaunchPad with Energia, you would want to change this to something like “GREEN_LED.”
Notice that this is an integer variable type with the const. This keyword tells the compiler the value of “ledPin” cannot change. There is also some optimizations that occur with avr-gcc for variables declared as const.
The difference between const and #define is defined in another post, if you want to dig a little deeper.
int ledState = LOW;
This state variable, or flag variable, is going to track the state of the LED. When using millis() it is pretty common to create these “state variables” to track what is happening in the code.
Are you new to “flags” and “states”? Then check out this post on flag variables and this one on state machines with an enum.
unsigned long previousMillis = 0;
Blink without delay needs to keep track from loop-to-loop. This variable will let us know the “last” time we checked millis().
Since millis() returns an unsigned long, this variable needs the same variable type.
unsigned long interval = 1000;
We need to wait a certain amount of time between states. Here we call the variable “interval”.
Unless I am tight on RAM, I’ll define “interval” as an unsigned long, even if the number could have fit into an int.
Using the same variable types avoids casting problems, or more likely, bugs because I don’t always understand how the compiler casts variables.
setup()
void setup() { pinMode(ledPin, OUTPUT); }
Okay, this is more than 1 line of code. But the only thing we need to do is set our LED’s pin to OUTPUT.
loop()
void loop() {
The key to remember is that code inside of loop() will run for forever. In millis()-based code, we want to write everything with the mindset: “This will run thousands of times a second.”
What does that mindset mean? It means lots of if-statements and variable checks. No, not working? Okay, I’ll use an analogy to get through the rest of the code.
Sandwich example
Let’s say you order a delicious sandwich. The waiting time is 10 minutes. So you look at your watch and see that it is 12:04 pm. After sitting down you check your watch again, now it is 12:05 pm—9 minutes to go. Bored you start reading /r/funny.
Now you look at your watch, and it is 12:09 pm—5 minutes to go. Wow, time is flying. At this point, you decide to see read an analysis of last week’s Mr. Robot. You check your watch, and it is 12:13 pm.
Great, only one more minute.
Pack up your things, look at your watch and it says 12:14 pm—0 minutes! Excellent, time to go and get your delicious sandwich.
The key here is that you didn’t use a “timer” or “alarm.” Instead, while you were busy doing other things (aka multitasking) you kept checking to see how much time had passed since the start.
unsigned long currentMillis = millis();
Each time loop() runs, we need to check the current time. Think of this as looking at your watch to see what time it is right now.
(The very first time we go through loop(), previousMillis is still going to be set to “0”. Technically that was the FIRST time we looked at the time.)
if(currentMillis - previousMillis > interval) {
Here is the magic code that scares people new to millis()-based programs. This single line of code appears in more than just “blink without delay”. For example, all of my millis()-cookbook examples have this line of code .
The code simply reads subtract the current time from the previous time. Then check if more than our waiting time has passed.
Using subtraction like this handles the case where millis() “rolls-over” in 49 days.
This post goes into detail about how to avoid millis() rollover. Most people try to reset millis(), when all you need to do is handle roll over.
previousMillis = currentMillis;
Here’s where we update previousMillis for the first time. Whenever our waiting period has passed, we need to reset the initial time.
If your millis() code doesn’t seem to be working, check to make sure you are resetting previousMillis.
if (ledState == LOW) ledState = HIGH; else ledState = LOW;
Even those this isn’t a single line, the C-complier sees it as 1 line. Basically, we need to toggle the state of ledState so that it will turn ON or OFF.
digitalWrite(ledPin, ledState); } }
The last thing we do is set the LED to its state variable.
This code is the breakdown of the example included with the Arduino(-based) IDEs. In my code, I generally leave the digitalWrite() outside of the if-statement.
Exercise for the reader
Ready to test your knowledge? Okay, add a push-button to this code to enable or disable the blinking.
Question: What other common Arduino / Microcontroller examples do you need explained? You can leave a comment by clicking here.
Hi James, I love your tutorials. My problem is:
From “Master-Slave” coding to light on/off a LED with “H” and “L” chars sent to a Serial Monitor, I try ADDING code to also start and stop Stepper motor to that LED lightning .
What avenue could be best for me to do that?
I try code in loop…and code in Function….no success.
Thanks.
Simon.
I’m not able to help debug code (especially when I can’t see it.) I would suggest posting your question, along with code, on the Arduino Programming Forum. That way others can help.
Hi James! Thanks a lot for the line-by-line explanation.
I need to keep the LED on for 1s and then keep it off for the next 3 seconds and so on. Could you please help me how to do this ?
Thanks
Independant on-off tutorial.
I would like to know how to blink an LED twice or three time in per second. I am new to Arduino and found your site most informative in my learning Arduino Coding.
Change the interval. 250ms would be twice per second. 166ms would be (about) 3 times per second.
Thanks James, I stumbled on this while trying to figure out why my code wasn’t multitasking.
I really appreciate the line-by-line explanation.
Hello,
Great write up – the line by line was very helpful for beginners like myself. I need some further advice on how to do the following:
1- Always be “looking” for a switch
2- When the switch is closed sweep a servo (I have this part of the code working nicely)
3- Wait some amount of time when the sweep is complete to start “looking” for the switch being closed again. So even if the switch is held closed or closed again during this time frame the servo will not sweep.
It seems I need to somehow use the Millis() command and perhaps some type of flag/states as in your example code in the comments below. I’m just not sure how to tie them together and any help is much appreciated as I mentioned I’m new to the Arduino/coding world.
Thanks!
Hi! I need to use the Millis() command while reading data from the HX711 ADC. Do you happen to have any tutorial about how to program any ADC (such as the HX711), please? Thank you!
hi
i am working on a project theft intimation of vehicles using gsm and tracking it by gps.
here i am getting stuck with the infinite loop used in gps as it is continuously sending the lattitude and longitude. i also have to check 4 ir sensors and a pir sensor continuously.
please help me urgently for how am i going to use two loops in a program, out of which one is infinite loop.
the codes i am using are
(code removed)
please reply as soon as posible
thank you
Since this is so urgent, it is probably better to post on a public forum. I suggest the “Project Guidance” section of the Arduino.cc forums.
Hi,
I’m trying to figure out how to print a statement after a certain amount of time after a button is pushed and held down. Millis() starts at the beginning of when the program starts and I want it after the button is pushed. Any suggestions?
Just like all of the other millis() examples I have. Record the time at which the event occurs, then compare to the previous time. Use flags to control when the message goes out.
Something like this:
Thanks, this was very helpful. Also, I am so going to tweet your quote thousands of times.
🙂
Hey James-
I have been trying to wrap my brain around the millis() concept and i seem to be missing something. I have read your posts roughly 5-6 times each. I just can’t grasp the concept. I have the below code that currently is running and working just fine. I am looking to add a string of Neopixel code to run while the linear actuator is moving both up or down, but only then. Think of it like a warning light while the actuator is moving. I understand the delay() function literally stops the whole void loop() and nothing else can be done, but I just can’t apply the millis() concept. If you have time I would appreciate you taking a look at my code and seeing if you can point me in a direction. I am fairly new to the Arduino world, and while I am enjoying myself I find moments like these frustrating. I appreciate your help in advance.
The Neopixel code would go where I’ve marked it below:
The changes you need to make aren’t difficult, but will require rethinking the code. Your code can’t have sequential steps. Instead, you need to build “states”. This lets the code decide what the next step will be. For example, once a button is pressed set a flag to high. if that flag is high and relay1’s initial state is 0, then turn it on and “wait.” once that time is over, make relay1’s state be equal to 1 for the off time and “wait.” once that is done set your relay1 state flag back to 0 and start the process with relay2.
More than I can explain in comments here. I’d suggest you post your code and request on the arduino programming forum [forum.arduino.cc]. Feel free to provide the link once you do, and I’ll try to answer there.
In the mean time, 3 things I noticed:
1) based on the code, you need to make sure you are using pull-down resistors with your buttons. Otherwise, you’ll get false reads.
2) your variable names aren’t very helpful. instead of “button2” make it “red lights” or whatever it controls. It is very easy to get confused between the numbers you make up, the pin numbers on the arduino, and pin numbers on the device when reading through code.
3) I would avoid using D0 and D1, since those conflict with serial. So if you want to do any debugging, that is going to be very difficult.
Thanks, James, for another excellent post! You might consider, however, revising it to keep the line numbers of the extracted lines consistent with the line numbers of the complete program.
I’ve updated the lines with matching numbers. Thanks for the great suggestion.
Having some trouble, I can get the led to stay on instead of off. Which I need, so i need it to blink with a momentary toggle. Press on Blink,press again Blink off but Led stays on. How can I implement the toggle button code into this?
Thank you!
Not sure what you want to achieve. Do you mean having a button to start/stop the blinking?
1st short button-press blinking starts
2nd short button-press blinking stops
3rd short button-press blinking starts
etc. etc.
?
This is done by using another boolean variable that you must define
take a name that is selfexplaining
“blinkingRun”
so each button-press sets blinkingRun to the inverted state
blinkingRun= !blinkingRun; // “!” is the not-operator
and then there is a condition
if (blinkingRun) {
//blinking-code here
}
I got the impression that you did NOT yet understand how it works
so write a first attempt how you thinkit might work
best regards Stefan