GUIDA ARDUINO 7: DISPLAY 7 SEGMENTI

Nella Settima Parte della Guida verrà Illustrato come Interfacciare uno o più Display 7-segmenti per la Visualizzazione di Numeri o Lettere…

 

 

 
 



 

INTRO

I display 7-segmenti sono componenti passivi che al loro interno racchiudono 8 LED; sette di questi LED sono a forma di segmento e uno a forma di punto, i 7 led a forma di segmento sono disposti in modo tale da formare un numero decimale in base a quale segmento viene acceso.

Ogni LED ha due contatti, l’anodo e il catodo. Questo tipo di dispositivo ha però 9 pin, però si hanno 8 LED con due contatti ognuno. Quindi tutti i LED hanno un contatto in comune (si connettono o tutti gli anodi o i catodi insieme e si connettono ad un unico pin) e l’altro contatto è disponibile all’esterno uno per ogni LED.  Il display sette segmenti viene definito ad anodo comune o a catodo comune in base a quale contatto i led hanno tutti in comune, o l’anodo o il catodo. Se si ha l’anodo in comune vi sarà un pin con gli anodi e 8 pin con 8 catodi in modo tale da accendere i segmenti desiderati. Stesso discorso per i display a catodo comune ma con i catodi tutti insieme e gli anodi con un pin individuale.

I display possono essere composti da una singola cifra come quelli mostrati sopra oppure possono avere fino a 4 e più cifre. Supponiamo un display a 2 cifre con catodo comune ad esempio; dovrebbe avere 2 contatti per i catodi in comune e poi gli 8 anodi della prima cifra e 8 anodi per la seconda cifra in totale 18 pin. La cosa si complica molto con tre o 4 cifre. Quindi i display 7-segmenti a più di una cifra hanno o l’anodo o il catodo connesso insieme per ogni cifra e poi tutti i segmenti nella stessa posizione di tutte le cifre sono connessi insieme. Quindi un display a 3 cifre avrà 1 pin per i segmenti “a”, uno per i “b”, uno per i “c”, uno per i “d”, uno per i “e”, uno per i “f”, uno per i “g” poi un pin per tutti i punti (chiamati dp ovvero dot point) e poi avrà 3 pin per i 3 contatti in comune delle cifre (anodo o catodo) per un totale di 11 contatti.

Per avere un numero a più di una cifra nel caso di display 7-segmenti con questa connessione si usa la tecnica TDM ovvero Time Division Multiplexing, si invia ai pin dei segmenti il segnale per avere il numero e una per volta si attiva la cifra, ad esempio: Se abbiamo il numero “962” si invia ai pin dei segmenti prima i livelli logici adeguati per visualizzare “2” e si attiva tramite il contatto comune della prima cifra quest’ultima. In questo modo si hanno 2 cifre spente e la cifra delle unità che rappresenta “2”, poi si attiva la seconda cifra e si invia ai pin dei segmenti il segnale per visualizzare “6” e così anche per la terza cifra, poi questo processo si ripete ricominciando dalla prima cifra. È noto che se un led lampeggia velocemente gli occhi lo vedono come sempre accesso, quindi iterando il processo TDM sul display a 3 cifre con una velocità elevata si vedrà il numero “962” per intero.

Questo è una tipica connessione per display 7-Segmenti con più di una cifra. I Pin dei segmenti sono connessi tutti insieme internamente o esternamente e vi è un resistore di protezione da 330 Ohm per ognuno, invece ai pin in comune (in questo caso i catodi) vi è connesso un transistor che porta a massa la corrente dei segmenti chiudendo il circuito. Quindi in base a quale transistor è attivo si illumina la cifra corrispondente. Invece dei transistor si può usare un buffer, se invece ho un display ad anodo comune, collego il pin comune a VCC tramite un transistor di tipo PNP o un buffer. Bisogna ricordarsi che i transistor NPN sono accesi se sulla base vi è una tensione positiva, mentre i PNP se vi è una tensione negativa. Se la corrente assorbita dal display è molto bassa (minore di 10mA con tutti i segmenti accesi) non è necessario il transistor o il buffer.

 





 
COMANDO DI UN SINGOLO DISPLAY 7-SEGMENTI

