Misuratore Ampere / Volt / Continuità per pista Slot

ti rendi conto vero che in sei ore hai cambiato idea su una parte hardware "importante" del tuo progetto, scegliendo una soluzione sbagliata che NON ti era mai stata consigliata, quando potevi scegliere tra una moltitudine di soluzioni che ti erano state proposte ma hai rifiutato?
e poi sei tornato indietro adottando una soluzione semplicissima, ma che ti hanno dovuto consigliare?
e comunque sempre su una parte "laterale" del tuo progetto, mentre le funzioni principali sono al palo
questa situazione ha un nome ben preciso: "analisys paralisys"
che in italiano rende: troppa tastiera e troppo poco stagno, come ti ho scritto prima

ricki158:
Qua comunque metto il video delle prove.

https://youtu.be/3GB7U7DbHMM

...

Non so se hai mai visto questo video, ma come puoi ben notare ho i due display (che ho capito come usare e che circuito fare SPORCANDOMI LE MANI E FACENDO PROVE, PROVE NELLE QUALI NE HO BRUCIATI DUE) ho i due pulsanti e tutto sembra funzionare correttamente, tranne la temporizzazione per quel che riguarda la tastiera e i display (secondo me).

Non ho mai programmato seriamente in vita mia e queste sono le mie prime esperienze. Non mi sembra di essermi tirato indietro davanti alle prove, prove anche stupide (vedi i diodi o la resistenza) che comunque mi sono servite a capire in futuro quali strade sono migliori di altre. Quello che attualmente non riesco a provare sono le misurazioni che devo fare in loco, dal momento che VOGLIO FINIRE LA PARTE SOFTWARE DI GESTIONE DEI DISPLAY E DELLE SCHERMATE, anche perché vorrei finire prima un problema e poi vedere che cosa succede con le misurazioni.

L'ultimo sketch del video lo allego a questo post.

Dal momento che, come ho già spiegato, non ho mai programmato pesantemente e alcune cose non mi sono chiare, potresti spiegarmi che cosa sto sbagliando, anziché dirmi che non mi brucio abbastanza le dita? Non chiedo la pappa pronta, chiedo soltanto di capire quali sono i miei errori e magari se mi fai capire come risolverli.
Se fossi nato "imparato" non credo avrei aperto un topic su questo forum...

