Passo a passo a spasso nel tempo.......

Altra pensata, altro titolo ad effetto…
se vi ricordate qualche tempo fa avevo scritto una libreria per rendere facili i timer con millis()
era una libreria un po’ sui generis, lo ammetto, tutto contenuto nel puntoacca, e tutta in C, no C++ e oggetti, che’ non sono capace
ma anche così ha la sua valenza…
comunque, quello che non si può gestire con quella libreria è una sequenza di stati successivi, un timer ciclico per intenderci
e quindi oggi ho pensato di generalizzare un timer ciclico
l’uso è banale, si tratta di dimensionare un array di unsigned long int con tanti elementi (tanti tempi, in millisecondi) quanti sono i possibili stati, più uno, obbligatoriamente a 0 (serve alla libreria)
ecco, se volessi fare un timer ciclico a 4 fasi dimensionerei un array di 5 elementi
poi una semplice chiamata di funzione mi restituisce la fase attuale del timer, un numero (un byte) che va da 0 (fase iniziale) a 3 (ultima fase), per poi ricominciare da zero
da lì un semplice if o uno switch, o quello che si vuole, per gestire gli “eventi” del timer ciclico
ecco la funzione:

byte steptime(unsigned long int tempi[], byte dimensione)
{
    if (! tempi[dimensione - 1])
    {
        // non ancora calcolato la somma dei tempi
        for (byte i = 0; i < dimensione - 1; i++)
        {
            tempi[dimensione - 1] = tempi[dimensione - 1] + tempi[i];
        }
    }

    unsigned long int resto = millis() % tempi[dimensione - 1];

    // resto del ciclo ancora da completare
    for (byte i = 0; i < dimensione - 1; i++)
    {
        if (resto < tempi[i])
        {
            // non ancora passato
            return i;
        }
        else
        {
            // passato
            resto = resto - tempi[i];
        }
    }
}

come vedete per prima cosa calcola il tempo totale del ciclo (in millisecondi)
poi ne trova il resto, ovvero “esclude” i cicli già completati, poi determina in quale “fase” del timer ci si trova
siccome a me non piace passare le dimensioni degli array (e non apriamo questo discorso, grazie) mi sono fatto una piccola macro, che mi evita il disturbo

#define timer(tempi) steptime(tempi, sizeof(tempi)/sizeof(tempi[0]))

e quindi per usarlo basta definire la sequenza di tempi (o le sequenze)

unsigned long int sequenza[] = {1000, 2000, 5000, 1000, 0}; // tempi in millisecondi
unsigned long int B[] = {1000, 1000, 3000, 0};       // obbligatoriamente ultimo elemento a 0

e poi dove serve nella loop interrogare la funzione timer(sequenza)
magari anche direttamente in un’altra funzione, così, ad esempio

    byte stato1 = timer(sequenza);
    Serial.print("Stato del timer: ");
    Serial.print(stato1);
    Serial.print(" - ");
    Serial.println(timer(B));
    delay(300);