You are on page 1of 32

The Full Arduino Functions:

SIGNAL(TIMER0_OVF_vect)

// copy these to local variables so they can be stored in registers

// (volatile variables must be read from memory on every access)

unsigned long m = timer0_millis;

unsigned char f = timer0_fract;

7
8

m += MILLIS_INC;

f += FRACT_INC;

1
0

if (f >= FRACT_MAX) {
f -= FRACT_MAX;

1
1

m += 1;
}

1
2
1
3

timer0_fract = f;

1
4

timer0_overflow_count++;

timer0_millis = m;

1
5

1
6

unsigned long millis()

1
7
1
8
1
9
2
0
2
1
2
2

{
unsigned long m;
uint8_t oldSREG = SREG;

// disable interrupts while we read timer0_millis or we might get an


// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;

2
3
2
4
2
5
2
6
2
7
2
8

return m;
}

2
9
3
0
3
1
3
2
Arduino - multiple LEDs with different delays
This question is Not Answered.

muteprint Mar 3, 2013 5:56 PM


Hi all
I'm trying to write code to get 3 LEDs flashing independently, each with a
different ON and OFF period.
For example:
LED1: ON for 25 ms, OFF for 500 ms
LED2: ON for 50 ms, OFF for 800 ms
LED3: ON fo 100 ms, OFF for 300 ms

So far I have set up the hardware: 3 LEDs on digital pins 6, 7 and 8 using my
Arduino UNO board and a breadboard.

Code-wise I understand that I can't use the "delay" function because it causes
the whole system to delay i.e. causes 'blocking'. At the moment I'm using the
millis() function. My problem is that at the moment my code causes LED1 to turn
ON for 25 ms and off for 25 ms, LED2 turns ON for 50 ms and off for 50 ms etc.
So I need to somehow alter the OFF period independently.

In summary: I need a new approach or an alteration to my code to be able to


independently change the ON and OFF periods for each of my LEDs
independently.

Here is my code so far:


[code]

// Which pins are connected to which LED


const byte LED1 = 6;
const byte LED2 = 7;
const byte LED3 = 8;

// Assigning delays.
const unsigned long LED1_interval = 25;
const unsigned long LED2_interval = 50;
const unsigned long LED3_interval = 100;

// Declaring the variables holding the timer values for each LED.
unsigned long LED1_timer;
unsigned long LED2_timer;
unsigned long LED3_timer;

// Setting 3 digital pins as output pins and resetting timer


void setup ()
{
pinMode (LED1, OUTPUT);
pinMode (LED2, OUTPUT);
pinMode (LED3, OUTPUT);
LED1_timer = millis ();
LED2_timer = millis ();
LED3_timer = millis ();
} // end of setup

//LED1 loop that turns it ON if it is OFF and vice versa


void toggle_LED1 ()
{
if (digitalRead (LED1) == LOW)
digitalWrite (LED1, HIGH);
else
digitalWrite (LED1, LOW);

// remember when we toggled it


LED1_timer = millis ();
} // end of toggleLED_1

//LED2 loop
void toggle_LED2 ()
{
if (digitalRead (LED2) == LOW)

digitalWrite (LED2, HIGH);


else
digitalWrite (LED2, LOW);

// remember when we toggled it


LED2_timer = millis ();
} // end of toggle_LED2

//LED 3 loop
void toggle_LED3 ()
{
if (digitalRead (LED3) == LOW)
digitalWrite (LED3, HIGH);
else
digitalWrite (LED3, LOW);

// remember when we toggled it


LED3_timer = millis ();
} // end of toggle_LED3

void loop ()
{

// Handling the blink of LED1.


if ( (millis () - LED1_timer) >= LED1_interval)
toggle_LED1 ();

// Handling the blink of LED2.


if ( (millis () - LED2_timer) >= LED2_interval)
toggle_LED2 ();

// Handling the blink of LED3.


if ( (millis () - LED3_timer) >= LED3_interval)
toggle_LED3 ();

/* Other code that needs to execute goes here.


It will be called many thousand times per second because the above code
does not wait for the LED blink interval to finish. */

} // end of loop
[/code]

Any help would be greatly appreciated because I'm [b]very[/b] new to this!

