enum EtatLed : byte {STOP, ETEINTE, EN_ALLUMAGE, ALLUMEE, EN_EXTINCTION} ;

class LedGradient {
    byte brocheLed;
    byte pasDuPwm;
    unsigned long deltaT;
    unsigned long dureeAuxExtremes;
    int pwm;
    unsigned long dernierTick;
    EtatLed etat;

    void generationAleatoire() {
      dureeAuxExtremes = random(500, 1000);   // le temps qu'on attend entre deux gradients
      pasDuPwm = random(1, 10);               // vitesse de progression du PWM
      deltaT = random(5, 20);                 // durée d'attente entre deux changements de PWM
    }

  public:
    LedGradient(const byte pin) : brocheLed(pin) {}

    void demarrer() {
      generationAleatoire();
      digitalWrite(brocheLed, LOW);
      pwm = 0;
      etat = EN_ALLUMAGE;
      dernierTick = millis();
    }

    void arreter() {
      pwm = 0;
      digitalWrite(brocheLed, LOW);
      etat = STOP;
    }

    void begin() {
      pinMode(brocheLed, OUTPUT);
      arreter();
    }

    void tick() {
      switch (etat) {
        case STOP: break;

        case ETEINTE:
          if (millis() - dernierTick >= dureeAuxExtremes) {
            generationAleatoire();
            etat = EN_ALLUMAGE;
            dernierTick = millis();
          }
          break;

        case EN_ALLUMAGE:
          if (millis() - dernierTick >= deltaT) {
            pwm += pasDuPwm;
            if (pwm >= 255) {
              pwm = 255;
              etat = ALLUMEE;
            }
            analogWrite(brocheLed, pwm);
            dernierTick = millis();
          }
          break;

        case EN_EXTINCTION:
          if (millis() - dernierTick >= deltaT) {
            pwm -= pasDuPwm;
            if (pwm <= 0) {
              pwm = 0;
              etat = ETEINTE;
            }
            analogWrite(brocheLed, pwm);
            dernierTick = millis();
          }
          break;

        case ALLUMEE:
          if (millis() - dernierTick >= dureeAuxExtremes) {
            etat = EN_EXTINCTION;
            dernierTick = millis();
          }
          break;
      }
    }
};

LedGradient lesLeds[] = {6, 9, 10, 11};

void setup() {
  randomSeed(analogRead(A0)); // on génère un peu d'aléatoire
  for (auto& l : lesLeds) {
    l.begin();
    l.demarrer();
  }
}

void loop() {
  for (auto& l : lesLeds) l.tick();
}