Voglio usare questo topic per descrivere una possibile implementazione della macchina a stati finiti impiegando uno più switch case. L'aromento è stato già trattato su arduino forum, alcuni post interessanti li elenco qui di seguito:
Sarebbe meglio leggere tutto il topic o se preferite partite da pagina 8.
irrorino
https://forum.arduino.cc/index.php?topic=641557.0
Il primo codice che posto è simile all'implementazione mostrata nei link precedenti, l'obbiettivo è introdurre l'implementazione passo per passo al fine di potere documentare i dettagli poco comprensibili ai principianti.
Prima di passare a leggere lo sketch N°2 è bene capire come funziona il N°1.
boolean oneShotSwitch;
uint32_t elapsedTime;
uint32_t mainTimer;
byte currentState = 0;
byte oldState = ~currentState;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
oneShotSwitch = false;
if (currentState != oldState) {
oneShotSwitch = true;
mainTimer = millis();
}
oldState = currentState;
elapsedTime = millis() - mainTimer;
switch (currentState) {
case 0:
if (oneShotSwitch) {
// se oneShotSwitch == true stampa "case 0"
Serial.println("case 0");
}
// se passano 10 secondi da quando si è entrati nel case 0
// verrà selezionato come stato successivo il case 1
if (elapsedTime >= 10000)
currentState = 1;
break;
case 1:
if (oneShotSwitch) {
// se oneShotSwitch == true stampa "case 1"
Serial.println("case 1");
}
// se passano 10 secondi da quando si è entrati nel case 1
// verrà selezionato come stato successivo il case 2
if (elapsedTime >= 10000)
currentState = 2;
break;
case 2:
if (oneShotSwitch) {
// se oneShotSwitch == true stampa "case 2"
Serial.println("case 2");
}
// se passano 10 secondi da quando si è entrati nel case 2
// verrà selezionato come stato successivo il case 0
if (elapsedTime >= 10000)
currentState = 0;
break;
}
}
Il codice non fa altro che stampare nel monitor seriale la scritta "case n" dove n corrisponde al valore di currentState
la quale può assumere i seguenti valori: 0, 1, 2. Tuttavia qualunque valore nel range 0÷254 può essere assegnato.
La stampa avverrà solo al primo ingresso nel case n. Per 10 secondi il ciclo di loop eseguirà lo stesso case, trascorsi 10 secondi il case eseguito al prossimo ciclo di loop è quello specificato nell'assegnazione a currentState.
Quando si assegna un nuovo valore a currentState possiamo dire che prenotiamo quale sarà il case da eseguire al prossimo ciclo del loop o se preferite stabiliamo cosa deve accadere nel futuro. Il presente è il momento in cui il codice viene eseguito. Il passato viene valuto nel presente e ci dice come siamo arrivati qui, il passato viene salvato nella variabile oldState, il suo valore alle volte è utile valutarlo nel presente altre volte non torna utile.
Nello sketch mostrato sopra non riteniamo utile valutare il passato nel presente, ma oldState è comunque usato all'interno del loop prima della istruzione switch (currentState) {. All'interno del case oldState e currentState hanno lo stesso valore, non sempre ciò è desiderabile ed infatti ho scritto che questo sketch è una possibile implementazione, ciò vuol dire che non è l'unica e aggiungo che non c'è ne una giusta ma al massimo che ne esiste una adatta all'applicazione che si ha in mente di sviluppare.
Provate nel case 2 ad assegnare 254 a currentState anziché 0 (zero).
Il risultato è che nessuno dei case verrà eseguito e nulla verrà stampato nel serial monitor.
Nota: I nomi delle variabili sono stati scelti in modo arbitrario e pertanto lecito dargli un altro nome, purché sia
quanto più possibile autodocumentante.
Ho pronte altre varianti, ma se vole postate la vostra variante, possibilmente che non si discosti troppo da questa o che non sia troppo complessa in modo che si possa descrivere passo passo e via via introdurre la complessità.
Il prossimo sketch stampa quanto segue nel monitor seriale:
case 0-millis():290521000..........290531000
case 1-millis():290531000..........290541000
case 2-millis():290541000..........290551000
case 0-millis():290551000..........290561000
case 1-millis():290561000..........290571000
case 2-millis():290571000..........290581000
Un puntino viene stampato ogni secondo
Ciao.