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.
[arduino firstline=”2″]
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.
[arduino firstline=”3″]
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.
The biggest mistake I see people make with millis() code is defining this as an int. If you do that, you’ll have roll-over issues.
setup()
[arduino firstline=”6″] 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()
[arduino firstline=”10″] 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.” [shareable text=”Write millis()-based code with the mindset: “This will run thousands of times a second.””]Write millis()-based code with the mindset: “This will run thousands of times a second.”[/shareable] 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. [arduino firstline=”11″] 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.) [arduino firstline=”12″] 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. [arduino firstline=”13″] 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. [arduino firstline=”14″] 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. [arduino firstline=”18″] 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.What other common Arduino / Microcontroller examples do you need explained?
33 Comments
Thank you for the great explanation..
What kinda always annoyed me as the noob i am, is that the Millis method works in reverse as presented… It starts with a LED Off state, then it counts up Millis to reach the set interval value and the LED switches On…
Searched quite a while and even tho i wasn’t the only one complaining about it i still couldn’t find a straight foreward answer… Anyway I figured out myself to fix this issue, it actually is very simple… I changed the “unsigned long previousMillis = 0;” into a equal number as in the interval but then as a minus.
That would be
unsigned long previousMillis = -1000;
unsigned long interval = 1000;
Then it starts with a LED on and so on…
Cheers…
The most easy way to do this is to assign the opposite value in the variable definition
the given code has in line 2
int ledState = LOW;
and to change this to
int ledState = HIGH;
and you are done
best regards Stefan
Thank you for the fast reply…
I think i failed to mention i was playing with an ESP8662 NodeMCU board and i already tried to change line 2 but it doesn’t work. It simply stays as is, whatever HIGH or LOW is changed..
Till now the only way to get around it, is as what I described previously.
Cheers..
Hi I got pointed to this tutorial through a link in the Arduino-Forum. Very well explained. I don’t have an overview about your tutorials yet. Ideas about other beginners (or a bit advanced beyond beginner) might be
– when and how to use interrupt service-routines or when to use alternatives
. use selfexplaining names everywhere
– PString and/or SafeString als alternatives to “String”
– ESP826/ESP32-stuff (especially ESP-NOW)
best regards Stefan
Hola.
Me podría ayudar a hacer un contador con un pulsador de por ejemplo 10 pulsos y en este pulso se me active una salida durante un tiempo predeterminado. Luego de ese tiempo desactive esa salida, ponga a cero el contador y siga contando pulsos sin que afecte a la ejecución del código independientemente de la velocidad de los pulsos
Why not define the ledstate as byte = 0 and remove the if / else loop and replace it with ledstate = (1 – ledstate).. it saves some ram and program space and works just the same.
Hi,
Could you tell me why this program does’t show anything?
[arduino firstline=””]
#include <LiquidCrystal>
lcd(7, 8, 9, 10, 11, 12);
int buzzer = 5;
int x = 1;
unsigned long past = 0;
unsigned long s11 = 150;
unsigned long s2 = 200;
unsigned long s22 = 250;
unsigned long s3 = 300;
unsigned long s4 = 400;
unsigned long s5 = 500;
unsigned long s7 = 700;
void setup() {
lcd.begin(16, 2);
pinMode(buzzer, OUTPUT);
}
void loop() {
unsigned long c = millis();
if (c == 1000)
{
lcd.print("Happy birthday");
lcd.setCursor(0, 1);
lcd.print(" to you!");
}
if (c == 3000);
lcd.clear();
if (c == 3500)
{
lcd.print("Happy birthday");
lcd.setCursor(0, 1);
lcd.print(" to you!");
}
if (c == 6500)
lcd.clear();
if (c == 7000)
{
lcd.print("Happy birthday");
lcd.setCursor(0, 1);
lcd.print("dear…");
}
if (c == 11000)
lcd.clear();
if (c == 11500)
{
lcd.print("Happy birthday");
lcd.setCursor(0, 1);
lcd.print(" to you!");
}
}
[/arduino]
Avoid those variables from the begining :))
The problem is that you are looking for an exact value of millis(). You will probably never get so lucky to be checking for a value of “1000” at the EXACT moment millis() is that value.
The right way is to use a ranged comparison like “less than” or “greater than.” However, if you just change the code to be:
if (millis() >= 1000)
then once millis() is more than 1000, it’ll always print that statement. That means you need to add some flags.In a case like this where you are trying to print a sequential message, you could just use a variable to sequence.
[arduino firstline=”1″]
int statement = 0;
if ((millis() >= 1000) && (statement == 0)) {
statement = statement + 1; // increment the statement variable
// print whatever
}
[/arduino]
Then on your next check you would do:
[arduino firstline=”10″]
if ((millis() >= 3000) && (statement == 1)) {
statement = statement + 1; // increment the statement variable
// print whatever
}
[/arduino]
and so on.
Hi There, great line by line, really helped me understand better.
Do you think a logical AND (&&) can be added to your 1st IF statement to check for time but also a button state ? I need to turn “blink” a remote relay via Xbee but check that the user pushed a button to activate it 1st. Basically the relay will blink a light attached to it, but the user needs to have switched on the light to have it blink, otherwise it should just be off.
Thanks
Yes.
Dan: Did you implement the button, and if it worked, could you post your sketch?
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:
[arduino firstline=””]
//Global Variables
unsigned long buttonPushedMillis;
unsigned long delayInterval = 2500; // 2500ms or 2.5 second
bool messageReady = false; // flag for when button is let go
void setup() {
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
}
void loop() {
unsigned long currentMillis = millis(); // record what time it is
// this code will work with a pushbutton using the internal pull-up
// the variable "buttonPushedMillis" will get updated each iteration of loop, or
// while the button is held down. when released, buttonPushedMillis has the "last"
// value of millis
if (digitalRead(2) == LOW) {
buttonPushedMillis = currentMillis;
messageReady = true;
}
// make sure this code isn’t checked until after button has been let go
if (messageReady) {
//this is typical millis code here:
if ((unsigned long)(currentMillis – buttonPushedMillis) >= delayInterval) {
// okay, enough time has passed since the button was let go.
Serial.println("Message");
// wait for next button press
messageReady = false;
}
}
}
[/arduino]
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:
[arduino collapse=”true”]
//2015 TV Stand and Controller Control
const int Relay1 = 7;
const int Relay2 = 6;
const int Relay3 = 5;
const int Relay4 = 4;
int Relay1a = 8;
int Relay2a = 9;
int Relay3a = 10;
int Relay4a = 11;
const int buttonPin0 = 0;
const int buttonPin1 = 1;
const int buttonPin2 = 2;
const int buttonPin3 = 3;
int buttonState0 = 0;
int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
// the setup routine runs once when you press reset:
void setup() {
pinMode(buttonPin0, INPUT);
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(Relay1, OUTPUT);
pinMode(Relay2, OUTPUT);
pinMode(Relay3, OUTPUT);
pinMode(Relay4, OUTPUT);
pinMode(Relay1a, OUTPUT);
pinMode(Relay2a, OUTPUT);
pinMode(Relay3a, OUTPUT);
pinMode(Relay4a, OUTPUT);
}
void loop () {
buttonState0 = digitalRead(buttonPin0);//Keyfob D
buttonState1 = digitalRead(buttonPin1);//Keyfob C
buttonState2 = digitalRead(buttonPin2);//Keyfob B
buttonState3 = digitalRead(buttonPin3);//Keyfob A
if (buttonState3 == HIGH) {
//Neopixel code runs here until the 22 seconds to lift the actuator are up and then they would stop
digitalWrite(Relay1,HIGH);//Actuator up segment
delay(22000);
digitalWrite(Relay1,LOW);
}
if (buttonState3 == LOW){
}
if (buttonState2 == HIGH) {
//Neopixel code would run here until the 23 seconds to close the actuator are up and then stop
digitalWrite(Relay2,HIGH);//Actuator down segment
delay(23000);
digitalWrite(Relay2,LOW);
}
if (buttonState2 == LOW);{
}
if (buttonState1 == HIGH) {
digitalWrite(Relay1a, HIGH);//XBox Controller Tray
delay(1000);
digitalWrite(Relay1a, LOW);
delay(10000);
digitalWrite(Relay2a, HIGH);
delay(1000);
digitalWrite(Relay2a,LOW);
}
if (buttonState0 == HIGH){
digitalWrite(Relay3a, HIGH);//Remote Control Tray
delay(1000);
digitalWrite(Relay3a, LOW);
delay(10000);
digitalWrite(Relay4a, HIGH);
delay(1000);
digitalWrite(Relay4a, LOW);
}
}[/arduino]
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