UKHeliBob:
I will probably not have the time but I would be interested to see the program written using an FSM library
...
Here is a slightly different program, which is NOT using a FSM library, but the code is using some of the programming logic which is used by FSM libraries sometimes, like a "function pointer" to each "state function", and the loop is calling the current state function over and over while the current state is active.
Functional differences to the UKHeliBob FSM example:
No button is used at all, all state switching is done by time only in this code.
fadeUp duration is 5.1 seconds (5100 milliseconds and ends with LEDON state.
fadeDown duration is the same and ends with LEDOFF state.
Duration of LEDON and LEDOFF is fixed to 10 seconds (10000 milliseconds and they will automatically switch to a fade state after timeout.
As I told: No button at all is used. But could be implemented easily.
Besides of that: LED fading of my code does NOT require to use a PWM pin for the LED.
In fact, I'm using the board LED on pin13 in my code, and I have included a function for some kind of software PWM, so that it does not matter whether the LED pin is PWM enabled or not: My sketch will fade the LED up and down, switch OFF or ON, as required.
Perhaps a "blinking state" could be useful, too.
If the TO is still interested in learning how to do FSM with Arduino, I could possibly work out another example with using a button and possibly more different states. Perhaps the TO likes to throw in some words into this thread, too.
Here is my example code, using FSM and function pointers:
const byte ledPin=13;
byte currentState;
unsigned long stateActiveSince;
void softPWM(byte fadeVal)
{
digitalWrite(ledPin,HIGH);
delayMicroseconds(fadeVal*10);
digitalWrite(ledPin,LOW);
delayMicroseconds((255-fadeVal)*10);
// Serial.println(fadeVal);
}
enum states {LEDOFF, FADEUP, LEDON, FADEDOWN};
void setState(byte index)
{
currentState=index;
stateActiveSince=millis();
Serial.print("Current state is: ");Serial.println(index);
}
long stateTime()
//returns number of milliseconds since current state was set
{
return millis()-stateActiveSince;
}
void funcLedOff()
{
if (stateTime()>10000) setState(FADEUP);
digitalWrite(ledPin,LOW);
}
void funcFadeUp()
{
byte fadeVal=0;
if (stateTime()>5100) setState(LEDON);
else{ fadeVal=stateTime()/20; softPWM(fadeVal);}
return;
}
void funcLedOn()
{
if (stateTime()>10000) setState(FADEDOWN);
digitalWrite(ledPin,HIGH);
}
void funcFadeDown()
{
byte fadeVal=255;
if (stateTime()>5100) setState(LEDOFF);
else {fadeVal=255-stateTime()/20; softPWM(fadeVal);}
return;
}
int (*stateFunctions[])() = {funcLedOff,funcFadeUp,funcLedOn,funcFadeDown};
// *currentFunction=funcLedOff;
void setup()
{
Serial.begin(9600);
pinMode(ledPin,OUTPUT);
setState(LEDOFF);
}
void loop()
{
stateFunctions[currentState]();
}