Nel primo esempio andremo a controllare un display 7-segmenti a singola cifra e andremo a vedere come visualizzare i numeri da 0 a 9. Andremo prima a realizzare la funzione usando i pin standard di Arduino, e poi andremo a realizzare la funzione controllando direttamente le porte del microcontrollore.

Nel primo caso bisogna creare una matrice che contenga la configurazione delle uscite per avere opportuni numeri accendendo e mantenendo spenti i segmenti. In particolare si va ad abbinare il segmento “a” al pin più basso, il segmento “b” al pin successivo e così via. Bisogna poi inizializzare ingressi e uscite e configurare le uscite secondo la matrice, con un valore per volta.

Come esempio per visualizzare tutti i numeri si usa un contatore da 0 a 9. Il codice è il seguente:

byte s_seg_cat_com[10][7] = {{1,1,1,1,1,1,0},    // = 0
                             {0,1,1,0,0,0,0},    // = 1
                             {1,1,0,1,1,0,1},    // = 2
                             {1,1,1,1,0,0,1},    // = 3
                             {0,1,1,0,0,1,1},    // = 4
                             {1,0,1,1,0,1,1},    // = 5
                             {1,0,1,1,1,1,1},    // = 6
                             {1,1,1,0,0,0,0},    // = 7
                             {1,1,1,1,1,1,1},    // = 8
                             {1,1,1,1,0,1,1}};   // = 9

byte s_seg_an_com[10][7] = {{0,0,0,0,0,0,1},   // = 0
                           {1,0,0,1,1,1,1},    // = 1
                           {0,0,1,0,0,1,0},    // = 2
                           {0,0,0,0,1,1,0},    // = 3
                           {1,0,0,1,1,0,0},    // = 4
                           {0,1,0,0,1,0,0},    // = 5
                           {0,1,0,0,0,0,0},    // = 6
                           {0,0,0,1,1,1,1},    // = 7
                           {0,0,0,0,0,0,0},    // = 8
                           {0,0,0,0,1,0,0}};   // = 9
                                                           
void setup() {                
  pinMode(0, OUTPUT);    //Pin 0 segmento a
  pinMode(1, OUTPUT);    //Segmento b
  pinMode(2, OUTPUT);    //Segmento c
  pinMode(3, OUTPUT);    //Segmento d
  pinMode(4, OUTPUT);    //Segmento e
  pinMode(5, OUTPUT);    //Segmento f
  pinMode(6, OUTPUT);    //Segmento g
  pinMode(7, OUTPUT);    //Segmento h
}

    
void s_seg_cifra(byte numero) {                             //funzione scrittura su display
  byte pin = 0;                                             //primo pin utilizzato
  for (byte segmento = 0; segmento < 7; segmento ++) {      //Scansiona tutti i segmenti
    digitalWrite(pin, s_seg_an_com[numero][segmento]);      //Scrivi il valore dei segmenti (anodo o catodo com)
    ++pin;                                                  //Incrementa il pin
  }
}

void loop() {                                               //Ciclo infinito 
   for (byte conteggio = 0; conteggio < 10; conteggio ++) {  //Conta da 0 a 9
     s_seg_cifra(conteggio);                                  //richiama la funzione
     delay(1000);                                             //Attendi un secondo
   }
}

Prima di tutto si va ad inizializzare la matrice “s_seg_cat_com” e “s_seg_an_com” rispettivamente le matrici per i display a catodo comune ed ad anodo comune. Nel setup vengono inizializzate 7 uscite.

Nella funzione “s_seg_cifra” si va a inizializzare il pin da dove si inizia la connessione, si scansiona la matrice e si scrivono le uscite. La funzione riceve il numero da visualizzare. Ovvero noi siamo partiti da pin 0 quindi inizializziamo “pin = 0”.  Nel ciclo for si va a scansionare la matrice e in particolare si va a scansionare la linea corrispondente al numero da visualizzare e si scansiona uno per volta il bit dell’uscita andando a scriverla al pin corrispondente.

Nel ciclo “loop” con un for che parte da 0, si incrementa di uno ogni secondo e si ferma a 9, realizzando un conteggio. Il valore del conteggio viene inviato alla funzione di visualizzazione.

