Millis For Arduino
Millis For Arduino
The millis function makes use of an internal counter within the ATmega microcontroller at the heart of your
Arduino. This counter increments every clock cycle – which happens (in standard Arduino andcompatibles) at a
clock speed of 16 Mhz. This speed is controlled by the crystal on the Arduino board (the silver thing with T16.000
stamped on it):
Crystal accuracy can vary depending on external temperature, and the tolerance of the crystal itself. This in turn
will affect the accuracy of your millis result. Anecdotal experience has reported the drift in timing accuracy can be
around three or four seconds per twenty-four hour period. If you are using a board or your own version that is
using a ceramic resonator instead of a crystal, note that they are not as accurate and will introduce the
possibility of higher drift levels. If you need a much higher level of timing accuracy, consider specific timer ICs
such as the Maxim DS3232.
Using function delay(n) the microcontroller cannot perform any other functions in the main loop().
If you try and add more code to the loop() you will find it is very slow to execute.
So Don't use delay( )
/* Flashing LED
* ------------
* Turns on and off a light emitting diode(LED) connected to a digital
* pin, in intervals of 2 seconds using delay() function. *
*/
We will use the millis() function to control our LED as before. Since the delay() function is not used the
processor is not tied up waiting and can carry out any additional processing in the main loop that is needed
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
currentTime = millis();
loopTime = currentTime;
}
void loop()
{
currentTime = millis();
if(currentTime >= (loopTime + 1000)){
digitalWrite(ledPin, !digitalRead(ledPin)); // toggles the LED on/off
loopTime = currentTime; // Updates loopTime
}
// Other processing can be done here
}
#include <elapsedMillis.h>
int led = 13;
elapsedMillis timer0;
#define interval 1000 // the interval in mS
void setup() {
pinMode(led, OUTPUT);
timer0 = 0; // clear the timer at the end of startup
}
void loop() {
if (timer0 > interval) {
timer0 -= interval; //reset the timer
int ledPin = digitalRead(led);
// read the current state and write the opposite
digitalWrite(led, !ledPin);
}
}
If you only want the timer to fire once and never again you need to add a guard boolean to
prevent code being executed again after the timer has fired
#include <elapsedMillis.h>
int led = 13;
elapsedMillis timer0;
void setup() {
pinMode(led, OUTPUT);
digitalWrite(led, HIGH);
timer0Fired = false;
timer0 = 0; // clear the timer at the end of startup
}
void loop() {
if ((!timer0Fired) && (timer0 > interval)) {
timer0Fired = true; // don't execute this again
digitalWrite(led, LOW); // turn led off after 5 sec
}
}
Repeating Timer
int led = 13;
unsigned long timer; // the timer
unsigned long INTERVAL = 1000; // the repeat interval
void setup() {
pinMode(led, OUTPUT); // initialize LED output
timer = millis(); // start timer
}
void loop() {
if ((millis()-timer) > INTERVAL) {// timed out
timer += INTERVAL;// reset timer by incrementing to the
next interval
// toggle led
if (digitalRead(led)) {
digitalWrite(led, LOW);
} else {
digitalWrite(led, HIGH);
}
}
}
void setup() {
pinMode(led, OUTPUT); // initialize LED output
timedOut = false; // allow timer to fire
timer = millis(); // start timer
}
void loop() {
// this will toggle the led ONCE only after 5sec (timeOut)
if ((!timedOut) && ((millis() - timer) > INTERVAL)) {
timedOut = true; // don't do this again
// you can reset the single shot timer by setting
// timedOut = false;
// timer = millis();
// toggle led
if (digitalRead(led)) {
digitalWrite(led, LOW);
} else {
digitalWrite(led, HIGH);
}
}
}
Example code: count down timers- both repeating and one off
that will reliably execute even if loop() takes more the 1mS to execute.
/*
Robust Timer
Works even if sometimes the loop() takes longer the 1mS to
execute.
*/
void setup() {
timer_1 = TIMER_INTERVAL_1;
timer_2 = TIMER_INTERVAL_2;
Serial.begin(9600);
while (Serial.available()) {
}
Serial.println("Timer Begin");
lastMillis = millis();
}
void loop() {
unsigned long deltaMillis = 0; // clear last result
unsigned long thisMillis = millis();
if (thisMillis != lastMillis) {
deltaMillis = thisMillis-lastMillis;
lastMillis = thisMillis;
}
if (deltaMillis> 0) {
// handle one off timer
if (timer_2 > 0) { // still counting down
timer_2 -= deltaMillis;
if (timer_2 <= 0) {
// timer2 timed out
Serial.println("oneoff Timer2 timed out");
}
}
Note that for the one off timer, timer_2, we first check if the timer is >0 before
subtracting the deltaMillis so that we only process the timeout once.
For the repeating timer, timer_1, we just subtract the deltaMillis every time, but
most of the time deltaMillis will be 0.
String readString;
//#include
//LiquidCrystal_I2C lcd(0x20,16,2);
void setup() {
pinMode(Led1, OUTPUT);
pinMode(Led2, OUTPUT);
pinMode(Led3, OUTPUT);
pinMode(M1, OUTPUT);
Serial.begin(9600);
void loop()
{
char *help_menu = "\’e\’ go forward\n\’d\’ stop\n\’s\’ left\n\’f\’
right\n\’c\’ go backward\n";
if (Serial.available() > 0)
{
command = Serial.read();
switch (command)
{
case 'e': //go forward
forward();
break;
case 'c':
reverse();
break;
case 'd':
Stop();
break;
}
command = '\0'; //reset command
}
if ((unsigned long)(millis() - previousMillis) >= interval) {
Stop();
}
}
void forward() {
Serial.println("Go!!\r\n");
digitalWrite(M1, LOW);
digitalWrite(Led1, HIGH);
digitalWrite(Led2, LOW);
digitalWrite(Led3, LOW);
// lcd.setCursor(0, 0);
// lcd.print("forward");
analogWrite(E1, 255); //PWM speed control
previousMillis = millis();
}
void reverse() {
Serial.println("Back!!\r\n");
digitalWrite(M1, HIGH);
digitalWrite(Led1, LOW);
digitalWrite(Led2, HIGH);
digitalWrite(Led3, LOW);
// lcd.setCursor(0, 0);
// lcd.print("backward");
analogWrite(E1, 255); //PWM speed control
previousMillis = millis();
}
void Stop() {
analogWrite(E1, 0); //PWM speed control
digitalWrite(Led1, LOW);
digitalWrite(Led2, LOW);
digitalWrite(Led3, HIGH);
Serial.println("Stop!\r\n"); // usually you want to stop immediately
// lcd.setCursor(0, 0);
// lcd.print("stop ");
}
long waitUntil13 = 0;
long waitUntil12 = sequenceDelay;
long waitUntil11 = sequenceDelay + sequenceDelay2;
void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
}
void loop() {
if (millis() >= waitUntil13) {
LED13state = !(LED13state);
waitUntil13 += flashDelay;
}
================
This code can not turn on both LEDs no matter how you push the
buttons.This is whydelay() is fatal and very wrong if you need to
do more than one single thing at a time.
if digitalReadA==Down
then TimerA= millis() , digitalWriteA ON
if millis()-TimerA >= 15000UL
then digitalWriteA Off
if digitalReadB==Down
then TimerB= millis() , digitalWriteB ON
if millis()-TimerB >= 15000UL
then digitalWriteB Off
Result: This will not do a digitalRead or reset the timer, once the
LED has turned on, ie we are starting the timer on button push
(like attempt 1 earlier). Likewise it only tests the timer if the LED
is on, and only turns it off once (which make very little difference,
so I would normally omit the LEDon test in the 2nd part)
And this will work fine with two or more buttons and LEDs, as the
timers are independent and the code will not block.
Example 4
One button, one LED - each with their own timer; A more
usefull(?) example of doing two timing things "at once"
A challenge :)
A fter learning how to flash a single LED on your Arduino, you are
probably looking for a way to make cool patterns, but feel limited by the
use of delay(). If you ask in the forums you get told to look at the “Blink
Without Delay” example. This example introduces the idea of replacing
delay() with a state machine. If you’re confused how to use it, this tutorial
is setup to take you from blinking two LEDs with delay, to using an
alternate method, right down to how you can use millis().
Instead of “waiting a certain amount of time” like you do with delay(), you can use millis()
to ask “how much time has passed”?
Let’s start by looking at a couple of ways you can use delay() to flash LEDs.
Example #1: Basic Delay
This is the basic delay example you are probably already familiar with. It is included in the
Arduino IDE’s Examples as “Blink.”
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(13, LOW); // set the LED off
delay(1000); // wait for a second
}
Note that cpu is blocked for entire delay period doing nothing.
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH); // set the LED on
for (int x=0; x < 1000; x++) { // Wait for 1 second
delay(1);
}
digitalWrite(13, LOW); // set the LED on
for (int x=0; x < 1000; x++) { // Wait for 1 second
delay(1);
}
}
This new sketch will accomplish the same sequence as Example #1. The difference is that the
Arduino is only “delayed” for 1 millisecond at a time. A clever trick would be to call other
functions inside of that for() loop. However, your timing will be off because those
instructions will add additional delay.
void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH); // set the LED on
for (int x=0; x < 1000; x++) { // wait for a secoond
delay(1);
if (x==500) {
digitalWrite(12, HIGH);
}
}
digitalWrite(13, LOW); // set the LED off
for (int x=0; x < 1000; x++) { // wait for a secoond
delay(1);
if (x==500) {
digitalWrite(12, LOW);
}
}
}
Starting with the first for() loop, while Pin 13 is high, Pin 12 will turn on after 500 times
through the for() loop. It would appear that Pin 13 and Pin 12 were flashing in Sequence.
Pin 12 would turn on 1/2 second after Pin 13 turns on. 1/2 second later Pin 13 turns off,
followed by Pin 12 another 1/2 second.
If you wanted to add other LEDs or change the sequence, you have to start getting really
clever with all of the if-statements. Not to mention the comment from example #2. The
timing of these LEDs is going to be off, because the if() statement and digitalWrite() function
all take time, adding to the “delay()”.
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
void loop() {
unsigned long currentMillis = millis();
if ((currentMillis - previousMillis) >= interval) {
previousMillis = currentMillis;
digitalWrite(13, !digitalRead(13));
}
}
Millis() convert the “Blink” example into non-blocking code.
boolean LED13state = false; // the LED will turn ON in the first iteration of l
boolean LED12state = false; // need to seed the light to be OFF
long waitUntil13 = 0; //equivalent to prevMillis_led13
long waitUntil12 = sequenceDelay; //equivalent to prevMillis_led12
void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}
void loop() {
digitalWrite(13, LED13state); // each iteration of loop() will set the IO p
digitalWrite(12, LED12state);
// checking to see if enough time has elapsed
if (millis() >= waitUntil13) {
LED13state = !(LED13state);
waitUntil13 += flashDelay;
// this if-statement will not execute for another 1000 milliseconds
}
// keep in mind, waitUntil12 was already seeded with a value of 500
if (millis() >= waitUntil12) {
LED12state = !(LED12state);
waitUntil12 += flashDelay;
}
}
Other Examples
Check out this list of millis() examples: http://www.baldengineer.com/millis-cookbook.html
There are examples to create a Police Light Strobe Effect, Time your Code, Change the ON-
time and OFF-time for a LED, and others.
Conclusion
At first it seems that using the millis() function will make a sketch more complicated than
using delay(). In some ways, this is true. However, the trade off is that the sketch becomes
significantly more flexible. Animations become much simpler. Talking to LCDs while
reading buttons becomes no problem. Virtually, you can make your Arduino multitask.
cant you help me how to me after 20 sec forward and reverse motor will stop automaticly
=======