Thanks!

7783 Views

Tags:

Reply

1. Re: Arduino - multiple LEDs with different delays

billabott Mar 3, 2013 11:29 PM (in response to muteprint)

Most Arduino boards have two external interrupts: numbers 0 (on digital pin 2) and 1 (on digita
Official Arduino.cc Example

int pin = 13;


volatile int state = LOW;

void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE); //0 is digtal pin 2
}

void loop()
{
digitalWrite(pin, state);
}

void blink()
{
state = !state;
}

Observing that all your time factors are multiples of 25 ms, I would suggest that
you use a digital pin on your UNO to initiate a self generated external interrupt.

Adding code: const byte iSignal =9;


Adding physical wire/resister+LED/cap. between pins 9 and 2.

Here is the guts of it: pin 9 is pulsed every 25 ms by your loop(), the
iHandler() bumps a counter, the main loop() has a case statement that allows the
required LED transistion actions to take place depending on the counter value
only when old_counter is not equal to counter.

0 <= counter <= 32 (because 800/25=32), reset counter to 0 after 32


interrupts have occurred. (I am not sure if you want to count to 32 or 31.)

To make the implementation easier(reliable) change


LED1: ON for 25 ms, OFF for 500 ms

LED2: ON for 50 ms, OFF for 800 ms


to
LED1: ON for 25 ms, OFF for 450 ms
LED2: ON for 50 ms, OFF for 750 ms

FYI: http://arduino.cc/en/Reference/AttachInterrupt

Then again, you could just call the iHandler directly without the external
interrupt - but what fun would that be?

Like Show 0 Likes(0)

Reply

2. Re: Arduino - multiple LEDs with different delays

muteprint Mar 3, 2013 11:00 PM (in response to billabott)


Thank you very much for replying so quickly billabot. Unfortunately there will be
times when I need to LED to flash 3 times a second i.e. with an interval of
333ms, so not everything will be divisble by 25. Is your method adaptable to any
value?

I've been working on this tonight and made a few alterations to my code. I think
I'm going in the right direction with the method I've chosen.
Defined seperate ON and OFF intervals for each LED
Adapted my loops to use both the OFF and ON intervals.

Unfortunately I've ended getting myself really confused and now my LEDs seem
to sometimes flash the OFF interval, sometimes with the ON and sometimes with
a combination of the both.

Any idea how I've gone so badly wrong?

I hope I'm slowly moving in the right direction. If not I might have to try a
different approach like using the interupt function. I am very new to the Arduino
and writing code of any sort, so that approach seems quite daunting to me.

Below is my altered code.

[code]

//DEFINING CONSTANTS & VARIABLES

// Which pins are connected to which LED


const byte LED1 = 6;
const byte LED2 = 7;
const byte LED3 = 8;

// Assigning ON and OFF interval constants.


const unsigned long LED1_ON_interval = 3000; //
const unsigned long LED1_OFF_interval = 6000;
const unsigned long LED2_ON_interval = 500; //
const unsigned long LED2_OFF_interval = 1000;
const unsigned long LED3_ON_interval = 100; //
const unsigned long LED3_OFF_interval = 3000;

// Declaring the variables holding the timer value, i.e. time of last state change.
unsigned long LED1_statechange_Timei;

unsigned long LED2_statechange_Timei;


unsigned long LED3_statechange_Timei;
unsigned long LED1_statechange_Timeii;
unsigned long LED2_statechange_Timeii;
unsigned long LED3_statechange_Timeii;

//SETUP

// Setting 3 digital pins as LED output pins and starting millisecond timer
void setup ()
{
pinMode (LED1, OUTPUT);
pinMode (LED2, OUTPUT);
pinMode (LED3, OUTPUT);
LED1_statechange_Timei = millis ();
LED2_statechange_Timei= millis ();
LED3_statechange_Timei = millis ();
} // end of setup

//LOOPS 1

// LED1 loop that turns LED ON if it is OFF


void toggle_LED1i ()
{
if (digitalRead (LED1) == LOW)
digitalWrite (LED1, HIGH);
LED1_statechange_Timei = millis (); // Remember when LED1's state was
changed from ON to OFF
} // End of toggle_LED1i