Il codice invece per la scrittura, usando direttamente i registri del microcontrollore montato su breadboard è il seguente:

byte s_seg_kat_co[10] = {B00111111,    // = 0
                         B00000110,    // = 1
                         B01011011,    // = 2
                         B01001111,    // = 3
                         B01100110,    // = 4
                         B01101101,    // = 5
                         B01111101,    // = 6
                         B00000111,    // = 7
                         B01111111,    // = 8
                         B01101111};   // = 9
byte s_seg_an_com[10] = {B01000000,    // = 0
                         B01111001,    // = 1
                         B00100100,    // = 2
                         B00110000,    // = 3
                         B00011001,    // = 4
                         B00010010,    // = 5
                         B00000010,    // = 6
                         B01111000,    // = 7
                         B00000000,    // = 8
                         B00010000};   // = 9

                                                           
void setup() {                
  DDRD=B11111111;           //PortD uscite (pin arduino uno r3 0,1,2,3,4,5,6,7)
}
  
void s_seg_cifra(byte numero) {                             //funzione scrittura su display
  PORTD = s_seg_an_com[numero];                         //Scrivi il valore del display su PORTD
}                                           
 
void loop() {                                               //Ciclo infinito 
  for (byte conteggio = 0; conteggio < 10; conteggio ++) {  //Conta da 0 a 9
    s_seg_cifra(conteggio);                                 //richiama la funzione
    delay(1000);                                            //Attendi un secondo
  }
}

Invece della matrice si usa un vettore con i 10 elementi dei 10 numeri da visualizzare e si crea un vettore per i display ad anodo comune ed a catodo comune.  DDRD è il registro che seleziona se avere ingressi o uscite e si inizializza tutti a 1 così saranno tutti uscite.

Questa volta la funzione “s_seg_cifra” riceve semplicemente il numero da visualizzare e va a modificare il valore del registro PORTD (ovvero le uscite) con il valore da visualizzare indicato alla posizione del numero nel vettore.

Anche in questo caso si usa un conteggio da 0 a 9 come esempio. Lo schema è il seguente:

Il display 7 segmenti ha i segmenti in ordine (a,b,…,g) connessi come indicato nello sketch, ovvero da 0 a 6 con il segmento “a” connesso al pin 0 e così via. Vi è una resistenza di protezione per ogni segmento in modo tale che il LED associato al segmento non si bruci. Il valore del resistore dipende dalla corrente, solitamente nei display 7 segmenti vanno bene circa 5mA, considerando che la caduta è di circa 2V e l’alimentazione 5V avrò Iled=(5-2)/470 = 6mA che è un valore opportuno. Se il display 7 segmenti non è ben illuminato bisogna ridurre questo valore, ad esempio a 330 Ohm, se invece è troppo luminoso bisogna alzare questo valore a 560 Ohm.  Il pin in comune ovvero l’anodo viene connesso all’uscita 5V di Arduino nelle porte “POWER”.

Per il valore della resistenza del resistore di protezione sui segmenti visitate la guida sui diodi LED.

 

COMANDO PER DISPLAY 7-SEGMENTI CON DUE O PIÙ CIFRE

Come detto nell’introduzione, per pilotare un display 7-segmenti, con più di una cifra, bisogna usare una tecnica TDM e accendere una cifra per volta velocemente. Questo refresh va eseguito ogni 50ms circa, quindi quando si usano display di questo tipo i codici e le istruzioni devono essere veloci per poter visualizzare il valore su display senza che esso si spenga.

Arduino mette a disposizione una libreria molto rapida e completa per la gestione dei display 7-segmenti a più di una cifra. Il nome di questa libreria è “SevSeg” e la versione attuale è la 3.3.0, scaricabile ed istallabile direttamente dall’IDE di Arduino come mostrato nella guida precedente.