Per quanto riguarda la "paralisi", beh si. Dal momento che non so come proseguire sulla gestione dei display, sono andato avanti con i lavori sulla pista per raccogliere i dati. Mi sono accorto del problema sul sensore di corrente ed ho chiesto aiuto, probabilmente non ricordandomi di che cosa si parlava nelle pagine precedenti. Ad ogni modo sto cercando di utilizzare questo topic come un diario per ricordarmi ogni cosa che ho fatto e ogni idea alternativa che potrei aver utilizzato per fare la stessa cosa. Ricordavo gli ACS758 ma non mi ricordavo di averne visti con basetta (molto più semplice per l'installazione) e cercavo qualcosa.

Voltmetro_Pista.ino (33.7 KB)

Tutto vero, hai ragione
Non dovevo esprimermi così, giusto
Semplicemente io avrei adottato una roadmap differente
Una UNO per misurare le tensioni, via subito, due ore di lavoro, letteralmente 5 fili posati, leggere da seriale
Dopo sarei passato a una MEGA, con 4 shunt per le correnti, e 4 operazionali per l'amplificazione, sempre su seriale
Fatto questo sarei passato a gestire i display, magari a casa con la UNO provare i display, nei giorni possibili alla pista con la MEGA mettere a posto le correnti, in contemporanea, insomma
Da ultimo "giuntare" il tutto
poi, sembra che tu abbia le idee più chiare delle mie,......

Beh sarebbe stata una buona idea, avrei dovuto fare una misurazione a monte della resistenza di shunt e a valle, in totale 8 misurazioni, 8 partitori di tensione e due convertitori analogico digitali a 16 bit. La caduta di tensione, a resistenza conosciuta, mi avrebbe dato la corrente passante. Inoltre avrei già effettuato le misure a monte in tensione per i regolatori.

Ottima idea, semplice ed efficace, ma ormai ho preso questa strada.

Per quanto riguarda invece i display? Che cosa c'è che non funziona come vorrei a livello software?

Tanto per cominciare non é "ormai ho preso questa strada", lo sarebbe se il progetto fosse concluso, ma non essendo tale la strada può ancora essere cambiata. Anzi, direi che sarebbe meglio cambiarla, vusto che la strada attuale non ti ha ancora portato a stendere neanche un filo.
Quindi ora capiamo TUTTO l'hardware che devi utilizzare, e se non lo possiedi ancora attendiamo che ti arrivi.
Dopo questo testiamo ogni conponente scoprendo in tal modo i suoi limiti e le sue esigenze.
Una volta fatto ciò si monta tutto in loco e si riverifica (non si sa mai)
Infine si scrive lo scatch completo, da caricare in loco.
Si fa così perché con il metodo attualmente in uso non pare si sia sortito l'effetto desiderato.

ricki158:
Per quanto riguarda invece i display? Che cosa c'è che non funziona come vorrei a livello software?

Non ne ho la più pallida idea, non sono interessato a display e robe simili
mi piace la programmazione "dura e pura", mi spiace

Silente:
Tanto per cominciare non é "ormai ho preso questa strada", lo sarebbe se il progetto fosse concluso, ma non essendo tale la strada può ancora essere cambiata. Anzi, direi che sarebbe meglio cambiarla, vusto che la strada attuale non ti ha ancora portato a stendere neanche un filo.
Quindi ora capiamo TUTTO l'hardware che devi utilizzare, e se non lo possiedi ancora attendiamo che ti arrivi.
Dopo questo testiamo ogni conponente scoprendo in tal modo i suoi limiti e le sue esigenze.
Una volta fatto ciò si monta tutto in loco e si riverifica (non si sa mai)
Infine si scrive lo scatch completo, da caricare in loco.
Si fa così perché con il metodo attualmente in uso non pare si sia sortito l'effetto desiderato.

E' vero, però preferisco usare quei modulini che sono piccoli rispetto a una resistenza di shunt da 50A.

L'unica cosa che mi deve ancora arrivare sono i moduli con l'ACS758, per il resto ho tutto. Il circuito con solo i display e i due pulsanti l'ho fatto su breadboard, ho anche i due moduli dei convertitori analogico digitale da collegare e i partitori di tensione. Ho collegato alla pista i cavi per leggere le tensioni. Posso intanto realizzare i partitori su breadboard e provare un solo canale, ma dal momento che per adesso funzionano solamente i display e la tastiera, e funzionano male da come si può vedere nel video, volevo risolvere questo problema software intanto, sennò poi le cose che non funzionano rischiano di essere troppe e dovrei maneggiare troppe cose di cui non ho la padronanza. Per questo mi sono fermato a questo punto.

Cioè se ho delle letture che sono lente oppure leggono cose totalmente sballate, come faccio a capire dove sta il problema se già la temporizzazione della tastiera e dei display può avere problemi? E' un errore nel codice di acquisizione oppure nel codice di gestione display e tastiera?

E' questo che sto dicendo ed è per questo che sono fermo. E sono fermo perché non so far funzionare queste cose e vi sto chiedendo un aiuto se non altro a capire dove sto sbagliando.

ricki158:
Cioè se ho delle letture che sono lente oppure leggono cose totalmente sballate, come faccio a capire dove sta il problema se già la temporizzazione della tastiera e dei display può avere problemi? E' un errore nel codice di acquisizione oppure nel codice di gestione display e tastiera?

Ma allora non hai capito nulla. Io ti ho detto di PROVARE TUTTO SEPARATAMENTE proprio per far si che gli eventuali problemi non possano trovarsi da altre parti. Perché se il codice degli lcd NON fosse caricato li il problema NON potrebbe essere. Quindi per trovare il problema di un pezzo carica SOLO il suo codice.
Poi, ora sono al mare e non posso essere di aiuto attivo, ma so che se cerchi un problema in quel codice é come cercare un ago in un pagliaio

Ok allora, mi rendo conto che il programma può essere complicato.
In questo periodo sono un po' incasinato con gli esami ma oggi ho pulito un po' il codice per tenere solo quello che mi interessa per la gestione dei display e dei due tasti. Allego il codice.

In pratica ci sono vari problemi: intanto il refresh dei display, questo condiziona le letture. Succede la stessa cosa di quel che succedeva nel video, ovvero fa un refresh ogni mezzo secondo circa, e quindi una lettura della tastiera ogni mezzo secondo. Io ho impostato un refrsh per la tastiera, così se tengo premuto un tasto i valori non mi schizzano velocemente (avevo paura che tenendo premuto il tasto SEL per cambiare modalità, una volta cambiata modalità essa cambiava troppo velocemente per cambiarne solo una alla volta oppure comunque abbastanza lentamente da averne il controllo), però questo refresh avviene dopo 100 millisecondi.

Un altro "problema" è l'aggiornamento del display cancellando i valori precedenti:
Quando sono all'interno di una modalità a me serve aggiornare solamente i dati della lettura, del massimo e la X per la selezione di quale massimo voglio azzerare.
Ogni volta che cambio la modalità invece vorrei cancellare tutto quello che ho scritto tranne l'intestazione e il fondo dello schermo. Quelli rimangono. Questo perché in 3 modalità ho la suddivisione delle piste e il colore, mentre per la quarta modalità ho temperatura e umidità, quindi devo cancellare tutto lo schermo.

Voltmetro_Pista_TEST_DISPLAY_KEYBOARD.ino (27.8 KB)

allora, intanto ho cominciato a rivedere il codice per quel che riguarda la "tastiera" dei due tasti, in particolare la funzione "long press" per il tasto select.

unsigned long selectTime = 0;                         /* salva i millisecondi */
#define selectDelay 1000                              /* tempo in cui select deve rimanere acceso perché capiti qualcosa */
byte varSEL = 0;                                      /* variabile che contine il numero del canale in base a quante volte schiaccio il tasto select */
byte mode = 0;                                        /* cambia la modalità */
bool selectLong = false;                              /* variabile booleana per il pulsante select schiacciato per più tempo */
bool selectFlag = false;

void setSEL(){

  if (select) {                                       /* se schiaccio select e quindi la variabile booleana select è true */
    
    if (!selectFlag) {                                /* se la flag di select è false */
      selectFlag = true;                              /* porta la flag a true */
      selectTime = millis();                          /* salva il tempo di millis */
    }

    if ((millis() - selectTime > selectDelay) && (!selectLong)) {  /* se il tempo da quando ho iniziato a schiacciare select è maggiore del tempo impostato e la variabile booleana selectLong è false  */
      selectLong = true;                              /* porta a true la variabile booleana selectLong */
      if (mode < 3) {mode++;}                         /* esegui questo if. se mode è minore di 4, aggiungi uno a mode */
      else mode = 0;                                  /* altrimenti porta a 0 mode */
    }
  
  }
  
  else {                                              /* altrimenti se non schiacci select */
    
    if (selectFlag) {                                 /* se la flag di select è true */
      
      if (selectLong) {selectLong = false;}           /* se select long è true, portalo a false */
      
      else {                                          /* altrimenti se select long è false */
        
        if (varSEL < Channel - 1) {varSEL++;}         /* se varSEL è minore di Channel, aggiungi uno a varSEL */
        else varSEL = 0;                              /* altrimenti porta a 0 varSEL */
      
      }
    
      selectFlag = false;                             /* porta la flag di select a false */
    
    }
  }
}

Questa è tutta la funzione che gestisce solo il tasto select, mentre la funzione di "acquisizione" è questa:

unsigned long refreshKeyboardTime = millis();         /* salva i millisecondi una sola volta all'accensione del processore per il loop del refresh della tastiera */
#define refreshKeyboardLoop 100                       /* tempo di clock per il loop del refresh della tastiera */

#define KeyboardPin A0                                /* pin lettura tastiera */
byte varKeyboard = 0;                                 /* variabile byte che contiene il valore della lettura del pin anallogico della tastiera */
bool select = false;                                  /* variabile booleana per il pulsante select */
bool reset = false;                                   /* variabile booleana per il pulsante reset */

void keyboard(){
  varKeyboard = analogRead(KeyboardPin);              /* lettura del pin analogico della tastiera */
  if (varKeyboard < 127){select = true; return;}      /* se la lettura è minore del valore, la variabile booleana select è true. se l'if è true allora blocca qui la funzione con il return */
  if (varKeyboard < 255 && varKeyboard >= 127){reset = true; return;}  /* se l'if precedente non è vero, la funzione va avanti. se la lettura è compresa fra i valori allora la variabile booleana reset è true. se l'if è true allora blocca qui la funzione con il return */
  select = false;                                     /* nel caso in cui entrambi gli if non siano true, porta a false select */
  reset = false;                                      /* nel caso in cui entrambi gli if non siano true, porta a false reset */
}

E funziona rispetto a prima.
Nella parte di acquisizione ho scritto il codice semplice, come veniva a me.
Nella parte di gestione del long press mi sono aiutato con un sito ma ho capito che le azioni vanno fatte alla fine, quando il tasto non è più premuto. Quindi bisogna servirsi di una flag in modo da capire il cambiamento di stato. Appena schiaccio il pulsante salvo il tempo di millis e poi faccio un controllo sulla flag che porto a true, dopodiché quando trascorre il tempo che voglio allora mi succede quello che voglio far succedere con il long press. Quando invece mollo il pulsante, se la variabile booleana del long press è true, la porto a false e basta, sennò se non è "scattata" allora faccio le azioni dello short press.

ricki158:
... se tengo premuto un tasto i valori non mi schizzano velocemente ...

Mi auto-quoto da un'altro post (:D)

Etemenanki:
...
SE pulsante premuto E flag a zero, metti variabile = millis, e metti flag ad 1
SE pulsante premuto, E flag ad uno, E tempo trascorso (da controllare con millis), esegui comandi e metti flag a due
SE pulsante rilasciato E flag diversa da zero, metti flag a zero
...

In pratica, usa una flag ed una unsigned long, che gestisci con tre if consecutivi ...

il primo if (ma solo se il pulsante prima non era premuto) controlla se hai premuto il tasto, se si, imposta la variabile unsigned long uguale a millis (per poterla poi controllare con il secondo if) e mette la flag da 0 ad 1 ... da qui in poi non verra' piu eseguito finche' il pulsante non verra' rilasciato e la flag tornera' a 0 ...

il secondo if (che agisce solo dopo che il primo ha impostato variabile a millis e flag ad 1), controlla che il pulsante sia premuto, che la flag sia ancora ad 1 (pulsante ancora premuto, non e' stato rilasciato nel frattempo), e che il tempo di attesa (quello minimo in cui devi tenere il pulsante premuto) sia trascorso, se no non fa nulla, se si, esegue i comandi relativi (nel momento in cui il tempo scade, non quando rilasci il pulsante), e mette la flag a 2 (in modo da non rieseguire di nuovo il tutto al prossimo ciclo di loop) ...

Il terzo if si limita a resettare la flag, che sia o meno trascorso il tempo minimo non importa ...

E' perfino possibile inserire un quarto if che esegua dei comandi se il tempo minimo di pressione NON sia stato raggiunto (differenziare fra pressione lunga e pressione breve), ma in questo caso i relativi comandi (quelli del tempo breve) verranno eseguiti per forza dopo il rilascio del tasto ... pero' la cosa non ha molta importanza, dato che se uno imposta, tipo, un tempo minimo di 1 secondo, e le pressioni brevi sono piu corte, il ritardo sarebbe al massimo dei pochi decimi di secondo in cui il tasto rimane premuto per il tempo breve ...

Una cosa del genere, nel tuo caso, molto a spanne (pseudocodice, da correggere ovviamente)

...
   if ((varKeyboard<127)&&(miaflag==0))
   {
      variabileul=millis();
      miaflag=1;
   }
   if ((varKeyboard<127)&&(miaflag==1)&&(millis()-variabileul>1000)) \\un secondo, come esempio
   {
      (... codice da eseguire una volta, se il tasto e' rimasto premuto piu di un secondo ...)
      miaflag=2;
   }
   if ((varKeyboard=0)&&(miaflag==1) \\tasto rilasciato prima che passasse un secondo
   {
      (... codice da eseguire una volta, se il tasto e' rimasto premuto meno di un secondo ...)
      miaflag=2;
   }
   if ((varKeyboard=0)&&(miaflag==2) \\tasto rilasciato ed operazioni gia eseguite
   {
      (... nulla ... oppure codice da eseguire sempre al rilascio del tasto, se necessario ...)
      miaflag=0;
   }

In questo caso, il terzo if viene eseguito solo nel momento in cui rilasci il pulsante, solo se il secondo if non ha gia messo la flag a 2 (quindi se il secondo di tempo non era ancora trascorso, mentre invece se trascorre, il secondo if esegue i suoi comandi alla scadenza del tempo ed imposta la flag a 2 lui, impedendo l'esecuzione del terzo) ... mentre il quarto resetta la flag al rilascio solo se uno dei precedenti ha messo la flag a 2, segno che o uno o l'altro hanno eseguito i rispettivi comandi ... (sarebbe perfino possibile inserire un'ulteriore if che restituisca un'errore se il pulsante viene rilasciato ma nessuno dei due precedenti if ha messo la flag a 2, segno che non e' stato eseguito qualcosa che invece doveva essere eseguito, ma qui andiamo nelle cose inutili per il tuo scopo, mi sa :wink:

EDIT: nel quarto if, puoi mettere anche li un codice, ma solo se serve, che verra' eseguito in ogni caso al rilascio del tasto ... potrebbe essere, che so, una tone per fare il bip, o qualsiasi cosa dovesse essere necessaria da fare "sempre" al rilascio del tasto (sempre, nel senso sia che il tasto sia rimasto premuto poco o molto ... e' facoltativo, semplicemente una possibilita' in piu ;))

Come dicevo di la, a logica sembrerebbe perfino che possa funzionare ... resta da provarlo :wink:

Ei Etem! :smiley: Grazie per la risposta e piano piano cerco di capire la logica del tuo codice.

Io per quello che ho fatto funziona, utilizzando uno stato del bottone, una flag del bottone, una flag long click del bottone e il tempo.

SE il bottone è premuto
SE la flag del bottone è bassa (questo per il cambio di stato del bottone)
porta la flag alta
salva i millis
SE è trascorso il tempo che ho impostato && la flag long click è bassa (cioè è trascorso il tempo e non sono entrato in long click)
porta la flag long click alta
cicla la variabile mode per cambiare modalità
ELSE (quindi se il bottone non è premuto)
SE la flag è alta
SE la flag long click è alta (cioè se ho appena rilasciato dopo aver tenuto premuto il pulsante per il tempo long click)
porta la flag long click bassa
ELSE (cioè se invece ho appena rilasciato dopo aver premuto normalmente il pulsante)
cicla la variabile varSEL per selezionare quale componente dell'array dei valori del massimo voglio resettare
porta la flag bassa

void setSEL(){
  if (select) {                                       /* se schiaccio select e quindi la variabile booleana select è true */
    if (!selectFlag) {                                /* se la flag di select è false */
      selectFlag = true;                              /* porta la flag a true */
      selectTime = millis();                          /* salva il tempo di millis */
    }
    if ((millis() - selectTime > selectDelay) && (!selectLong)) {  /* se il tempo da quando ho iniziato a schiacciare select è maggiore del tempo impostato e la variabile booleana selectLong è false  */
      selectLong = true;                              /* porta a true la variabile booleana selectLong */
      if (mode < 3) {mode++;}                         /* esegui questo if. se mode è minore di 3, aggiungi uno a mode */
      else mode = 0;                                  /* altrimenti porta a 0 mode */
    }
  }
  else {                                              /* altrimenti se non schiacci select */
    if (selectFlag) {                                 /* se la flag di select è true */
      if (selectLong) {selectLong = false;}           /* se select long è true, portalo a false */
      else {                                          /* altrimenti se select long è false */
        if (varSEL < Channel - 1) {varSEL++;}         /* se varSEL è minore di Channel - 1, aggiungi uno a varSEL */
        else varSEL = 0;                              /* altrimenti porta a 0 varSEL */
      }    
      selectFlag = false;                             /* porta la flag di select a false */
    }
  }
}

Buongiorno!
Dopo aver risolto la questione del pulsante ho cominciato ad affrontare il problema refresh del display.

Ho letto qualcosina sul web anche, il problema è pulire il display ogni volta che qualche pixel cambia.

Ho cominciato intanto a dividere le cose da stampare sul display non come singola schermata (per esempio per la modalità 0 voglio vedere le tensioni, modalità 1 voglio vedere le correnti, modalità 2 gli errori, modalità 3 temperatura e umidità) ma le ho divise per "refresh". Per esempio non serve stampare ogni volta la schermata completa ma posso chiamare una singola funzione che stampa il nome delle piste, che rimangono "stazionarie" nelle prime 3 modalità. In questo modo ho ridotto il tempo di refresh del display, ma non sono ancora abbastanza veloce.

Ho poi pensato a togliere lo sfondo quando chiamavo la funzione per cambiare il colore del testo, in questo modo vado a scrivere solo i pixel del testo e non il "rettangolo" composto dal testo e dallo sfondo.

Per ogni funzione che scrive quello che voglio ho fatto una funzione gemella che scrive lo stesso testo ma in nero, colore dello sfondo. In questo modo cancello le scritte e cambio solo i pixel che mi servono, velocizzando tutto.

Mi restano da sistemare alcune parti fisse che devo cancellare soltanto quando cambio da un modo all'altro, con l'utilizzo di una flag, quindi cancellando una sola volta ed evitando un refresh continuo della funzione che cancella la stringa.

Il problema che credo avrò sarà quello relativo alle parti che per forza di cose devono aggiornarsi continuamente, ovvero i valori stampati degli array delle tensioni ecc ecc. Ho paura che mi rallentino non poso il refresh del display. Devo provare.

Il problema del refresh del display non è tanto il refresh in sè, piuttosto è che mi forza la velocità di clock delle operazioni. Per esempio in questo modo non riesco a comunicare attraverso la libreria DHT11 con il modulo e non ottengo dei valori corretti per avere una lettura di temperatura e umidità. Probabilmente se non risolvo questo problema poi me lo porto avanti non solo per il DHT11 ma anche per l'interrogazione ai due moduli ADC per tensioni e correnti, quindi sostanzialmente non potrò leggere nulla.

Io intanto nel frattempo continuo a dividere attraverso l'uso di funzioni le cose che voglio stampare, in maniera da cancellare il meno possibile dal display e renderlo veloce.

Un'altra cosa che non funziona come mi sarei immaginato è la funzione che mi scrive una X accanto al valore del massimo che seleziono attraverso la pressione normale del tasto select e con la variabile varSEL. Sulla stampa seriale vedo correttamente il numero della varSEL, ma stampando mi compaiono tutte le X.

Ho usato questo codice:

void printVarSEL(){
  switch (varSEL){
    case 0:
      display1.setTextColor(ST7735_WHITE);            /* imposta il colore bianco per il carattere */
      display1.setTextSize(1);                        /* imposta la dimensione 1 per il carattere */
      display1.setCursor(110, 58);                    /* punta al pixel 110, 58 */
      display1.print("X");                            /* scrivi X */
    case 1:
      display1.setTextColor(ST7735_WHITE);            /* imposta il colore bianco per il carattere */
      display1.setTextSize(1);                        /* imposta la dimensione 1 per il carattere */
      display1.setCursor(110, 125);                   /* punta al pixel 110, 125 */
      display1.print("X");                            /* scrivi X */
    case 2:
      display2.setTextColor(ST7735_WHITE);            /* imposta il colore bianco per il carattere */
      display2.setTextSize(1);                        /* imposta la dimensione 1 per il carattere */
      display2.setCursor(110, 58);                    /* punta al pixel 110, 58 */
      display2.print("X");                            /* scrivi X */
    case 3:
      display2.setTextColor(ST7735_WHITE);            /* imposta il colore bianco per il carattere */
      display2.setTextSize(1);                        /* imposta la dimensione 1 per il carattere */
      display2.setCursor(110, 125);                   /* punta al pixel 110, 125 */
      display2.print("X");                            /* scrivi X */
  }
}

E ricordo che varSEL "cicla" quando premo il pulsante normalmente attraverso questo codice:

void setSEL(){
  if (select) {                                       /* se schiaccio select e quindi la variabile booleana select è true */
    if (!selectFlag) {                                /* se la flag di select è false */
      selectFlag = true;                              /* porta la flag a true */
      selectTime = millis();                          /* salva il tempo di millis */
    }
    if ((millis() - selectTime > selectDelay) && (!selectLong)) {  /* se il tempo da quando ho iniziato a schiacciare select è maggiore del tempo impostato e la variabile booleana selectLong è false  */
      selectLong = true;                              /* porta a true la variabile booleana selectLong */
      if (mode < 3) {mode++;}                         /* esegui questo if. se mode è minore di 3, aggiungi uno a mode */
      else mode = 0;                                  /* altrimenti porta a 0 mode */
    }
  }
  else {                                              /* altrimenti se non schiacci select */
    if (selectFlag) {                                 /* se la flag di select è true */
      if (selectLong) {selectLong = false;}           /* se select long è true, portalo a false */
      else {                                          /* altrimenti se select long è false */
        if (varSEL < Channel - 1) {varSEL++; varSELclean = true;}  /* se varSEL è minore di Channel - 1, aggiungi uno a varSEL, porta a true la flag per cancellare le x */
        else varSEL = 0;                              /* altrimenti porta a 0 varSEL */
      }    
      selectFlag = false;                             /* porta la flag di select a false */
    }
  }
}

Ma come detto, il codice per il pulsante funziona correttamente, dal valore che stampo sulla seriale.

Allego un video per far vedere a che punto sono arrivato. Il codice lo condivido più tardi quando avrò finito di "dividere" le cose da stampare.

Non ho quei display, pero' cosi ad occhio, non fai prima a cancellare il vecchio valore e scrivere il nuovo solo quando cambia ? (o solo una volta al secondo, se puoi) ... e per cancellare, forse e' piu veloce se scrivi il vecchio valore con il colore di sfondo prima del nuovo ... ad esempio, la cifra e' 1, se diventa 2, scrivi 1 con il colore di sfondo e poi 2, solo nella posizione del valore che cambia (se e' possibile dirgli il pixel di start, ovviamente) ... dovrebbe essere piu rapido che cancellare un riquadro o tutto lo schermo ...

E' infatti quello che sto facendo scrivendo la stessa stringa in nero. Per le scritte statiche o semi statiche è più semplice e appunto le "cancello" solo quando serve, mentre per i valori che cambiano spesso devo scriverli e "cancellarli" ogni volta, così parto con quella parte di schermo pulito.

Per esempio per il valore del massimo, siccome ho comunque una funzione che confronta il massimo con quello precedente e lo scrive se maggiore, posso fare una flag che se maggiore rispetto al massimo precedente va a true, se va a true scrivo in nero il valore precedente e scrivo nel colore desiderato il nuovo valore.

Stessa idea volevo utilizzare per il carattere "X".

Mi viene, a questo punto, un dubbio diverso ... stai usando un solo arduino sia per le varie elaborazioni che per il pilotaggio dei display ? ... lo chiedo perche' ho visto in rete che gia quei "cosi" sono abbastanza lenti anche quando ce n'e' collegato uno solo ... non vorrei che fosse un problema di "sovraccarico" della MCU, in parte, il colpevole ...

Con un solo display pilotato, sono sempre cosi' lenti, o la cosa cambia ?

Si ho un solo Arduino collegato. Con un solo display non ho provato. Per me è comunque un discorso di ottimizzazione. In più potrei comunque far fare un "clock" solo alla funzione che mi gestisce le modalità del display ogni secondo, così nel frattempo posso leggere la tastiera e fare tutto quello che devo fare in parallelo e non sono legato al refresh del display, giusto?

O quello, oppure, forse anche meglio, usare dei "mini", (o micro, o comunque il piu piccolo disponibile che funzioni) per ogni display ... trasformandoli in pratica in "display semi-intelligenti", a cui passi i dati e che si arrangiano a fare visualizzazioni e refresh ... non so a livello software, ma non credo sia complicatissimo (pero' devi chiedere ad un programmatore, cosa che io non sono, per questo) ... lato hardware, solleveresti l'arduino che fa tutto dal carico di dover gestire anche i display e dal dover usare un sacco di memoria extra solo per loro ...

Vorrei contenere le dimensioni di tutto il mobiletto, sennò avrei usato un display di dimensioni maggiori.

La soluzione un Arduino per ogni display è percorribile, con un Arduino minimo che legge tutto quello che portano i sensori e trasmette via i2c agli altri due Arduino. Questo a livello hardware, ma come ho già detto vorrei evitare questa soluzione per l'ingombro.

Per il momento sto percorrendo la strada dell'ottimizzazione dei pixel e del clock più lento così posso fare sia le operazioni dei display sia le operazioni di cui ho bisogno.

Sto finendo di dividere la parte statica dalla parte dinamica, con relative funzioni di pulizia dei caratteri. Dopodiché dovrò farmi venire in mente come cancellare le X di cui non ho bisogno.

Per l'ingombro, puoi farti anche un paio di "standalone" con due pezzi di millefori della stessa dimensione del display (o stampati su misura, volendo), saldati sotto a quelli, ognuno con una MCU con il suo quarzo o risuonatore e poco altro (tanto mica ti serve che siano arduino, dovendo solo gestire le schermate e visualizzare i dati che gli passi, basterebbe la MCU in configurazione minima ... ed avrebbero lo stesso ingombro del display ;))