Go Down

Topic: [Risolto] Multiplex 3 Display 7-Seg (Read 4 times) previous topic - next topic

ZG84

Nov 24, 2012, 09:06 pm Last Edit: Nov 27, 2012, 09:09 pm by ZG84 Reason: 1
Salve a tutti ragazzi mi chiamo Gianluca.
Sto rispolverando le mie poche conoscenze elettroniche e sto imparando a usare arduino e questo è il primo progetto che sto cercando do portare a termine che è fondamentale per tutti gli altri  :).
Ho realizzato un alimentatore con tensione regolabile 1.2V 27V e volevo integrare un voltmetro tramite Atmega328 in Stand alone con 3 display 7Seg a Catodo Comune.
Inizialmente l'idea era di pilotare i display con 3 integrati 4511decoder/latch/driver bcd - 7 Seg di facile realizzazione ed avrei già finito.
Però, curiosando in giro per il forum e su google, ho sentito parlare del multiplexing.
Siccome sono una "volpe" mi ci sono cimentato e dopo una settimana(lavoro permettendo) non riesco a venirne fuori e sono costretto a chiedervi una mano.

Domanda di curiosità
1- Bisogna comandare i singoli segmenti in sequenza o si possono comandare anche i display(singola cifra) in sequenza? Vantaggi e Svantaggi tra le due opzioni?

io al momento sto comandando le singole cifre
Veniamo al vero problema......

I display mi visualizzano (o almeno dovrebbero) decine unità e decimali

