Multitarea con Máquina de Estados

Ejemplo de Avelino Herrera de Máquina de Estados:

Primera aproximación a realizarlo (L.Salas):

struct Blink {
  int pin;
  int timeOn;
  int timeOff;
  int estado;
  unsigned long relojAnt;
};
Blink blink1{ 3, 100, 100};
Blink blink2{ 6, 500, 300};
Blink blink3{ 9, 300, 500};
Blink blink4{12, 900, 200};

void setup() {
  Serial.begin(9600);
}

void loop() {
  parpadea(&blink1);
  parpadea(&blink2);
  parpadea(&blink3);
  parpadea(&blink4);
}

void parpadea(Blink *blink) {
  if (blink->estado == 0) {                      // Estado 0: es para inicializar
    pinMode(blink->pin, OUTPUT);
    digitalWrite(blink->pin, HIGH);
    blink->relojAnt = millis();
    blink->estado = 1;
  } else if (blink->estado == 1) {               // Estado 1: led on
    if (millis() - blink->relojAnt > blink->timeOn) {
      blink->relojAnt = millis();
      digitalWrite(blink->pin, LOW);
      blink->estado = 2;
    }
  } else if (blink->estado == 2) {               // Estado 2: led off
    if (millis() - blink->relojAnt > blink->timeOff) {
      blink->relojAnt = millis();
      digitalWrite(blink->pin, HIGH);
      blink->estado = 1;
    }
  }
}

 

Después del Refactor( Rubén Tejera):

enum State {Initialize, LedOn, LedOff};

struct Led {
  int pin;
  unsigned long timeFrameOn;
  unsigned long timeFrameOff;
  State actualState;
  unsigned long previusClock;
};

Led led1{ 3, 100, 100};
Led led2{ 6, 500, 300};
Led led3{ 9, 300, 500};
Led led4{12, 900, 200};

bool isTimeToChangeState(unsigned long previusTime, unsigned long rangeTime){
  return millis() - previusTime > rangeTime;
}

void setPreviusClock(Led *led){
  led->previusClock = millis();
}

void setState(Led *led, State newState){
  led->actualState = newState;
}

void setPinMode(int pin, bool type){
  pinMode(pin, type);
}

void setDigitalOutput(int pin, int newState){
  digitalWrite(pin, newState);
}

void switchOnLed(Led *led){
  setPreviusClock(led);
  setDigitalOutput(led->pin, HIGH);
  setState(led, LedOn);
}

void switchOffLed(Led *led){
  setPreviusClock(led);
  setDigitalOutput(led->pin, LOW);
  setState(led, LedOff);
}

void startLed(Led *led){
  setPinMode(led->pin, OUTPUT);
  switchOnLed(led);
}

void blink(Led *led) {
  switch ( led->actualState ){
    case Initialize:
      startLed(led);
      break;

    case LedOn:
      if (isTimeToChangeState(led->previusClock, led->timeFrameOn)) {
        switchOffLed(led);
      }
      break;

    case LedOff:
      if (isTimeToChangeState(led->previusClock, led->timeFrameOff)) {
        switchOnLed(led);
      }
      break;

    default:
      startLed(led);
      break;
  }
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  blink(&led1);
  blink(&led2);
  blink(&led3);
  blink(&led4);
}