// LED1 loop that turns LED OFF if it is ON


void toggle_LED1ii ()
{
if (digitalRead (LED1) == HIGH);
digitalWrite (LED1, LOW);
LED1_statechange_Timei = millis (); // Remember when LED1's state was
changed from OFF to ON
} // End of toggle_LED1ii

// LED2 loop that turns LED ON if it is OFF


void toggle_LED2i ()
{
if (digitalRead (LED2) == LOW)
digitalWrite (LED2, HIGH);
LED2_statechange_Timeii = millis (); // Remember when LED2's state was
changed from ON to OFF
} // End of toggle_LED2i

// LED2 loop that turns LED OFF if it is ON


void toggle_LED2ii ()
{
if (digitalRead (LED2) == HIGH);
digitalWrite (LED2, LOW);
LED2_statechange_Timeii = millis (); // Remember when LED2's state was
changed from OFF to ON
} // End of toggle_LED2ii

// LED3 loop that turns LED ON if it is OFF


void toggle_LED3i ()
{
if (digitalRead (LED3) == LOW)
digitalWrite (LED3, HIGH);
LED3_statechange_Timei = millis (); // Remember when LED3's state was
changed from ON to OFF
} // End of toggle_LED2i

// LED3 loop that turns LED OFF if it is ON


void toggle_LED3ii ()
{
if (digitalRead (LED3) == HIGH);
digitalWrite (LED3, LOW);
LED3_statechange_Timeii = millis (); // Remember when LED3's state was
changed from OFF to ON
} // End of toggle_LED3ii

//LOOPS 2

void loop () // Start of loop


{

//LED 1
// If the time since the last change in state from OFF to ON is equal or greater
than the ON interval
//then run the loop toggle_LED1i
if ( (millis () - LED1_statechange_Timei) >= LED1_ON_interval)
toggle_LED1i ();
// If the time since the last change in state from ON to OFF is equal or greater
than the OFF interval
//then run the loop toggle_LED1ii
if ( (millis () - LED1_statechange_Timeii) >= LED1_OFF_interval)
toggle_LED1ii ();

//LED 2
// If the time since the last change in state from OFF to ON is equal or greater
than the ON interval
//then run the loop toggle_LED2i
if ( (millis () - LED2_statechange_Timei) >= LED2_ON_interval)
toggle_LED2i ();
// If the time since the last change in state from ON to OFF is equal or greater
than the OFF interval

//then run the loop toggle_LED2ii


if ( (millis () - LED2_statechange_Timeii) >= LED2_OFF_interval)
toggle_LED2ii ();

//LED 3
// If the time since the last change in state from OFF to ON is equal or greater
than the ON interval
//then run the loop toggle_LED3i
if ( (millis () - LED3_statechange_Timei) >= LED3_ON_interval)
toggle_LED3i ();
// If the time since the last change in state from ON to OFF is equal or greater
than the OFF interval
//then run the loop toggle_LED2ii
if ( (millis () - LED3_statechange_Timeii) >= LED3_OFF_interval)
toggle_LED3ii ();

} // End of loop
[/code]

Thanks!

Like Show 0 Likes(0)

Reply

3. Re: Arduino - multiple LEDs with different delays

billabott Mar 7, 2013 5:15 AM (in response to muteprint)


Sorry, no, I am out of ideas. I will, however, share with you that there are other
uC that have multiple timers on board that can be configured to generate
interrupts at any predetermined interval.

Q: Just out of curiosity, what exactly controls the periodicity of your LEDs?

Or in other words; "What is your application, eh?"

You might simplify your program by adopting a more conventional approach by


using

boolean LED1_state = false;


scopes are GLOBAL

// place these very near the top of script so their

boolean LED2_state = false;


boolean LED3_state = false;

If time to turn off LED1


Set LED1_on_timer to milles() +800;
turn it on again.

// turning off; so it is known when to

toggle_LED(&LED1, &LED1_state); // call function to toggle LED between 1


and 0
Set LED1_off_timer to milles() +2048;
correct value

// presumeably will be reset to a

// after turning LED1 on prior to the expiration of


