uso millis()

Come spunto aggiungo anche il codice di esempio di miky_police in forma di macchine a stati, come suggerito qualche post precedente.

Oltre al fading lampeggia anche indisturbato il led on board, e allo stesso modo possono essere portati avanti altri N lavori indipendenti in contemporanea.

Curiosità: In questo codice le due funzioni gestFader e gestObdLed vengono eseguite circa 50mila volte al secondo ciascuna, quindi il ciclo programma è di circa 20 microsecondi.

//----------------------------------------------------------------------------
#define  EXT_LED_PIN  3
#define  OBD_LED_PIN  13
//----------------------------------------------------------------------------
void setup() 
{
    pinMode(EXT_LED_PIN, OUTPUT);
    pinMode(OBD_LED_PIN, OUTPUT);
}
//----------------------------------------------------------------------------
void loop() 
{
    gestFader();  // processo alba-tramonto su led esterno
    gestObdLed(); // processo lampeggio led on board 1Hz
}
//----------------------------------------------------------------------------
void gestObdLed()
{
    static unsigned long tempo = 0;

    if(millis() - tempo >= 500)
    {
        tempo += 500;
        digitalWrite(OBD_LED_PIN, !digitalRead(OBD_LED_PIN));
    }
}
//----------------------------------------------------------------------------
void gestFader()
{
    static byte          fase = 0;
    static unsigned long tempo = 0;
    static int           fadeValue = 0;

    switch (fase)
    {
        case 0: // IN ACCENSIONE (durata 1.53 sec)
            analogWrite(EXT_LED_PIN, fadeValue);
            if(millis() - tempo >= 30) 
            {
                tempo += 30;
                fadeValue += 5;
                if(fadeValue > 255) { tempo = millis(); fase = 1; }
            }
            break;
        //------------------------------------------------------------
        case 1: // DURATA GIORNO 3 SECONDI
            if(millis() - tempo >= 3000) 
            {
                fadeValue = 255;
                tempo = millis();
                fase = 2;
            }
            break;
        //------------------------------------------------------------
        case 2: // IN SPEGNIMENTO (durata 1.53 sec)
            analogWrite(EXT_LED_PIN, fadeValue);
            if(millis() - tempo >= 30)  
            {
                tempo += 30;
                fadeValue -= 5;
                if(fadeValue < 0) { tempo = millis(); fase = 3; }
            }
            break;
        //------------------------------------------------------------
        case 3: // DURATA NOTTE 5 SECONDI
            if(millis() - tempo >= 5000) 
            {
                fadeValue = 0;
                tempo = millis();
                fase = 0;
            }
    }//end switch
}        
//----------------------------------------------------------------------------

La dimostrazione del fatto che il problema non è strettamente delay contro millis, ma la struttura logica con cui si imposta l'esecuzione, è il codice seguente, che fa la stessa cosa senza usare millis ma solo delay e non blocca nulla :wink:

//----------------------------------------------------------------------------
#define  EXT_LED_PIN  3
#define  OBD_LED_PIN  13
//----------------------------------------------------------------------------
void setup() 
{
    pinMode(EXT_LED_PIN, OUTPUT);
    pinMode(OBD_LED_PIN, OUTPUT);
}
//----------------------------------------------------------------------------
void loop() 
{
    gestFader();  // processo alba-tramonto su led esterno
    gestObdLed(); // processo lampeggio led on board 1Hz
    delay(10);    // temporizza il programma a passi di *circa* 10ms
}
//----------------------------------------------------------------------------
void gestObdLed()
{
    static unsigned long tempo = 0;
    static byte          counter = 0;

    if(++counter == 50)
    {
        counter = 0;
        digitalWrite(OBD_LED_PIN, !digitalRead(OBD_LED_PIN));
    }
}
//----------------------------------------------------------------------------
void gestFader()
{
    static byte          fase = 0;
    static unsigned long tempo = 0;
    static int           fadeValue = 0;
    static int           counter = 0;

    switch (fase)
    {
        case 0: // IN ACCENSIONE (durata 1.53 sec)
            analogWrite(EXT_LED_PIN, fadeValue);
            if(++counter == 3) 
            {
                counter = 0;
                fadeValue += 5;
                if(fadeValue > 255) { counter = 0; fase = 1; }
            }
            break;
        //------------------------------------------------------------
        case 1: // DURATA GIORNO 3 SECONDI
            if(++counter == 300) 
            {
                fadeValue = 255;
                counter = 0;
                fase = 2;
            }
            break;
        //------------------------------------------------------------
        case 2: // IN SPEGNIMENTO (durata 1.53 sec)
            analogWrite(EXT_LED_PIN, fadeValue);
            if(++counter == 3) 
            {
                counter = 0;
                fadeValue -= 5;
                if(fadeValue < 0) { counter = 0; fase = 3; }
            }
            break;
        //------------------------------------------------------------
        case 3: // DURATA NOTTE 5 SECONDI
            if(++counter == 500) 
            {
                fadeValue = 0;
                counter = 0;
                fase = 0;
            }
    }//end switch
}        
//----------------------------------------------------------------------------

Nota: naturalmente in questo caso il ciclo programma è di 10ms, le funzioni vengono cioè eseguite solo cento volte al secondo.