Ho detto che era incasinato, non è scritto per essere didattico e ci sono insieme molte altre cose. Forse questo scheletro (per orientarsi) può essere più utile?
// collegamenti hardware
#define SPEAKER ... // ---> 0 riposo
#define ENCODER_SW ... // <--- LOW se premuto
#define ENCODER_A ... // <--- HIGH a riposo
#define ENCODER_B ... // <--- HIGH a riposo
// fase iniziale processo appmachine
uint8_t fase = 0;
// variabili valorizzate da lettura encoder
bool onClic;
bool onLpress;
bool onUp;
bool onDn;
// tempo di sistema letto da millis ad ogni ciclo
uint32_t now;
//--------------------------------------------------------------------
// L E V E L 2
//--------------------------------------------------------------------
void beepClic(void) { tone(SPEAKER, 500, 60); }
void beepLpress(void) { tone(SPEAKER, 1000, 60); }
void beepUp(void) { tone(SPEAKER, 3000, 10); }
void beepDn(void) { tone(SPEAKER, 2000, 10); }
//--------------------------------------------------------------------
// L E V E L 1
//--------------------------------------------------------------------
const uint8_t tabT[7][4] = {
{ 0, 4, 1, 0 },
{ 2, 1, 1, 0 },
{ 2, 3, 1, 2 },
{ 2, 3, 3, 0 },
{ 5, 4, 4, 0 },
{ 5, 4, 6, 5 },
{ 5, 6, 6, 0 }
};
void readEncoder(void){
static uint8_t s = 0; // stato processo lettura switch
static uint8_t f = 0; // stato processo lettura fasi
static uint16_t t;
// rileva click e longpress pulsante
onClic = false;
onLpress = false;
uint8_t in = digitalRead(ENCODER_SW);
if (0 == s && LOW == in) { t = now; s = 1; }
else if (1 == s && HIGH == in) { onClic = true; s = 0; }
else if (1 == s && ((uint16_t)now-t > 500)) { onLpress = true; s = 2; }
else if (2 == s && HIGH == in) { s = 0; }
// rileva rotazione encoder
uint8_t enc = (digitalRead(ENCODER_B) << 1) | digitalRead(ENCODER_A);
onUp = (3 == f && 3 == enc);
onDn = (6 == f && 3 == enc);
f = tabT[f][enc];
}
//--------------------------------------------------------------------
void appMachine(void)
{
static uint8_t s;
static uint32_t t; // per calcolo tempo trascorso da inizio fase
static uint8_t fasePrec = ~fase;
bool primo = (fase != fasePrec);
if (primo) { fasePrec = fase; t = now; }
uint32_t trascorso = now - t;
switch (fase)
{
//__________________________________________________
// maschera principale
case 0:
if (primo) { // operaz all'attivazione fase
stampaPrincipale();
}
// se click su encoder, attiva menu
if (onClic) { fase = 1; beepClic(); break; }
// altre operaz da eseguire ad ogni giro
break;
//__________________________________________________
// scorre opzioni menu
case 1:
if (primo) {
s = 0; // scelta da 0 a 6
stampaScelta(s);
}
// se pressione lunga, annulla e torna a principale
if (onLpress) { beepLpress(); fase = 0; break; }
// se clic attiva la scelta
if (onClic) {
beepClic();
// imposta fase regolazione per scelta effettuata
if (...==s) { fase=...; }
//...ecc...
break;
}
// se ruotato riavvia timer inattivita`
if (onUp || onDn) { t = now; }
// se ruotato cambia scelta
if (onUp && s < 6) { s += 1; beepUp(); stampaScelta(s); }
else if (onDn && s > 0) { s -= 1; beepDn(); stampaScelta(s); }
// se passati 20 sec senza azioni torna a principale
if (trascorso > 20000) { fase = 0; }
break;
//__________________________________________________
}
}
//--------------------------------------------------------------------
// L E V E L 0
//--------------------------------------------------------------------
void setup(){
pinMode(ENCODER_A, INPUT);
pinMode(ENCODER_B, INPUT);
pinMode(ENCODER_SW, INPUT);
}
//--------------------------------------------------------------------
void loop() {
now = millis();
readEncoder(); // imposta onClic, onLpress, onUp, onDn
appMachine(); // esegue la fase corrente
}