this value
else if time to turn on LED1
Set LED1_off_timer to milles() +50;
turn it off again.

// turning on; so it is known when to

toggle_LED(&LED1, &LED1_state);; // call function to toggle LED between 0


and 1
Set LED1_on_timer to milles() +2048; // presumeably will be reset to a
correct value
// after turning LED1 off prior to the expiration of
this value

void toggle_LED(int *LEDxP, boolean *LEDxP_state)


function to toggle ANY LED since pointers are used

// will need ONLY this one

{
digitalWrite (*LEDxP, (*LEDxP_state = !(*LEDxP_state))); // see note below

} // End of toggle_LED

note: According to http://arduino.cc/en/Reference/BooleanVariables


digitalWrite does accept boolean arg of true/false in lieu of HIGH/LOW arg.

Message was edited by: William Bottger

Like Show 0 Likes(0)

Reply

4. Re: Arduino - multiple LEDs with different delays

coder27 Mar 4, 2013 4:47 PM (in response to billabott)


Even with using only one timer, you may be able to do something like this:

You have 6 events to schedule (turning each of 3 LED's On and Off).


For each event, you need to store 4 fields: which LED, On vs. Off,
the time-of-day the event should be taken next, and the amount of time
between events. For LED1, the time between events would be 525 ms.
You can store these 6 events in an array. (They don't have to be sorted
in any particular order.) It may help to think of this array as the "delay-queue"
of a task scheduler.

Then you can write a function that will scan this array and find the event with the
soonest next time-of-day. Set an interrupt timer for that time-of-day. While
waiting for the timer, any work can be going on. When the timer goes off,
turn the specified LED On or Off, and update the next time-of-day field by adding
the specified time between events for that LED. Loop back and scan the array
again to find the next soonest event.
o

Like Show 0 Likes(0)

Reply

5. Re: Arduino - multiple LEDs with different delays

billabott Mar 7, 2013 4:47 AM (in response to muteprint)


unsigned long Timer // "ALWAYS use unsigned long for timers, not int"
// (variable declaration outside setup and loop, of course)
// makes the Timer var GLOBAL in scope

That is good advice from http://playground.arduino.cc/Code/AvoidDelay

Please check out my modified code above for pointer ref. & deref. usage!

Code in previous post updated based on the following experiment which does
compile and run correctly!
boolean ON = HIGH;
boolean OFF = LOW;
boolean led1 = ON;

void setup()
{ //led1 = OFF;
pinMode(13, OUTPUT);

void loop()
{ test(&led1);
digitalWrite(13, led1);
delay(1500);
}

void test(boolean *varLED)


{ *varLED = !(*varLED);
}
This Arduino sketch was programmed by William A T Bottger.

Message was edited by: William A T Bottger

Like Show 0 Likes(0)

Reply

6. Re: Arduino - multiple LEDs with different delays

coder27 Mar 12, 2013 7:04 AM (in response to muteprint)


Hi muteprint,
I looked a little closer at your code, and see a few problems:

In toggle_LED1ii ()
you have:
LED1_statechange_Timei = millis (); // Remember when LED1's state was
changed from OFF to ON
but that should be Timeii (two i's).

Similarly, in toggle_LED2i ()
you have:
LED2_statechange_Timeii = millis (); // Remember when LED2's state was
changed from ON to OFF
but that should be Timei (one i).

Also, in setup(), I think you need to initialize the Timeii statechange variables, in
order to prevent referring
to random values in the loops.

Billabott is probably right that by using pointers you can condense the code, but I
haven't
looked at that closely, and I think you probably want to get it working first, and
then improve it later.

How to write Timings and Delays


in Arduino
by Matthew Ford 4th March 2015 2013 (original - 21st March 2013)
Forward Computing and Control Pty. Ltd. NSW Australia
All rights reserved.
How to write Timings and Delays in Arduino
Why your program might fail after 50 days.
This page has been re-written to use ElapsedMillis repeating timers
This page also shows how to use elapsedMillis for a one-off timers.
4th March 2015 update: Added Code Alternatives to using ElapsedMillis

Introduction
Using delay() causes your system to be stuck while waiting for the delay to
expire. However replacing delays requires some care. This page explains in a
step by step way how to replace delays with repeating timers in a reliable way.
Warning: Do not run the standard Arduino BLINK example code, or any
other code using pin 13 (LED) as an output, on the Fio V3 board when a
battery is connected. You may damage the board.
See this page for more warnings about the FioV3 board
Timers Using elapsedMillis
A Repeating Timer using elapsedMillis
A Once Off Timer using elapsedMillis
Code Examples to be Avoided
Simple Blink Example using Delay
Second Attempt to Blink without Delay
Almost Final solution to Blink without Delay
Word of Warning Add a loop monitor
Final Solution for Reliable Timers (Superseded by above elapsedMillis examples,
8th Nov 2013)
Timers Using elapsedMillis
Lets start at the end with the two working examples that don't have problems.
These working examples are based on elapsedMillis by Paul Stoffregen, one for a
repeating timer and one for a once off timer.

Follow those two examples are working alternatives that don't use the
elapsedMillis library.
First install the elapsedMillis library. Downloaded the elapsedMillis.zip file.
Unzip this file to your Arduino/libraries directory (open the IDE File->preferences
window to see where your local Arduino directory is).
Some times the instructions for How to Install a Library - Automatic
installation work, but not always. Unzipping the file manually is safest.
A Repeating Timer using elapsedMillis
This is a simple example of a repeating timer
#include <elapsedMillis.h>
// see warning above about FioV3
int led = 13;
// Pin 13 has an LED connected on most Arduino boards.
// if using Arduino IDE 1.5 or above you can use pre-defined
// LED_BUILTIN instead of 'led'
//
elapsedMillis timer0;
#define interval 1000
// the interval in mS

// the setup routine runs once when you press reset:


void setup() {
// initialize the digital pin as an output.
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);
}

}
The code above loop() continues to run without being stuck waiting for the delay
to expire.
During each pass of the loop(), a timeout interval is compared to a free running
timer.
When the timer exceeds the value of the interval the desired action is taken (in
this example change the state of the LED) and the timer is reset.
The reason for using
timer0 -= interval; //reset the timer
is that it allows for the possibility that the timer just happened to be incremented
between testing it
if (timer0 > interval) {
and resetting it
timer0 -= interval; //reset the timer
or if there is some other delay the prevents the main loop from running every
milli-second. (See the Adding a Loop Montor below)
Using timer0 -= interval; also gives you the option of varying the timing interval.
Another point is to clear timer0 at the end of startup(), using
timer0 = 0;
This ensures the timer is accurate at the start of the loop(), even if startup()
takes some time to execute.
A Once Off Timer using elapsedMillis
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>
// see warning above about FioV3
int led = 13;
// Pin 13 has an LED connected on most Arduino boards.
// if using Arduino IDE 1.5 or above you can use pre-defined
// LED_BUILTIN instead of 'led'
//
elapsedMillis timer0;

#define interval 5000


// the interval in mS
boolean timer0Fired;

// the setup routine runs once when you press reset:

void setup() {
// initialize the digital pin as an output.
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
}
}
Also see http://playground.arduino.cc//Code/ElapsedMillis
Code Alternatives to using ElapsedMillis
Here are two code examples that do not used ElapsedMillis.
Repeating Timer
The following sketch shows a simple repeating timer. You can download the
sketch from RepeatingTimer.ino
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 moving it along to the next interval

//

toggle led

if (digitalRead(led)) {
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
} else {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
}
}
}
Single Shot Timer
This sketch shows a simple single shot timer. You can download the sketch
from SingleShotTimer.ino
int led = 13;
unsigned long timer; // the timer
boolean timedOut = false; // set to true when timer fired
unsigned long INTERVAL = 5000; // the timeout interval

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)) {
// timed out
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); // turn the LED off by making the voltage LOW
} else {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
}
}
}

