Here is an extended example of a state machine controlling LEDs
const byte ledPins[] = {5, 6, 9, 10};
byte LEDCOUNT = sizeof(ledPins) / sizeof(ledPins[0]);
byte ledIndex = 0;
const unsigned long FIVESECS = 5000;
unsigned long currentTime;
unsigned long startTime;
enum states
{
ALL_FADE_UP_TOGETHER,
ALL_ON_FOR_5_SECS,
ALL_FADE_DOWN_TOGETHER,
ALL_FADE_UP_DOWN_IN_SEQUENCE,
DO_NOTHING
};
byte currentState = ALL_FADE_UP_TOGETHER;
void setup()
{
Serial.begin(115200);
for (int pin = 0; pin < LEDCOUNT; pin ++)
{
pinMode(ledPins[pin], OUTPUT);
digitalWrite(ledPins[pin], HIGH);
}
Serial.println("Fading all up together");
}
void loop()
{
currentTime = millis();
switch (currentState)
{
case ALL_FADE_UP_TOGETHER:
{
static int pwmLevel = 255;
static int pwmIncrement = -1;
unsigned long period = 20;
if (currentTime - startTime >= period)
{
setPwmLevelForAllLeds(pwmLevel);
startTime = millis();
pwmLevel += pwmIncrement;
if (pwmLevel <= 0)
{
setPwmLevelForAllLeds(255);
currentState = ALL_ON_FOR_5_SECS;
startTime = currentTime;
setPwmLevelForAllLeds(0); //all on
Serial.println("Waiting 5 seconds");
}
}
}
break;
//*****
case ALL_ON_FOR_5_SECS:
if (currentTime - startTime >= FIVESECS)
{
currentState = ALL_FADE_DOWN_TOGETHER;
Serial.println("Fading all down together");
startTime = currentTime;
setPwmLevelForAllLeds(0); //all on
}
break;
//*****
case ALL_FADE_DOWN_TOGETHER:
// case ALL_FADE_UP_TOGETHER:
{
static int pwmLevel = 0;
static int pwmIncrement = 1;
unsigned long period = 20;
if (currentTime - startTime >= period)
{
setPwmLevelForAllLeds(pwmLevel);
startTime = millis();
pwmLevel += pwmIncrement;
if (pwmLevel >= 255)
{
setPwmLevelForAllLeds(255); //all off
currentState = ALL_FADE_UP_DOWN_IN_SEQUENCE;
startTime = currentTime;
setPwmLevelForAllLeds(255); //all off
Serial.println("Fading all up down in sequence");
}
}
}
break;
//*****
case ALL_FADE_UP_DOWN_IN_SEQUENCE:
{
static unsigned long startTime;
static int pwmLevel = 255;
static int pwmIncrement = -1;
unsigned long period = 5;
if (currentTime - startTime >= period)
{
analogWrite(ledPins[ledIndex], pwmLevel);
startTime = millis();
pwmLevel += pwmIncrement;
if (pwmLevel <= 0)
{
pwmIncrement *= -1;
pwmLevel += pwmIncrement;
}
if (pwmLevel >= 255)
{
pwmLevel = 255;
analogWrite(ledPins[ledIndex], pwmLevel); //make sure that the LED is off
pwmIncrement *= -1;
ledIndex++;
if (ledIndex >= LEDCOUNT)
{
currentState = DO_NOTHING;
Serial.println("Doing nothing forever");
}
}
break;
}
}
//*****
case DO_NOTHING:
{
break;
}
}
}
void setPwmLevelForAllLeds(byte pwmLevel)
{
for (int ledIndex = 0; ledIndex < LEDCOUNT; ledIndex++)
{
analogWrite(ledPins[ledIndex], pwmLevel);
}
}
NOTES :
it runs on a Uno and uses 4 LEDs
The LEDs on my test system are active LOW, ie they are at max brightness when the output driving them is at zero (LOW). You will need to adjust either your hardware or the program
There are no delay()s in the program and all timing is done using millis()
It includes an example of waiting for a period apparently doing nothing, but loop() is still running freely so the program could do other things such as reading an input to change or cancel the sequence
The states are held in an enum and have explicit names which I find helpful
The program gives you a status report of what it is doing on the Serial monitor
When it enters the DO_NOTHING state it is actually very busy doing nothing !
It has not been extensively tested or optimised but seems to work
The variables could undoubtedly be tidied up to use more local variables. As it is there is a mish-mash of local and global variables.