Iniziamo ad illustrare come funziona l’inizializzazione di questa libreria. Bisogna fornire alla funzione di setup il numero di cifre, dove è collegato l’anodo in comune o il transistor oppure il buffer usato per pilotarlo, bisogna fornire poi i pin dove sono connessi i segmenti, bisogna indicare se si usa un resistore sui segmenti o no, se il display è ad anodo comune o catodo, e infine bisogna dire se si vuole che gli 0 vengano visualizzati e se aggiornare il valore del display con un certo ritardo o no. Inoltre sempre tra le inizializzazioni si può scegliere l’intensità del display. Le stringhe di configurazioni sono le seguenti:

  byte cifre = "numero di cifre";                       //Numero di cifre (2,3,4,5...)
  byte pin_cifre[] = {"cifra1","cifra2","cifra3" };     //Dipende dal tipo di arduino usato 
  byte pin_seg[] = {"a","b","c","d","e","f","g","DP"};  //Dove connetto i pin dei segmenti (a,b,c,..,g,DP)
  bool resistore = "true/false";                        //valore true se resistori su segmenti, false altrimenti
  byte connessione = "tipo di connessione";             //vedi lista sottostante
  bool ritardo = "true/false";                          //valore true aggiorna il display dopo un certo delay
  bool zeri = "true/false";                             //true non mostra gli 0 prima del numero, false mostra gli 0 (009)

  sevseg.begin(Connessione, cifre, pin_cifre, pin_seg, resistore, ritardo, zeri);     //Inizializzazione
   sevseg.setBrightness("valore da 0 a 100");           //Luminosità spento, 100 massima

La prima variabile contiene il numero delle cifre, la seconda è un vettore con dimensione uguale alle cifre e contiene i pin dove sono connesse le cifre dalla cifra delle unità in poi, poi vi è un vettore con 8 elementi dove sono indicati i pin dei sette segmenti e del punto, poi vi è un booleano vero o falso e dipende dall’hardware usato, ovvero se uso i resistori sui segmenti o no.

La variabile “connessione” indica come viene connesso il catodo comune e si hanno le seguenti possibilità:

  • COMMON_CATHODE: se il display è a bassa corrente (1mA circa per ogni segmento) può essere connesso direttamente il pin in comune tra i segmenti al microcontrollore. Questa stringa indica che connetto direttamente i catodi in comune direttamente ai pin pre-indicati.
  • COMMON_ANODE: simile alla precedente stringa indico però questa volta che il display è ad Anodo comune e connetto direttamente gli anodi ai pin indicati senza transistor o buffer.
  • N_TRANSISTORS: Se il diplay ha i segmenti con corrente alta (5mA ad esempio) e tutti i segmenti sono accesi, il pin in comune assorbe una corrente molto alta che brucerebbe il microcontrollore (40mA e Arduino ne sopporta al massimo 20mA). Se ho un display a catodo comune non connetto i catodi direttamente ai pin di Arduino ma connetto il pin di Arduino della cifra alla base di un transistor NPN con una resistenza da 1KOhm, connetto l’emettitore a massa e il collettore al catodo del display. Se uso questa connessione indico “N_TRANSISTORS” nella variabile “connessione”.
  • P_TRANSISTORS: stesso discorso fatto in precedenza ma questa volta si usa questa connessione con display ad Anodo comune e transistor PNP. Connetto il pin di Arduino della cifra alla base di un transistor PNP con una resistenza da 1KOhm, connetto l’emettitore alla tensione positiva 5V e il collettore all’anodo del display.

Le altre due modalità (NP_COMMMON_CATHODE, NP_ANODE_CATHODE) sono illustrate in modo poco chiaro però non vengono utilizzate.

Poi vi sono due booleani, il primo serve per dire se inserire un delay nel ciclo di refresh del display (scorrimento delle tre cifre) e l’ultimo booleano serve a dire se accendere gli zeri a sinistra del numero oppure no. Questo vuol dire che se ho il numero 47 sul display si vedrà 047 se ho usato FALSE oppure lo zero spento e solo 47 se uso TRUE (FALSE -> 089, 670, 012, 010, 001e 007 ad esempio oppure TRUE -> 89, 100, 89, 1, 4 con le altre cifre spente).

Con la stringa “sevseg.begin()” si vanno a inserire tutte le variabili con la configurazione nella funzione di inizializzazione della libreria. “sevseg.setBrightness(numero da 1 a 100);” si va a regolare la luminosità con una tecnica PWM sul display  con numeri bassi si ha una luminosità bassa con numeri alti si ha più luminosità e con 100 è acceso sempre, senza PWM, al massimo della luminosità.