Code Examples to be Avoided


Simple Blink Example using Delay
Many of the sample Arduino programs are seductively simple. Take the Blink
example
// Initial code attempt
int led = 13; // don't use on FioV3 when battery connected
// Pin 13 has an LED connected on most Arduino boards.
// if using Arduino IDE 1.5 or above you can use pre-defined
// LED_BUILTIN instead of 'led'
//
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:


void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
The problem with this example is that the CPU is stuck waiting in the delay
function.
delay(1000);

If you try and add more code to the loop() you will find it is very slow to execute.
So the first point is:Don't use delay( )
Second Attempt to Blink, without Delay
But if you don't use delay what are the alternatives. Well Arduino provides a
millis() method that returns the number of milli Seconds since the last uC reset.
Using this method we can code this second attempt at a delay.
// Second attempt
int led = 13; // don't use on FioV3 when battery connected
// Pin 13 has an LED connected on most Arduino boards.
// if using Arduino IDE 1.5 or above you can use pre-defined
// LED_BUILTIN instead of 'led'
//
unsigned long timeout;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
timeout = millis();
}

// the loop routine runs over and over again forever:


void loop() {
if (millis() > timeout) { // WARNING this has problems as discussed below
// time to toggle the Led
timeout += 1000;
if (digitalRead(led)) {
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
} else {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
}
}
}

