Gestire più pattern contemporaneamente è certamente possibile con una piattaforma come Arduino e ci sono diversi modi in cui puoi farlo.
Un metodo che prenderei in considerazione è la scrittura di funzioni che rappresentano efficacemente ogni modello matematicamente. Lo passeresti solo per il tempo totale trascorso finora nel tuo programma e farà l'azione appropriata per quel momento specifico. Tornerà immediatamente dopo (senza ritardi o altro).
Per fare ciò, devi prima sapere quanto dura un singolo ciclo del modello. È quindi possibile utilizzare l'operatore modulo per capire fino a che punto del ciclo corrente ci si trova. Da lì, tutto ciò che devi fare è avere alcune ifcondizioni per determinare cosa fare in un dato momento.
Ecco come potrebbe apparire il tuo modello "5 secondi acceso, 5 secondi spento":
function pattern5on5off(unsigned long totalTime)
{
// Calculate how far through the current cycle we are
const unsigned long cycleTime = totalTime % 10000;
// If we're in the first 5 seconds of the cycle then turn the light on.
// Otherwise, turn it off.
if (cycleTime < 5000)
digitalWrite(3, HIGH);
else
digitalWrite(3, LOW);
}
Certo, chiamare costantemente digitalWrite()quando tecnicamente non è necessario non è molto efficiente. Tuttavia, non dovrebbe causare alcun danno ed è abbastanza facile da ottimizzare se necessario.
Per usare l'esempio sopra in uno schizzo, devi solo chiamarlo loop()e passare il numero da cui ottieni millis(); per esempio:
void loop()
{
const unsigned long totalTime = millis();
pattern5on5off(totalTime);
// call other patterns here...
}
Altri schemi saranno più complessi, ma seguiranno lo stesso principio. Dovresti semplicemente usare le ifdichiarazioni appropriate per esprimere la tua logica.
La cosa vitale da ricordare è che la funzione rappresenta un momento specifico nel tempo. Non dovrebbe mai mettere in pausa o ritardare il programma, altrimenti impedirà l'esecuzione degli altri pattern.
Modifica: temporizzazione sul primo ciclo
Come notato da jfpoilpret nei commenti, il primo ciclo inizierà in un punto casuale. Questo perché la prima volta che si chiama millis()in loop(), non si avvia a 0 (il dispositivo sarà già stato in esecuzione per un breve periodo prima loop()viene chiamato). È facile da risolvere, se necessario.
Lo faresti compensando il totalTimevalore di qualunque valore tu abbia ottenuto la prima volta loop(). Per esempio:
unsigned long g_startTime = 0;
void loop()
{
unsigned long totalTime = 0;
if (g_startTime == 0) {
// This is the first cycle.
// Store the start time so we can compensate later.
g_startTime = millis();
} else {
// This is not the first cycle.
// Compensate for the start time.
totalTime = millis() - g_startTime;
}
pattern5on5off(totalTime);
// etc..
}