Multiplexing 4 display 7 segmenti anodo comune problema aliasing

Buonasera a tutti!
Vi chiedo un aiuto: mi sto costruendo un orologio multifunzione con Arduino per poi farne il circuito stampato ed utilizzarlo con un ATMEGA standalone.
Il codice è praticamente finito, e ve ne posto un breve estratto per farvi vedere come ho gestito le varie cifre da visializzare.. Mettiamo che siano le 19 e 24 minuti:

     if(counter_h==19){
                    uno_primo();
               }    nove_secondo();



 if(counter_minutes==24){
      due_terzo();
      quattro_quarto();
    }

Dove uno_primo() è una funzione void:

void uno_primo(){

   digitalWrite(1,HIGH); //Scrive uno nel primo display
   digitalWrite(0,LOW);  // 1,0,12,13 anodo dei display: HIGH display acceso, LOW spento
   digitalWrite(12,LOW);
   digitalWrite(13,LOW);

   digitalWrite(5 , LOW); //Accendo i segmenti di interesse (anodo comune LOW acceso, HIGH spento)
   digitalWrite(6 , HIGH);
   digitalWrite(7 , HIGH);
   digitalWrite(9 , HIGH);
   digitalWrite(10 , HIGH);
   digitalWrite(11 , LOW);
   digitalWrite(4 , HIGH);
   digitalWrite(8 , HIGH);
   delay(2);  //Tempo in cui la cifra rimane visualizzata prima di uscire, tornare nel loop e visualizzare un altro numero.
 
}

e così via per gli altri numeri.

Questo per farvi vedere come avviene la gestione del multiplexing (ometto come calcolo l'ora e i minuti ecc...).
PROBLEMA: Nelle quattro cifre compare come un alone anche sui caratteri che dovrebbero risultare spenti, quasi come se ci fossero delle piccole correnti di polarizzazione che fanno accendere debolmente i segmenti che dovrebbero essere spenti. Mi viene in mente l'aliasing, ovvero una sovrapposizione tra i vari segnali che dovrebbero pilotare i singoli segmenti. Ma il tempo di delay (2ms) mi sembra comunque una buona scelta: infatti i display non tremolano e l'ora risulta comunque leggibile.
Vorrei chiedervi come posso (e se è possibile) migliorare questa gestione, se avete suggerimenti per cercare, nei limiti del possibile, di rendere l'immagine più nitida possibile eliminando questo problema.
Oppure avere una conferma che è proprio un limite della tecnica multiplexing su questo tipo di applicazioni.
Grazie mille :slight_smile:
Riccardo.

Buonasera,
essendo il tuo primo post, nel rispetto del regolamento, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

gpb01:
Buonasera,
essendo il tuo primo post, nel rispetto del regolamento, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

Mi scuso, ho provveduto! :slight_smile:
In attesa di qualche consiglio :slight_smile:

Se accendi l'anodo successivo con ancora i segmenti comandati della cifra precedente, per il tempo di scrittura della nuova cifra la vecchia sarà leggermente visibile. Siccome le digitalWrite impiegano 5 microsecondi, per aggiornare tutti i segmenti serviranno almeno 35 µs, e l'ultimo per tutto questo tempo avrà "il valore" del corrispondente segmento della cifra precedente.

Soluzione banale: spegni tutti i 4 anodi, aggiorni i segmenti, accendi l'anodo desiderato per 2ms

Claudio_F:
Se accendi l'anodo successivo con ancora i segmenti comandati della cifra precedente, per il tempo di scrittura della nuova cifra la vecchia sarà leggermente visibile. Siccome le digitalWrite impiegano 5 microsecondi, per aggiornare tutti i segmenti serviranno almeno 35 µs, e l'ultimo per tutto questo tempo avrà "il valore" del corrispondente segmento della cifra precedente.

Soluzione banale: spegni tutti i 4 anodi, aggiorni i segmenti, accendi l'anodo desiderato per 2ms

Avevo provato a fare qualcosa del genere in questo modo:

void uno_primo(){
  digitalWrite(1,LOW); //Tutti gli anodi spenti.
  digitalWrite(0,LOW);  
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
 

  digitalWrite(1,HIGH); //Scrive uno nel primo display
  digitalWrite(0,LOW);  // 1,0,12,13 anodo dei display: HIGH display acceso, LOW spento
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);

  digitalWrite(5 , LOW); //Accendo i segmenti di interesse (anodo comune LOW acceso, HIGH spento)
  digitalWrite(6 , HIGH);
  digitalWrite(7 , HIGH);
  digitalWrite(9 , HIGH);
  digitalWrite(10 , HIGH);
  digitalWrite(11 , LOW);
  digitalWrite(4 , HIGH);
  digitalWrite(8 , HIGH);
  delay(2);  //Tempo in cui la cifra rimane visualizzata prima di uscire, tornare nel loop e visualizzare un altro numero
}

Il problema non si è risolto: secondo te è necessario modificare il delay di 2ms oppure spegnere gli anodi in un altro modo?
Grazie mille.. :slight_smile:

Hai spento gli anodi ma poi hai subito riacceso... come non averli spenti :wink:

Claudio_F:
Hai spento gli anodi ma poi hai subito riacceso... come non averli spenti :wink:

Hai ragione! Ecco una correzzione:

void uno_primo(){
   digitalWrite(5 , LOW);
   digitalWrite(6 , HIGH);
   digitalWrite(7 , HIGH);
   digitalWrite(9 , HIGH);
   digitalWrite(10 , HIGH);
   digitalWrite(11 , LOW);
   digitalWrite(4 , HIGH);
   digitalWrite(8 , HIGH);
   digitalWrite(1,HIGH); //Accendo l'anodo di interesse.
   digitalWrite(0,LOW);
   digitalWrite(12,LOW);
   digitalWrite(13,LOW);
   delay(2);
   digitalWrite(1,LOW); //Spengo gli anodi.
   digitalWrite(0,LOW);
   digitalWrite(12,LOW);
   digitalWrite(13,LOW);
   delay(2);
 
}

La situazione è migliorata di molto!
Secondo te i delay vanno bene? Grazie mille.. :slight_smile:

Il secondo delay credo non serva a nulla. Poi visto che gli anodi sono normalmente spenti, basta accendere e spegnere di volta in volta solo quello che interessa.

Claudio_F:
Il secondo delay credo non serva a nulla. Poi visto che gli anodi sono normalmente spenti, basta accendere e spegnere di volta in volta solo quello che interessa.

Perfetto, ho riscritto tutto il codice. Per quanto tempo lasceresti accesa la cifra? Come vedi io ho scelto 2ms,che,facendo un po' di prove, mi è sembrato un buon valore. Grazie mille.. :slight_smile:

Non so come sono le altre temporizzazioni del programma. Come minimo tutte le cifre devono essere accese 50 volte al secondo (massimo 5 ms tra l'accensione di una cifra e di quella successiva), il quanto tempo (rispetto al periodo di off) influisce sulla luminosità. Se così va bene allora va bene.