Now there are no delays in the main loop() and your other code will be run
promptly.
However all it not good with this solution.
The second attempt above has a failing. About 50 days after the Arduino board is
reset, millis() goes back to counting from 0. This is because the 32bits used to
store the value overflow and start counting from zero again. See the Arduino
reference description for millis(). The timeout variable is also 32bits and so
eventually timeout + 1000 will overflow and become a small number. What this
means is that for about 1 second every 50 days
if (millis() > timeout) {
will be true every loop and the led will flash at a very high rate for that second
until millis() over flows back to a small number as well.
For a blinking led this may not be a problem but in a real application it could
cause damage every 50 days when the timers stop working as expected.
If you are just interested in a repeating timer then
see http://arduino.cc/en/Tutorial/BlinkWithoutDelay for a simple reliable repeating
timer which does not count down. The code below works because even
if currentMillis overflows back to a small number, currentMillis
previousMillis still gives the correct result.
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis> interval) {
// save the last time
previousMillis = currentMillis;
// do stuff here each interval (interval -- an unsigned long)
...
}

Almost Final solution to Blink without Delay


The almost final solution involves a very small but significant change to the
code.
Replace
if (millis() > timeout) { // WARNING this has problems as discussed below
with
if (millis() == timeout) { // this works if loop() takes <1mS to execute
So the code becomes
// Final solution code
int led = 13; // don't use on FioV3 when battery connected
// Pin 13 has an LED connected on most Arduino boards.

// if using Arduino IDE 1.5 or above you can use pre-defined


// LED_BUILTIN instead of 'led'
//
unsigned long timeout;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
timeout = millis();
}
// the loop routine runs over and over again forever:
void loop() {
if (millis() == timeout) { // NOTE: the == only toggle led when millis() equals
timeout
// time to toggle the Led
timeout += 1000;
if (digitalRead(led)) {
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
} else {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
}
}
}
This code works because when timeout + 1000 overflows, millis() will not equal it
until millis() also overflows.
Word of Warning Add a loop monitor
The almost final solution presented above does have one dependency. That is
the main loop() must execute at lease once every 1mS, otherwise you may miss
the exact milliSecond when millis() == timeout.
This means you must not have any other delay()'s in you program what would
prevent the loop() from running at least once every 1mS. Unfortunately many of
the standard Arduino libraries use delay() or introduce pauses, such as
AnalogRead and SoftwareSerial. Usually the delay these introduce are small but
they can add up so I suggest you add a monitor at the top of your loop() to
check how quickly it runs.

The loop monitor is very similar to the blink example. A small piece of code at
the top of the loop() method just toggles the Led each time loop() is executed.
You can then use a digital multimeter with at Hz scale to measure the frequency
of the output on the LED pin (pin 13 in this case)
The code is:// Loop Monitor this checks that the loop() is executed at least once every 1mS
// (c)2013 Forward Computing and Control Pty. Ltd.
// www.forward.com.au
//
// This example code is in the public domain.
int led = 13; // don't use on FioV3 when battery connected
// Pin 13 has an LED connected on most Arduino boards.
// if using Arduino IDE 1.5 or above you can use pre-defined
// LED_BUILTIN instead of 'led'
//

// the setup routine runs once when you press reset:


void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
// add your other setup code here
}

