Cambio attività.
Lo strumento più importante per organizzare la logica del programma è la cosiddetta macchina a stati (State Machine) - un valore che ha un insieme preconosciuto di stati e il programma funziona in modo diverso su ognuno di loro. Sembra complicato, ma in realtà stiamo parlando di un'istruzione switch e di una variabile che viene commutata da un pulsante o da un timer. Il valore di questa variabile è il codice o il numero dello stato, attività, modalità, effetto - in questo caso, questi sono tutti sinonimi. Per esempio:
if (fare clic sul pulsante 1) mode++;
if (fare clic sul pulsante 2) mode--;
switch (mode)
{
case 0:
// compito 0
break;
case 1:
// compito 1
break;
case 2:
// compito 2
break;
// .........
}
Nota: la variabile mode deve essere firmata (int) per evitare l'overflow quando si ottiene un valore negativo.
Pertanto, sono organizzate la selezione e l'esecuzione di sezioni di codice selezionate, modalità di commutazione di funzionamento, effetti e così via.
Cambio di modalità.
Il cambio della variabile di mode può essere fatto non solo come nell'esempio sopra, ci sono opzioni:
- Limitare l'intervallo della variabile modalità al numero minimo di attività (in genere 0) e al massimo (numero di attività - 1).
- Passa dall'ultima attività alla prima e viceversa.
Negli esempi seguenti, MODES è il numero di attività, ovvero con 10 attività, la variabile assumerà valori da 0 a 9.
Limitazione.
if (mode < MODES - 1) mode++; // aumentare.
if (mode > 0) mode--; // diminuire.
Cambio.
if (++mode >= MODES) mode = 0; // aumentare.
if (--mode < 0) mode = MODES - 1; // diminuire.
Array di funzioni.
Sopra, abbiamo discusso di cambiare attività usando l'istruzione switch. Questo è un design classico, ingombrante e comprensibile. Ma cosa succede se abbiamo 10 attività o 50? Ad esempio, effetti per strip LED. Puoi eliminare del tutto lo switch e implementare il cambio di attività in un modo molto più compatto, utilizzando un array di puntatori a funzione. Considera un esempio in cui le attività vengono commutate da un timer con un periodo di 1 secondo. La funzione del compito attualmente attivo viene semplicemente richiamata nel ciclo principale del programma.
// compiti da svolgere.
void task1()
{
}
void task2()
{
}
void task3()
{
}
// numero di compiti.
#define T_AMOUNT 3
// array di funzioni, passiamo i nomi delle funzioni delle attività.
void (*func[])() = {task1, task2, task3};
void setup()
{
}
uint32_t tmrSwitch; // timer.
byte task; // numero dell'attività corrente.
void loop()
{
// timer
if (millis() - tmrSwitch >= 1000)
{
tmrSwitch = millis();
if (++task >= T_AMOUNT) task = 0; // cerchio di commutazione
}
func[task](); //chiamando la funzione corrente - compito
}
L'esempio si adatta molto facilmente per qualsiasi numero di attività, basta creare funzioni aggiuntive e inserirle in un array e modificare il numero di attività da cambiare.
Flags.
Le variabili booleane, o flag, sono uno strumento molto importante per organizzare la logica di un programma. Il flag globale può memorizzare lo "stato" dei componenti del programma, e saranno conosciuti in tutto il programma e nell'intero programma possono essere modificati. Un esempio leggermente esagerato:
bool flag = false;
void loop()
{
// se c'è stato un clic sul pulsante flag = true.
if (buttonClick()) flag = true;
if (flag)
{
// codice
}
}
Lo stato del flag globale può essere letto in qualsiasi altra funzione e posizione del programma, semplificando notevolmente il codice ed eliminando le chiamate non necessarie. Usando il flag, puoi organizzare una singola esecuzione di un blocco di codice su qualche evento:
bool flag = false;
void loop()
{
// se c'è stato un clic sul pulsante flag = true.
if (buttonClick()) flag = true;
if (flag)
{
flag = false; // verrà eseguito una volta dopo aver fatto clic sul pulsante.
}
}
Inoltre, il flag può essere invertito, il che consente di generare la sequenza 10101010 per cambiare alcuni due stati:
bool flag = false;
void loop()
{
// diciamo che la condizione è soddisfatta per un periodo di tempo da un timer.
if (timerElapsed())
{
flag = !flag; // invertire flag
// Ad esempio, devi passare due valori alla funzione, alternandoli su un timer.
setSomeValue(flag ? 10 : 200);
}
}
flags - sono uno strumento molto potente, non dimenticartene.