OUTPUT DIGITALE: Esempio DISPLAY 7 SEGMENTI a 4 ELEMENTI
Per costruire gli esempi proposti è necessario procurarsi un display a 7 segmenti a 4 elementi. Il modello utilizzato è quello a 12 pin. Lo schema dei contatti è il seguente:
I numeri indicano il digit mentre le lettere i segmenti del singolo digit.
Vediamo lo schema dei
collegamenti nel
display a 7 segmenti con una cifra
singola. Tra catodo comune e anodo comune
le
differenze dipendono da come i led sono stati orientati. Nel 7
segmenti ad anodo comune noi pilotiamo direttamente il catodo
(gnd) mentre l’anodo (5V),
che è in comune tra tutti i Led, viene alimentato a tensione costante (Vcc) il
che implica che per far accendere un singolo led dovremo impostare la singola
uscita dell’Arduino a LOW. Viceversa i Led che costituiscono il
7 segmenti a
catodo comune hanno la stessa massa e noi pilotiamo gli anodi il che implica che
per far accendere un Led dovremo impostare l’uscita del pin a HIGH,
per permettere
alla corrente di scorrere.
Ogni segmento viene identificato da una lettera (da A a G più il punto Dp che indica la virgola decimale). Ogni segmento ha il suo pin dedicato che andrà collegato ad Arduino. Sono quindi necessari 8 pin per controllare i segmenti più 1 pin per la terra (nel modello a catodo comune) o per i 5V (nel modello a anodo comune).
Per comporre una lettera o un numero dobbiamo individuare i segmenti che ci occorrono e settarne il loro valore ad HIGH (catodo comune) o LOW (anodo comune) per accenderli.
Nel caso il display utilizzato sia ad anodo comune (e non a catodo) il collegamento va fatto alla 5V e non alla terra! Il segmento si accende quando è impostato a LOW ed è bene mettere delle resistenze (almeno 220 Ohm) per non sovraccaricare i pin di Arduino.
Analizziamo ora il display a 7 segmenti con 4 cifre.
Abbiamo visto che un display a singola cifra ha bisogno di ben 8 connessioni per cui sembra logico pensare che per un display a 4 cifre ne servano 32. In realtà, sfruttando un sistema molto simile a quello che viene definito multiplex, è possibile ridurre il numero di connessioni necessarie a 12 (4 per selezionare la cifra da accendere e 8 per i segmenti).
Questa diminuzione nel numero di pin si paga a livello software: infatti riesce a manovrare le 4 cifre con poche connessioni semplicemente perché “accende e spegne” i singoli digit, tutti in modo molto veloce! Questo, a livello di programmazione, si traduce:
Ecco un esempio di loop():
// ----------------------------------------------------------------- // Definisco la mappatura tra pin e segmenti // ----------------------------------------------------------------- int segA = 6; // Undicesimo PIN del display 7Segment x 4 int segB = 2; // Settimo PIN del display 7Segment x 4 int segC = 10; // Quarto PIN del display 7Segment x 4 int segD = 12; // Secondo PIN del display 7Segment x 4 int segE = 13; // Primo PIN del display 7Segment x 4 int segF = 5; // Decimo PIN del display 7Segment x 4 int segG = 9; // Quinto PIN del display 7Segment x 4 int segDP = 11; // Terzo PIN del display 7Segment x 4 int digit1 = 7; // Dodicesimo PIN - PWM che Accende il primo digit int digit2 = 4; // Nono PIN - PWM che Accende il secondo digit int digit3 = 3; // Ottavo PIN - PWM che Accende il terzo digit int digit4 = 8; // Sesto PIN - PWM che Accende il quarto digit #define DIGIT_ON LOW #define DIGIT_OFF HIGH #define SEGMENT_ON HIGH // Catodo comune #define SEGMENT_OFF LOW #define DISPLAY_BRIGHTNESS 20000 void setup() { // Imposto titti i pin come output pinMode(segA, OUTPUT); pinMode(segB, OUTPUT); pinMode(segC, OUTPUT); pinMode(segD, OUTPUT); pinMode(segE, OUTPUT); pinMode(segF, OUTPUT); pinMode(segG, OUTPUT); pinMode(segDP, OUTPUT); // Pin relativi all'elemento pinMode(digit1, OUTPUT); pinMode(digit2, OUTPUT); pinMode(digit3, OUTPUT); pinMode(digit4, OUTPUT); // Spengo tutti gli elementi digitalWrite(digit1, DIGIT_OFF); digitalWrite(digit2, DIGIT_OFF); digitalWrite(digit3, DIGIT_OFF); digitalWrite(digit4, DIGIT_OFF); } void loop() { lettera('C',1); // Scrivo la lettera sull'i-esimo digit lettera('I',2); lettera('A',3); lettera('O',4); } // Funzioni per scrivere alcuni caratteri (catodo comune) void lettera(char ch, int digit) { // Accendo il digit corrispondente alla lettera da scrivere digitalWrite(digit1, (digit==1) ? DIGIT_ON : DIGIT_OFF); digitalWrite(digit2, (digit==2) ? DIGIT_ON : DIGIT_OFF); digitalWrite(digit3, (digit==3) ? DIGIT_ON : DIGIT_OFF); digitalWrite(digit4, (digit==4) ? DIGIT_ON : DIGIT_OFF); if (ch=='C') // Scrivo la lettera C sul 1^ digit { digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_OFF); digitalWrite(segDP, SEGMENT_OFF); } else if (ch =='I') // Scrivo la lettera I sul 2^ digit { digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); digitalWrite(segDP, SEGMENT_OFF); } else if (ch =='A') { digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); digitalWrite(segDP, SEGMENT_OFF); } else if (ch =='O') { digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_OFF); digitalWrite(segDP, SEGMENT_OFF); } // Piccolo ritardo delayMicroseconds(DISPLAY_BRIGHTNESS); digitalWrite(digit1, DIGIT_OFF); digitalWrite(digit2, DIGIT_OFF); digitalWrite(digit3, DIGIT_OFF); digitalWrite(digit4, DIGIT_OFF); }
Codice Sorgente A
Obiettivo progetto: Utilizzando un display a 7 segmenti composto da 4 elementi (digit) costruire un progetto che consenta di visualizzare il numero di secondi trascorsi dall'attivazione di Arduino.
soluzione: Costruiamo il seguente circuito
Ecco il programma
/* Esempio creato partendo dal codice: "Arduino UNO running 4-digit 7-segment display". http://www.hobbytronics.co.uk/arduino-4digit-7segment di pubblico dominio (meglio beerware: offri una birra all'autore Questo è un esempio per pilotare un display 7 segmenti con 4 elementi senza usare resistenze. Questa tecnica è molto diffusa ma devi sapere che eventuali errori possono portare ad un sovraccarico di corrente con il rischio di bruciare qualche segmento del display (basta porre attenzione al valore di luminosità). */ #define DIGIT_ON LOW // E' un modello a Anodo Comune #define DIGIT_OFF HIGH // ----------------------------------------------------------------- // PIN della fila in basso del display ==> e,d,dp,c,g,4 // ----------------------------------------------------------------- // La parte bassa corrisponde a quella dove ho il punto decimale // La numerazione del modulo "Display a 7 segmenti" con 4 elementi // va da sinistra a destra int segE = 13; // Primo PIN int segD = 12; // Secondo PIN int segDP = 11; // Terzo PIN int segC = 10; // Quarto PIN int segG = 9; // Quinto PIN int digit4 = 8; // Sesto PIN - PWM che Accende il quarto digit // ----------------------------------------------------------------- // PIN della fila in alto del display ==> 1,a,f,2,3,b // ----------------------------------------------------------------- // La numerazione del modulo "Display a 7 segmenti" con 4 elementi // va da sinistra a destra int digit1 = 7; // Dodicesimo PIN - PWM che Accende il primo digit int segA = 6; // Undicesimo PIN int segF = 5; // Decimo PIN int digit2 = 4; // Nono PIN - PWM che Accende il secondo digit int digit3 = 3; // Ottavo PIN - PWM che Accende il terzo digit int segB = 2; // Settimo PIN void setup() { // Imposto titti i pin come output pinMode(segA, OUTPUT); pinMode(segB, OUTPUT); pinMode(segC, OUTPUT); pinMode(segD, OUTPUT); pinMode(segE, OUTPUT); pinMode(segF, OUTPUT); pinMode(segG, OUTPUT); pinMode(segDP, OUTPUT); // Pin relativi all'elemento pinMode(digit1, OUTPUT); pinMode(digit2, OUTPUT); pinMode(digit3, OUTPUT); pinMode(digit4, OUTPUT); // Spengo tutti gli elementi digitalWrite(digit1, DIGIT_OFF); digitalWrite(digit2, DIGIT_OFF); digitalWrite(digit3, DIGIT_OFF); digitalWrite(digit4, DIGIT_OFF); } void loop() { displayNumber(millis()/1000); } void displayNumber(int toDisplay) { #define DISPLAY_BRIGHTNESS 20000 #define SPEGNI 10 // Ogni elemento rimane accesso per 20 millisecondi dopo di che viene spento for (int digit = 4 ; digit > 0 ; digit--) { if (digit==4) digitalWrite(digit4, DIGIT_ON); else if (digit==3) digitalWrite(digit3, DIGIT_ON); else if (digit==2) digitalWrite(digit2, DIGIT_ON); else if (digit==1) digitalWrite(digit1, DIGIT_ON); // Mostra il resto della divisione per 10 sull'elemento posto ad ON MostraSingoloNumero(toDisplay % 10); // Lascia l'elemento ON per una breve frazione di secondo delayMicroseconds(DISPLAY_BRIGHTNESS); // Spegne tutti i segmenti del display selezionato MostraSingoloNumero(SPEGNI); toDisplay /= 10; // Aggiorna il numero dividendolo per 10 (divisione intera) // Disattivo tutti i digit digitalWrite(digit1, DIGIT_OFF); digitalWrite(digit2, DIGIT_OFF); digitalWrite(digit3, DIGIT_OFF); digitalWrite(digit4, DIGIT_OFF); } } // Accende i segmenti specifici per ottenere la corretta // visualizzazione del numero passato come parametro void MostraSingoloNumero(int n) { #define SEGMENT_ON HIGH #define SEGMENT_OFF LOW switch (n) { case 0: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_OFF); break; case 1: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; case 2: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break; case 3: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break; case 4: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 5: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 6: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 7: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; case 8: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 9: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 10: // Tutto spento digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; } }
Lo stesso risultato è ottenibile sfruttando la libreria SevSeg
/* Esempio scritto prendendo spunto da un esempio scritto da Dean Reading. Questo mostra un conta secondi che utilizza la libreria SevSeg */ #define COMMON_ANODE 1 #define COMMON_CATODE 0 // ----------------------------------------------------------------- // Definisco la mappatura tra pin e segmenti // ----------------------------------------------------------------- int segA = 6; // Undicesimo PIN del display 7Segment x 4 int segB = 2; // Settimo PIN del display 7Segment x 4 int segC = 10; // Quarto PIN del display 7Segment x 4 int segD = 12; // Secondo PIN del display 7Segment x 4 int segE = 13; // Primo PIN del display 7Segment x 4 int segF = 5; // Decimo PIN del display 7Segment x 4 int segG = 9; // Quinto PIN del display 7Segment x 4 int segDP = 11; // Terzo PIN del display 7Segment x 4 int digit1 = 7; // Dodicesimo PIN - PWM che Accende il primo digit int digit2 = 4; // Nono PIN - PWM che Accende il secondo digit int digit3 = 3; // Ottavo PIN - PWM che Accende il terzo digit int digit4 = 8; // Sesto PIN - PWM che Accende il quarto digit // Stesse define ma ordinate per PIN del display // int segE = 13; // Primo PIN // int segD = 12; // Secondo PIN // int segDP = 11; // Terzo PIN // int segC = 10; // Quarto PIN // int segG = 9; // Quinto PIN // int digit4 = 8; // Sesto PIN - PWM che Accende il quarto digit // int segB = 2; // Settimo PIN // int digit3 = 3; // Ottavo PIN - PWM che Accende il terzo digit // int digit2 = 4; // Nono PIN - PWM che Accende il secondo digit // int segF = 5; // Decimo PIN // int segA = 6; // Undicesimo PIN // int digit1 = 7; // Dodicesimo PIN - PWM che Accende il primo digit #include "SevSeg.h" // Crea un'istanza dell'oggetto SevSeg sevseg; void setup() { // Inizializzo i PIN sevseg.Begin(COMMON_CATODE,digit1,digit2,digit3,digit4, segA,segB,segC,segD,segE,segF,segG,segDP); // Imposto la luminosità (valore da 0 a 100) sevseg.Brightness(90); } void loop() { // Mostra il valore sevseg.PrintOutput(); // Aggiorna il numero visualizzato. Il secondo argomento corrisponde // alla posizione della virgola. Se metto un valore superiore a 4 riempie // il numero con degli zeri iniziali int Secondi=millis()/1000 % 10000; sevseg.NewNum(Secondi,(byte) 4); }
Per poter utilizzare questo codice è necessario installare la libreria SevSEG disponibile in questo link. Per installarla basta scompattare il file e copiare la cartella prodotta all'interno della cartella contenente le librerie di Arduino (solitamente C:\Program Files\Arduino\libraries). Terminare aggiungendo la cartella appena copiata, mediante il menu "Add Library", all'interno dell'IDE di Arduino
al termine dell'importazione i files vengono ricopiati nella cartella C:\Users\<User>\Documents\Arduino\libraries. Se ci sono problemi nell'installazione occorre svuotare la cartella di libreria appena ricopiata.