In the interests of helping anyone who might be wondering how to fade/flash LEDs without using delay, I've done a bit more work on this.
The "LED flasher" class is now a library, you can get it here:
http://gammon.com.au/Arduino/LED_flasher.zip
Install that in the usual way (unzip into your libraries folder).
I made a similar class to fade up and down LEDs connected to the PWM pins, here:
http://gammon.com.au/Arduino/LED_fader.zip
Install that in the usual way.
This code demonstrates flashing some LEDs:
// Example of flashing multiple LEDs at different rates without delays
// Author: Nick Gammon
// Date: 23 December 2012
#include <LedFlasher.h>
// set up some LEDs
LedFlasher floodLight (8, 200, 300);
LedFlasher shuttleBayDoors (9, 300, 600);
LedFlasher impuleEngine (10, 900, 100);
LedFlasher strobe (11, 500, 1000);
LedFlasher navigation (12, 1000, 2000);
LedFlasher torpedoes (13, 250, 500);
void setup()
{
floodLight.begin ();
shuttleBayDoors.begin ();
impuleEngine.begin ();
strobe.begin ();
navigation.begin ();
torpedoes.begin ();
} // end of setup
void loop()
{
// update lights
floodLight.update ();
shuttleBayDoors.update ();
impuleEngine.update ();
strobe.update ();
navigation.update ();
torpedoes.update ();
// do other useful stuff here ...
} // end of loop
This code illustrates fading some LEDs:
// Example of fading multiple LEDs at different rates without delays
// Author: Nick Gammon
// Date: 27 December 2012
#include <LedFader.h>
// set up some LEDs
// pin min max millis
LedFader strobe (3, 10, 200, 1000);
LedFader navigation (5, 10, 200, 500);
LedFader torpedoes (6, 10, 200, 250);
void setup()
{
strobe.begin ();
navigation.begin ();
torpedoes.begin ();
} // end of setup
void loop()
{
// update lights
strobe.update ();
navigation.update ();
torpedoes.update ();
// do other useful stuff here ...
} // end of loop
State machine
This code illustrates using a state machine to turn LEDs on in sequence.
// The Enterprise
// Author: Nick Gammon
// Date: 27 December 2012
#include <LedFader.h>
#include <LedFlasher.h>
// pin assignments
const byte PrimaryLightsPin = 13;
const byte SecondaryLightsPin = 12;
const byte DeflectorPin = 11; // PWM
const byte NacellesPin = 10; // PWM
const byte ImpulsePin = 9; // PWM
const byte ShuttleBayLightPin = 8;
const byte ShuttleBayLandingPin = 7;
const byte RCSPin = 6; // PWM
const byte FloodlightsPin = 5; // PWM
const byte NavigationPin = 4;
const byte StrobesPin = 3; // PWM
const byte TorpedoPin = 2;
// Faders
// pin min max millis on? stop?
LedFader impulseFader (ImpulsePin, 0, 40, 3000, false, true);
LedFader RCSFader (RCSPin, 0, 40, 3000, false, true);
// Flashers
// pin off-time on-time on?
LedFlasher strobe (StrobesPin, 100, 100, false);
// states for the state machine
typedef enum
{
initialState,
wantPrimaryLights,
wantSecondaryLights,
wantDeflector,
wantNacelles,
wantImpulse,
wantShuttleBayLight,
wantShuttleBayLanding,
wantRCS,
wantFloodlights,
wantNavigation,
wantStrobes,
wantTorpedo,
// more states here
} states;
// state machine variables
states state = initialState;
unsigned long lastStateChange = 0;
unsigned long timeInThisState = 1000;
void setup ()
{
pinMode (PrimaryLightsPin, OUTPUT);
pinMode (SecondaryLightsPin, OUTPUT);
pinMode (DeflectorPin, OUTPUT);
pinMode (NacellesPin, OUTPUT);
pinMode (ShuttleBayLightPin, OUTPUT);
pinMode (ShuttleBayLandingPin, OUTPUT);
pinMode (FloodlightsPin, OUTPUT);
pinMode (NavigationPin, OUTPUT);
pinMode (StrobesPin, OUTPUT);
pinMode (TorpedoPin, OUTPUT);
// set up faders, flashers
impulseFader.begin ();
RCSFader.begin ();
strobe.begin ();
} // end of setup
void doStateChange ()
{
lastStateChange = millis (); // when we last changed states
timeInThisState = 1000; // default one second between states
switch (state)
{
case initialState:
state = wantPrimaryLights;
break;
case wantPrimaryLights:
digitalWrite (PrimaryLightsPin, HIGH);
state = wantSecondaryLights;
break;
case wantSecondaryLights:
digitalWrite (SecondaryLightsPin, HIGH);
state = wantDeflector;
break;
case wantDeflector:
digitalWrite (DeflectorPin, HIGH);
state = wantNacelles;
break;
case wantNacelles:
digitalWrite (NacellesPin, HIGH);
state = wantImpulse;
break;
case wantImpulse:
impulseFader.on ();
state = wantShuttleBayLight;
break;
case wantShuttleBayLight:
digitalWrite (ShuttleBayLightPin, HIGH);
state = wantShuttleBayLanding;
break;
case wantShuttleBayLanding:
digitalWrite (ShuttleBayLandingPin, HIGH);
state = wantRCS;
break;
case wantRCS:
RCSFader.on ();
state = wantFloodlights;
break;
case wantFloodlights:
digitalWrite (FloodlightsPin, HIGH);
state = wantNavigation;
break;
case wantNavigation:
digitalWrite (NavigationPin, HIGH);
state = wantStrobes;
break;
case wantStrobes:
strobe.on ();
state = wantTorpedo;
break;
case wantTorpedo:
digitalWrite (TorpedoPin, HIGH);
timeInThisState = 5000; // no rush
// what next?
break;
} // end of switch on state
} // end of doStateChange
void loop ()
{
if (millis () - lastStateChange >= timeInThisState)
doStateChange ();
// update faders, flashers
impulseFader.update ();
RCSFader.update ();
strobe.update ();
// other stuff here like testing switches
} // end of loop
Example output:
The first 4 LEDs turn on one second apart. The 5th one fades on over 3 seconds. The 8th one likewise (it's a bit hard to see, the LEDs are so bright). The second-last one flashes.
All this is done without using delay at all. And millis is only used in two places in the whole sketch (plus a couple of times in each library).
loop is very short. It doesn't block. You could test switches and have them respond immediately.
The state machine, implemented in doStateChange changes state every second (however you can alter the time between state changes). At each state change you turn on, or off, whatever you want to. Then you tell it what the next state is.