Descrizione Circuito:
I tre display hanno i 7 pin uguali in comune.
Il secondo display ha il segmento del punto comandato con un pin a parte x il momento dopo lo collegherò a 5V.
Ad ogni segmento una resistenza da 680Ohm per limitare la corrente assorbita per segmento a 5mA in modo da non superare i 40mA dei pin di arduino(evitandomi il Transistor npn sul catodo....devo ancora sistemare la documentazione che mi sono procurato per capire come funziona e per calcolare la resistenza di base per l'utilizzo on/off).

Descrizione programma:
Legge la tensione da 0-5volt(ottenuti con partitore di tensione) e la converte da 0 a 30volt,
estrae decine unita e decimali e dopo cerca di visualizzarle sui tre display   =(
Il problema e che impostando Fq (in teoria la velocità del ciclo dei tre display) ad un valore minore di quello dello sketch (Fq =130) non visualizza più nulla.Ora....seguendo un ragionamento logico se io alzo(abbasso Fq) la velocità di aggiornamento dovrei vedere i tre display sempre accesi fissi e non spenti giusto?
Qualcuno con molta più esperienza di me saprebbe spiegarmi dove sbaglio?

Se non sono stato abbastanza chiaro ditemelo pure.
Visto che lo sketch è abbastanza "grezzo" sono ben accetti consigli su come migliorare la struttura, l'ordine,
o se ci sono funzioni che devo ancora imparare per snellire lo sketch.
Tralasciate i vari Serial.print mi servivano per il debug.
La parte dello sketch che "non funziona" inizia da
//---------------
//---------------
MULTIPLEXING
Solo due cose sono infinite: l'universo e la stupidità umana, ma riguardo l'universo ho ancora dei dubbi.

Albert Einstein

ZG84

#1
Nov 24, 2012, 09:09 pm Last Edit: Nov 24, 2012, 11:38 pm by ZG84 Reason: 1
int Vp;                      // Vp= Tensione letta su pin analogico A0
float T;                     // T  = Dichiarata in anticipo spiego dopo serve per i calcoli
int vs;                       //Vs =  stessa cosa di T
                                 
int DT;                       // DT = Decine Tensione
int UT;                       // UT = Unita' Tensione
int dT;                       // dT = Decimali Tensione

                          //Dichiarazione  Varabili per led 7 segmenti
int A=3;               // A corrisponde al segmento a collegato al pin 3
int B=4;               // B corrisponde al segmento b collegato al pin 4
int C=5;               // ecc ecc
int D=6;
int E=7;
int F=8;
int G=9;
int DP=10;                   //questo è il pin che mi abiliterà il punto sul secondo display che sul                                                   
                                  //progetto definitivo colleghero direttamente ai + 5V

int DD=11;                   //DD= Catodo 1°Display => DD acronimo di Display Decine
int DU=12;                   //DU= Catodo 2°Display => DU    ||            Display Unità
int Dd=13;                   //Dd= Catodo 3°Display => Dd     ||            Display Decimali   
long x=0;                     // x= mi servirà dopo + in basso per cercare di far funzionare il         
                                  multiplexing

void setup () {
 
  pinMode(A,OUTPUT);                            //Definisco i pin dove sono collegati
  pinMode(B,OUTPUT);                            //i sette pin dei sette segmenti come uscite
  pinMode(C,OUTPUT);
  pinMode(D,OUTPUT);
  pinMode(E,OUTPUT);
  pinMode(F,OUTPUT);
  pinMode(G,OUTPUT);
  pinMode(DP,OUTPUT);                           //questo è il led che fa il punto del secondo display
  pinMode(DD,OUTPUT);                           //questi ultimi 3 sono i catodi
  pinMode(DU,OUTPUT);
  pinMode(Dd,OUTPUT);
}

void zero () {                                         //da "void zero" a "void nove" sono le funzioni che
  digitalWrite(A, HIGH);                           // richiamerò nel void loop
  digitalWrite(B, HIGH);                           // in queste funzioni stabilisco quali pin
  digitalWrite(C, HIGH);                           //devono essere a 5V e a GND per
  digitalWrite(D, HIGH);                           //visualizzare correttamente la cifra sul display
  digitalWrite(E, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, LOW);
  }
 
void uno () {
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(E, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
  } 
 
void due () {
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(G, HIGH);
  } 
 
void tre () {
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, HIGH);
  }

void quattro () {
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(E, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  }

void cinque () {
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  }

void six () {
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  }

void sette () {
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(E, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
  }

void otto () {
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  }

void nove () {
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  }

void loop () {                                           //Da qui inizia il programma lettura Tensione

                                                               // Conversione da 0-5 a 0-30
  Vp=analogRead(A0);                                // legge la tensione da 0 a 5 su A0
  T =(Vp*(5.0/1023.0))*6;                           // Tensione convertita e *6 in modo da dare un
                                                               //risultato da 0 a 30 Volt
                       
  DT = T/10.0;                     //Formula per ricavare Decine ovvero la cifra che verrà                                   
                                          visualizzata sul 1° display             
   
  if ( DT==0){                        //Formula per ricavare le Unita che verrano visualizzate sul 
  UT = (T-DT)/1.0;                 //2° display
  }
 
  if ( DT==1){                           
  UT = (T-DT)-9/1.0;
  }
 
  if ( DT==2){
  UT = (T-DT)-18/1.0;
  }
 
                                         //Formula per ricavare i Decimale da visualizzare sul 3 display     
  vs=T;                                //Trucchetto per avere da un numero decimale "float T=tensione       
                                         //su a0" un numero int vs da sotrarre in modo da ricavarmi i
   dT = (T-vs)/0.1;                // Decimali da visualizzare sul display

 

//--------------
//--------------
//MULTIPLEXING     

  unsigned long tempo=millis();                              //tempo e uguale a millis
  long Fq=130;                                                      //Fq è La frequenza di aggiornamento
   
                                                //x è il tempo aggiornato a fine ciclo in
                                                //modo da avere sempre valide le funzioni if anche se millis
                                                //continua il conteggio.
  if(tempo-x<Fq){                       //fino a che millis non raggiunge il valore impostato in Fq
  digitalWrite(DD,LOW);              //metto 0v il catodo Display Decine
  digitalWrite(DU,HIGH);              //metto a 5v catodo Display Unita nn essendoci diff.di pot. 
                                                 // il led non si accende
  digitalWrite(Dd,HIGH);               //stessa cosa su Display Decimali
  switch (DT){                              //Switch confronta il numero decimale ricavato con le 
                                                 formule sopra e i case mi richiamano le funzioni "void zero     
                                                  ecc.." dove sono definiti gli stati logici dei pin 
                                                  corrispondenti ai segmenti per la
                                                  visualizzazione delle cifre su display
                                                 i case arrivano fino a tre per le decine
                                                  perchè massimo(molto teorici poco pratici) ho 30 volt.
  case 0:
  zero();
  break;
  case 1:
  uno();
  break;
  case 2:
  due();
  break;
  case 3:
  tre();
  break;}
  }


  if(tempo-x>Fq && tempo-x<Fq*2){                    //uguale a sopra solo che onde evitare bug

// il famoso punto del secondo display
digitalWrite(DP,HIGH);                                     //esegue la funzione quando ha finito di                 
                                                                       //visualizzare le decine sempre per il tempo
                                                                       //impostato in Fq
  digitalWrite(DD,HIGH);
  digitalWrite(DU,LOW);
  digitalWrite(Dd,HIGH);
  switch (UT){
  case 0:
  zero();
  break;
  case 1:
  uno();
  break;
  case 2:
  due();
  break;
  case 3:
  tre();
  break;
  case 4:
  quattro();
  break;
  case 5:
  cinque();
  break;
  case 6:
  six();
  break;
  case 7:
  sette();
  break;
  case 8:
  otto();
  break;
  case 9:
  nove();
  break;}
  }
 
 
  if(tempo-x>=Fq*2 && tempo-x<=Fq*3){                             //stessa funzione per i decimali
  digitalWrite(DD,HIGH);
  digitalWrite(DU,HIGH);
  digitalWrite(Dd,LOW);
 
  switch (dT){
  case 0:
  zero();
  break;
  case 1:
  uno();
  break;
  case 2:
  due();
  break;
  case 3:
  tre();
  break;
  case 4:
  quattro();
  break;
  case 5:
  cinque();
  break;
  case 6:
  six();
  break;
  case 7:
  sette();
  break;
  case 8:
  otto();
  break;
  case 9:
  nove();
  break;}
}
if(tempo-x>=Fq*3 && tempo-x<=Fq*4){          //reimposta la variabile x ponendola uguale
x=tempo;}                                                   //al conteggio millis attuale in modo da rendere   
                                                                  // ancora valide le condizioni negli if al ripetersi
}                                                                 //del ciclo
 

 



Solo due cose sono infinite: l'universo e la stupidità umana, ma riguardo l'universo ho ancora dei dubbi.

Albert Einstein

Giuseppe G.

:smiley-roll:
Ciao ZG84,

intanto, per risponderti, bisognerebbe capire se almeno sei riuscito ad accendere un display, poi uno schizzo dello schema non farebbe male.
Se inserici le descrizioni delle funzioni delle variabili, si comprende meglio lo sketch e le sue funzioni.

Comunque, se sulla seriale hai un feedbak dei dati letti corretti, sei già a buon punto.

I display che usi, dovrebbero essere a catodo comune. Ricorda che per vederli accesi, devi inserire dei piccoli ritardi che mantengano attive le uscite per almeno 50-100ms per display che dovresti aver inserito nello sketch, ed infine, ad ogni segmento inseire una resistenza non inferiore a 220ohm, perchè potresti bruciare i pin del 328.

Io comincerei a far accendere il display dei decimi, legato ad una variabile che và da 0 a 9 senza driver di mezzo come il 4511. (questo potrebbe tornarti utile, quando hai bisogno di pin liberi, in quanto è un decoder BCD da 4 a 7 segmenti il chè vuol dire che se lo dovessi usare, potresti risparmiare 3 pin)

Capito questo, passerei alla visualizzazione completa delle tre cifre e di conseguenza alla visualizzazione della variabile letta. ;)
Un saluto a tutta la comunità.
Giuseppe G.

ZG84

Grazie dell'attenzione giuseppe adesso tolgo un po di Serial.print per renderlo più leggibile e cerco di aggiungere commenti per renderlo di facile comprensione.
col programma sono vicino alla meta (penso)...la lettura della tensione e corretta un po imprecisa verso 1.2Volt  e 27Volt ma da quello che ho letto in giro meglio di cosi senza componenti esterni non si riesce.
ci vorrà un po ma sistemo il post dello sketch.
Solo due cose sono infinite: l'universo e la stupidità umana, ma riguardo l'universo ho ancora dei dubbi.

Albert Einstein

leo72

Se ti vuoi evitare il transistor per ogni cifra e vuoi usare il mutiplexing, puoi dare uno sguardo al mio progetto "Micrologio".
Trovi schema e sketch di un piccolo orologio standalone basato su 328 che comanda un display led a 4 cifre a 7 segmenti in multiplexing con le sole resistenze sugli anodi, senza driver o altri chip esterni.

Go Up