// the loop routine runs over and over again forever:


void loop() {
// toggle the led output each loop The led frequency must measure >500Hz (i.e.
<1mS off and <1mS on)
if (digitalRead(led)) {
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
} else {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
}

// add the rest of your loop code here

You can download the monitor code here. When I run this code on my Uno board
the multiMeter on the Hz range connected between pin 13 and GND reads
57.6Khz. i.e. about 100 times >500hz. As you add your code to loop() the Hz
reading will reduce. Just check it stays well above 500Hz in all situations.
Final Solution for Reliable Count Down Timers
(Note: this code has been superseded by the elapsedMillis code at the
top of this page)
This last example shows how to code count down timers, both repeating and one
off, that will reliably execute even if loop() takes more the 1mS to execute.
The idea is to capture the number of millis() that have gone by since the last
loop() and use that number to decrement your timers. This code can
be downloaded from here. As noted above
seehttp://arduino.cc/en/Tutorial/BlinkWithoutDelay for an alternative simple
reliable repeating timer which does not count down.
/*
Robust Timer
(c)Forward Computing and Control Pty. Ltd.
Works even if sometimes the loop() takes longer the 1mS to execute.
This example code is in the public domain.
*/

static unsigned long lastMillis = 0; // holds the last read millis()


static int timer_1 = 0; // a repeating timer max time 32768 mS = 32sec use a
long if you need a longer timer
// NOTE timer MUST be a signed number int or long as the code relies on timer_1
being able to be negative
// NOTE timer_1 is a signed int
#define TIMER_INTERVAL_1 2000
// 2S interval

static int timer_2 = 0; // a one off timer max time 32768 mS = 32sec use a long
if you need a longer timer
// NOTE timer MUST be a signed number int or long as the code relies on timer_2
being able to be negative
// NOTE timer_2 is a signed int

#define TIMER_INTERVAL_2 5000


// 5 sec interval

// the setup routine runs once when you press reset:


void setup() {
// initialize the digital pin as an output.
timer_1 = TIMER_INTERVAL_1; // timeout in first loop
timer_2 = TIMER_INTERVAL_2; // set up one off timer times out in 10 sec
Serial.begin(9600);
while (Serial.available()) {
}
Serial.println("Timer Begin");
lastMillis = millis(); // do this last in setup
}

// the loop routine runs over and over again forever:


void loop() {
// set millisTick at the top of each loop if and only if millis() has changed
unsigned long deltaMillis = 0; // clear last result
unsigned long thisMillis = millis();
// do this just once to prevent getting different answers from multiple calls to
millis()
if (thisMillis != lastMillis) {
// we have ticked over
// calculate how many millis have gone past
deltaMillis = thisMillis-lastMillis; // note this works even if millis() has rolled over
back to 0
lastMillis = thisMillis;
}

// handle one off timer


// repeat this code for each timer you need to handle
if (timer_2 > 0) { // still counting down

timer_2 -= deltaMillis;
if (timer_2 <= 0) {
// timer timed out
// do timeout stuff here
// in this set the led HIGH
Serial.println("Timer 2 timed out");
}
}

// handle repeating timer


// repeat this code for each timer you need to handle
timer_1 -= deltaMillis;
if (timer_1 <= 0) {
// reset timer since this is a repeating timer
timer_1 += TIMER_INTERVAL_1; // note this prevents the delay accumulating if
we miss a mS or two
// if we want exactly 1000 delay to next time even if this one was late then just
use timeOut = 1000;

// do time out stuff here


Serial.println("Repeating Timer 1 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.
So for both types of timers, you can also add a check for deltaMillis > 0 and skip
all the timer code except for those times when the mS ticks over. i.e.
if (deltaMillis> 0) {
// handle one off timer
// repeat this code for each timer you need to handle
.. etc

// handle repeating timer


// repeat this code for each timer you need to handle
.. etc
}
For use of the Arduino name see http://arduino.cc/en/Main/FAQ

pfodDevice and pfodApp are trade marks of Forward Computing and Control
Pty. Ltd.

Contact Forward Computing an

You might also like