Per scrivere i valori sul display si usano le seguenti stringhe:

void loop() {
    sevseg.setChars(235);       //Mostra il valore 235
    sevseg.refreshDisplay();    //Attiva TDM
     
    sevseg.setChars("235");     //Mostra il valore 235
    sevseg.refreshDisplay();    //Attiva TDM

    sevseg.setNumber(314,2);    //Mostra il valore 3.14 
    sevseg.refreshDisplay();

    valore = 3.14;              //Valore = 3.14

    sevseg.setNumber(314,2);    //Mostra il valore 31.4
    sevseg.refreshDisplay();    //Aggiorna display
}



Nel primo caso si mostra 235, nel secondo caso sempre 235 ma in formato stringa, nel terzo caso si scrive il valore 3.14 e in particolare si invia il valore intero, senza punto e poi con il numero 2 si indica dopo quale cifra inserire il punto. Nell’ultimo caso si inizializza il valore a 3.14, quindi numero con le virgole, ma inviando questo valore alla funzione per visualizzare su display sette segmenti, non viene mostrato il punto, ma si mostra il punto dove indica dal numero dopo la virgola nella parentesi della funzione.

Un codice completo è il seguente:

#include "SevSeg.h"     //Versione 3.3
SevSeg sevseg; //Instantiate a seven segment controller object
int valore;

void setup() {
  byte numDigits = 3;                          //Numero di cifre
  byte digitPins[] = {8,9,10};                 //Dove connetto i pin in comune delle cifre
  byte segmentPins[] = {0,1,2,3,4,5,6,7};      //Dove connetto i pin dei segmenti (a,b,c,..,g,DP)
  bool resistorsOnSegments = true;             //Resistore per ogni segmento
  byte hardwareConfig = COMMON_ANODE;          //Anodo comune
  bool updateWithDelays = true;               //????
  bool leadingZeros = false;                   //Use 'true' if you'd like to keep the leading zeros

  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros);
   sevseg.setBrightness(100);

}

void loop() {
    sevseg.setChars(235);       //Mostra il valore 235
    sevseg.refreshDisplay();    //Attiva TDM

    delay(1000);
     
    sevseg.setNumber(314,2);    //Mostra il valore 3.14 
    sevseg.refreshDisplay();
    
    delay(1000);

    valore = 3.14;              //Valore = 3.14

    sevseg.setNumber(314,2);    //Mostra il valore 31.4
    sevseg.refreshDisplay();    //Aggiorna display
    
    delay(1000);
}



Per quanto riguarda lo schema, si hanno 3 possibilità, a connessione diretta o con buffer di corrente (byte di configurazione Common_Anode o Common_Cathode) o con transistor NPN con collettore al pin comune del display e emettitore a massa o con transistor PNP sempre con connessione come visto prima (byte di configurazione N_TRANSISTORS nel primo caso P_TRANSISTORS nel secondo).

Gli schemi con connessione diretta e con transistor NPN sono i seguenti:

Nel primo caso la corrente dei segmenti viene tutta assorbita dal microcontrollore, non deve superare quindi i 20mA e si consiglia di usare resistori di protezione con valore maggiore a 1KOhm. Se la luminosità è troppo debole bisogna usare dei buffer con ingresso connesso all’uscita di Arduino, l’uscita ai pin di anodo comune o catodo del display e l’alimentazione sempre a 5V.

Se non si dispone di buffer si può usare la soluzione a transistor. In figura si hanno tre transistor 2N2222 ma si possono usare anche i BC547, i 2N3904 o qualsiasi altro transistor. La resistenza da 1KOhm tra l’uscita di Arduino e la base serve come protezione, per evitare che Arduino e il transistor si brucino.

Se si aveva un display 7 segmenti ad anodo comune bisognava usare 3 transistor PNP (ad esempio i BC558) con la base sempre connessa all’uscita di Arduino con un resistore di protezione, l’emettitore a 5V e il collettore al pin in comune del display.

 

DOWNLOAD

Potete scaricare la simulazione del circuito con PROTEUS e gli Sketch compilati per l’IDE di Arduino al seguente LINK!!!



 

[Voti Totali: 0 Media Voti: 0]
Segui la Nostra Pagina Facebook: Facebook

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *