Realizzarla come macchina a stati finiti, magari utilizzando la AFSD Rhodense seconda di qualche mese fa è di una semplicità disarmante:
serve definire ingressi e uscite
// dichiarazione dei pin usati dalla macchina a stati
// gli ingressi
#define SVuoto1 2
#define SPieno1 3
#define SButton1 4
#define SVuoto2 7
#define SPieno2 8
#define SButton2 9
byte ingresso[]{SVuoto1, SPieno1, SButton1, SVuoto2, SPieno2, SButton2};
// le uscite
#define UEroga1 5
#define UPompa1 6
#define UEroga2 10
#define UPompa2 11
// led lampeggiante (servisse)
byte uscita[] = {UEroga1, UEroga2, UPompa1, UPompa2, LED_BUILTIN};
poi stabilire le varie azioni che la macchina deve fare
// la azioni
void OffPompa1()
{
// spegne la pompa 1
digitalWrite(UPompa1, LOW);
}
void OffPompa2()
{
// spegne la pompa 2
digitalWrite(UPompa2, LOW);
}
void OnPompa1()
{
// accende la pompa 1
digitalWrite(UPompa1, HIGH);
}
void OnPompa2()
{
// accende la pompa 2
digitalWrite(UPompa2, HIGH);
}
void Eroga1()
{
// eroga 1
digitalWrite(UEroga1, HIGH);
// e spegne la sua pompa
OffPompa1();
}
void Eroga2()
{
// eroga 2
digitalWrite(UEroga2, HIGH);
// e spegne la sua pompa
OffPompa2();
}
void NonEroga1()
{
// non eroga 1
digitalWrite(UEroga1, LOW);
}
void NonEroga2()
{
// non eroga 2
digitalWrite(UEroga2, LOW);
}
le condizioni che provocano i passaggi di stato
// le condizioni
bool Vuoto1()
{
// sensore serbatoio vuoto 1
return digitalRead(SVuoto1);
}
bool Vuoto2()
{
// sensore serbatoio vuoto 2
return digitalRead(SVuoto2);
}
bool Pieno1()
{
// sensore serbatoio pieno 1
return digitalRead(SPieno1);
}
bool Pieno2()
{
// sensore serbatoio pieno 2
return digitalRead(SPieno2);
}
bool Bottone1()
{
// Bottone erogazione 1
return digitalRead(SButton1);
}
bool Bottone2()
{
// Bottone erogazione 1
return digitalRead(SButton2);
}
infine descrivere gli stati in funzione di condizioni, tempi ed azioni
//gli stati
stato_t stato1[] =
{
{OffPompa1}, // stato 0 spegne pompa
{OnPompa1}, // stato 1 accende pompa
{Eroga1, NonEroga1}, // stato 2, eroga e spegne pompa
};
stato_t stato2[] =
{
{OffPompa2}, // stato 0 spegne pompa
{OnPompa2}, // stato 1 accende pompa
{Eroga1, NonEroga2}, // stato 2, eroga e spegne pompa
};
a questo punto si definiscono le due macchine (due differenti set di pompa erogatori e similia)
regola_t regola1[] =
{
{0, 1, Vuoto1, 0}, // stato 0, attesa, reagisce al sensore di vuoto
{0, 2, Bottone1}, // stato 0, attesa, reagisce al pulsante
{1, 0, Pieno1}, // stato 1, sta riempiendo, reagisce al pieno
{1, 2, Bottone1}, // stato 1, sta riempiendo, reagisce al pulsante
{2, 0, 0, 3000} // stato 2, eroga, attende fine erogazione
};
regola_t regola2[] =
{
{0, 1, Vuoto2, 0}, // stato 0, attesa, reagisce al sensore di vuoto
{0, 2, Bottone2}, // stato 0, attesa, reagisce al pulsante
{1, 0, Pieno2}, // stato 1, sta riempiendo, reagisce al pieno
{1, 2, Bottone2}, // stato 1, sta riempiendo, reagisce al pulsante
{2, 0, 0, 3000} // stato 2, eroga, attende fine erogazione
};
fsm_t macchinaA = {stato1, sizeof stato1 / sizeof stato1[0], regola1, sizeof regola1 / sizeof regola1[0]}; // * stato, numero stati, * regole, numero regole, stato iniziale
fsm_t macchinaB = {stato2, sizeof stato2 / sizeof stato2[0], regola2, sizeof regola2 / sizeof regola2[0]}; // * stato, numero stati, * regole, numero regole, stato iniziale
e nella loop rimangono da scrivere ben 4 righe
fsm(macchinaA);
// richiama il motore della FSM, sulla macchina A
fsm(macchinaB);
// sulla macchina B
fatto e finito, un pomeriggio di pioggia, anzi, il tempo di una digestione
PS: forse l'ordine di spiegazione non corrisponde con l'ordine di compilazione, verificate di dichiarare le variabili prima di usarle
e con questo chiudo