OUTPUT DIGITALE: Esempio DISPLAY 7 SEGMENTI (versione 17/05/2017)
Per costruire gli esempi proposti è necessario procurarsi un display a 7 segmenti.
Vediamo come funziona un display a 7 segmenti con una cifra singola. Esistono diversi tipi di display a 7 segmenti. Le differenze principali tra un modello e l’altro riguardano:
Tra catodo comune e anodo comune
le
differenze dipendono essenzialmente da come internamente i led sono stati orientati. Nella
prima tutti i catodi dei LED sono collegati alla
MASSA mediante i piedini 3 e 8. Pertanto i LED vengono accesi se il loro anodo (+) viene
collegato all’1 logico (tensione). Nell'anodo comune i pin comuni (3 e 8) sono
collegati a tutti gli anodi pertanto vanno collegati al positivo
dell’alimentazione. I LED si accendono quando il loro catodo viene
collegato allo 0 logico (massa).
Quindi 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 tutti la stessa massa
per cui occorre agire sugli anodi il che implica che
per far accendere un Led dovremo impostare l’uscita del pin di arduino a HIGH,
consentendo
alla corrente di scorrere.
Le 2 tipologie si distinguono solitamente per la presenza della lettera A in quelli ad anodo comune e della C in quelli a catodo comune, come mostrato nella immagine seguente (tale regola non è sempre vera: il display da me utilizzato per questo progetto è siglato con la lettera A ma si tratta di un modello a catodo comune!):
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. Il segmento si accende quando è impostato a LOW ed è bene mettere delle resistenze (almeno 220 Ohm) per non sovraccaricare i pin di Arduino.
Codice Sorgente A
Obiettivo progetto: Utilizzando un singolo display a 7 segmenti costruire un progetto che consenta di visualizzare in sequenza, ogni secondo, i caratteri contenuti nella parola "CIAO".
soluzione: Costruiamo il seguente circuito utilizzando un display a CATODO COMUNE
Inseriamo il presente programma nell'IDE di Arduino
/* ---------------------------------------------------------------------------- Esempio creato partendo dal codice sul sito: https://studioarduino.wordpress.com/2013/05/22/approfondimento-display-7-segmenti/ * ----------------------------------------------------------------------------- */ // Definisco la mappatura tra pin e segmenti int segDP = 4; // Quinto PIN del display 7Segment : PIN 7SEGMENT PIN ARDUINO int segC = 5; // Quarto PIN del display 7Segment : int segD = 6; // Secondo PIN del display 7Segment : -9A- -10- int segE = 7; // Primo PIN del display 7Segment : 7F | | 10B 9| |11 int segG = 8; // Sesto PIN del display 7Segment : |-6G-| |--8-| int segF = 9; // Settimo PIN del display 7Segment : 1E | | 4C 7| |5 int segA = 10; // Nono PIN del display 7Segment : -2D- .5DP --6- .4 int segB = 11; // Decimo PIN del display 7Segment void setup() { pinMode(segA, OUTPUT); pinMode(segB, OUTPUT); pinMode(segC, OUTPUT); pinMode(segD, OUTPUT); pinMode(segE, OUTPUT); pinMode(segF, OUTPUT); pinMode(segG, OUTPUT); pinMode(segDP, OUTPUT); } void loop() { lettera_C(); delay(1000); lettera_I(); delay(1000); lettera_A(); delay(1000); lettera_O(); delay(1000); } // Funzioni per scrivere alcuni caratteri (catodo comune) void lettera_C() { digitalWrite(segA, HIGH); digitalWrite(segB, LOW); digitalWrite(segC, LOW); digitalWrite(segD, HIGH); digitalWrite(segE, HIGH); digitalWrite(segF, HIGH); digitalWrite(segG, LOW); digitalWrite(segDP, LOW); } void lettera_I() { digitalWrite(segA, LOW); digitalWrite(segB, HIGH); digitalWrite(segC, HIGH); digitalWrite(segD, LOW); digitalWrite(segE, LOW); digitalWrite(segF, LOW); digitalWrite(segG, LOW); digitalWrite(segDP, LOW); } void lettera_A() { digitalWrite(segA, HIGH); digitalWrite(segB, HIGH); digitalWrite(segC, HIGH); digitalWrite(segD, LOW); digitalWrite(segE, HIGH); digitalWrite(segF, HIGH); digitalWrite(segG, HIGH); digitalWrite(segDP, LOW); } void lettera_O() { digitalWrite(segA, HIGH); digitalWrite(segB, HIGH); digitalWrite(segC, HIGH); digitalWrite(segD, HIGH); digitalWrite(segE, HIGH); digitalWrite(segF, HIGH); digitalWrite(segG, LOW); digitalWrite(segDP, LOW); }
Codice Sorgente B
Obiettivo progetto: Utilizzando un singolo display a 7 segmenti e un pushbutton costruire un progetto che permetta di visualizzare sul display il conteggio dei click in esadecimale. Arrivato al 15 click (F) il conteggio deve riprendere da zero.
soluzione: Costruiamo il seguente circuito utilizzando un display a CATODO COMUNE
La soluzione è rappresentata dal seguente programma
/* ---------------------------------------------------------------------------- Esempio che realizza un counter mediante un display a 7 segmenti e un push button * ----------------------------------------------------------------------------- */ // Definisco la mappatura tra pin e segmenti byte segDP = 4; // Quinto PIN del display 7Segment : PIN 7SEGMENT PIN ARDUINO byte segC = 5; // Quarto PIN del display 7Segment : byte segD = 6; // Secondo PIN del display 7Segment : -9A- -10- byte segE = 7; // Primo PIN del display 7Segment : 7F | | 10B 9| |11 byte segG = 8; // Sesto PIN del display 7Segment : |-6G-| |--8-| byte segF = 9; // Settimo PIN del display 7Segment : 1E | | 4C 7| |5 byte segA = 10; // Nono PIN del display 7Segment : -2D- .5DP --6- .4 byte segB = 11; // Decimo PIN del display 7Segment byte pushButton = 3; // Il push button e' connesso al pin digitale 3 byte conta=0; // Contatore const bool commonAnode=false; // False se è a Catodo comune static const byte pinArray[] = {segA, segB, segC, segD, segE, segF, segG }; // Le sequenze sottostanti indicano quali segmenti devono essere illuminati // per ogni digit esadecimale indicato static const byte HexCodeMap[] = { // Segmenti: ABCDEFG - mappa del 7-segment B00111111, // 0 "0" AAA B00000110, // 1 "1" F B B01011011, // 2 "2" F B B01001111, // 3 "3" GGG B01100110, // 4 "4" E C B01101101, // 5 "5" E C B01111101, // 6 "6" DDD B00000111, // 7 "7" B01111111, // 8 "8" B01101111, // 9 "9" B01110111, // 65 'A' B01111100, // 66 'b' B00111001, // 67 'C' B01011110, // 68 'd' B01111001, // 69 'E' B01110001 // 70 'F' }; // Funzione che mostra la cifra "number" sul display void ScriveCifra(byte number) { byte dataTmp = HexCodeMap[number]; for (byte c = 0; c < 7; c++, dataTmp = dataTmp >> 1) { digitalWrite(pinArray[c], commonAnode ? !(dataTmp & 0x01) : dataTmp & 0x01); } } void setup() { for (byte set=0; set<7; set++) pinMode(pinArray[set],OUTPUT); pinMode(segDP, OUTPUT); pinMode(pushButton, INPUT); ScriveCifra(conta); // mostro lo 0 (valore iniziale) } void loop() { static int precbuttonState=-1; // Variabile statica per memorizzare il precedente stato // Legge lo stato sul PIN 2 int buttonState = digitalRead(pushButton); // Se premo il pushbutton aumento il contatore e lo visualizzo if ( (buttonState!=precbuttonState) && (buttonState==1) ) { conta++; if (conta == 16) conta=0; ScriveCifra(conta); } precbuttonState=buttonState; delay(100); // ritardo di un decimo tra una lettura e la successiva (per stabilità) }
Codice Sorgente C
Obiettivo progetto: Costruire un programma che mostra in sequenza, ogni secondo, i numeri da 0 a 9. Il programma deve utilizzare la seguente libreria SevSeg.
Soluzione: Dobbiamo modificare il circuito rispetto al precedente poiché la libreria appena citata utilizza i pin di Arduino per selezionare quale display a 7 segmenti pilotare tra gli eventuali n collegati. Utilizzeremo a tale scopo il pin digitale 12 che colleghiamo al pin 3 o 8 (massa comune) del modulo a CATODO COMUNE
La soluzione è rappresentata dal seguente programma
#include <SevSeg.h> /* ---------------------------------------------------------------------------- Esempio creato partendo dagli esempi forniti con la libreria sevseg. Questo esempio mostra come utilizzare la libreria SevSeg con un display a 1 digit. * ----------------------------------------------------------------------------- */ // Definisco la mappatura tra pin e segmenti byte segDP = 4; // Quinto PIN del display 7Segment : PIN 7SEGMENT PIN ARDUINO byte segC = 5; // Quarto PIN del display 7Segment : byte segD = 6; // Secondo PIN del display 7Segment : -9A- -10- byte segE = 7; // Primo PIN del display 7Segment : 7F | | 10B 9| |11 byte segG = 8; // Sesto PIN del display 7Segment : |-6G-| |--8-| byte segF = 9; // Settimo PIN del display 7Segment : 1E | | 4C 7| |5 byte segA = 10; // Nono PIN del display 7Segment : -2D- .5DP --6- .4 byte segB = 11; // Decimo PIN del display 7Segment SevSeg sevseg; // script alternativo (A) // byte conta; // unsigned long timer; void setup() { byte numDigits = 1; // Questa libreria puo' gestire anche più display a 7-segmenti in serie byte digitPins[] = {12}; byte segmentPins[] = {segA, segB, segC, segD, segE, segF, segG, segDP }; bool resistorsOnSegments = false; // 'false' significa che le resistenze sono sui pin indicati in digitPins byte hardwareConfig = COMMON_CATHODE; // valori ammessi COMMON_ANODE - COMMON_CATHODE bool updateWithDelays = false; // Default. Raccomandato bool leadingZeros = false; sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros); sevseg.setBrightness(0); // script alternativo (A) // conta=0; // timer = millis(); } void loop() { // L'inizializzazione di timer e conta viene eseguita solo al primo loop static unsigned long timer = millis(); static int conta = 0; if (millis() >= timer) { conta++; timer += 1000; if (conta == 10) conta=0; sevseg.setNumber(conta, 1); } // script alternativo (A) // if (millis() - timer>1000) // { // if (conta>=10) conta=0; // sevseg.setNumber(conta); // conta++; // timer = millis(); // } sevseg.refreshDisplay(); }
Facciamo ora delle precisazioni sul funzionamento di alcune istruzioni presenti nella libreria SevSeg:
void SevSeg::begin(byte
hardwareConfig, byte numDigitsIn, byte digitPinsIn[],byte segmentPinsIn[], bool
resOnSegmentsIn,
bool updateWithDelaysIn, bool leadingZerosIn):
inizializza il modulo a 7-segmenti specificando:
hardwareConfig => la tipologia di display: catodo comune o anodo comune
numDigitsIn => il numero di display a 7 segmenti connessi
digitPinsIn[] => l'array contenente i pin di Arduino utilizzati per selezionare il display da pilotare tra gli numDigitsIn connessi
segmentPinsIn[] => l'array contenente i pin di Arduino associati ai singoli segmenti di un generico display a 7 segmenti. La sequenza dei pin presente in ogni elemento dell'array è associata in ordine ai segmenti: Dp G F E D C B A {verificata utilizzando le istruzioni: byte AllPinOn[1]={ B11111101 }; sevseg.setSegments(AllPinOn); }
resOnSegmentsIn => I display usano i LED per cui è opportuno utilizzare delle resistenze di limitazione di corrente (ad esempio da 330 ohm) in serie con i pin di Arduino. Se si mettono le resistenze sui pin di segmento (indicati in segmentPinsIn) bisogna impostare resistorsOnSegments a true altrimenti se sono collocate sui pin indicati in digitPinsIn occorre inizializzarla a false.
updateWithDelaysIn => Se impostato a true utilizza il vecchio metodo di update in vigore nella release precedente a quella del 2017. Quella tecnica impegnava il processore con funzioni come delayMicroseconds(attesa in funzione di setBrightness). Si consiglia pertanto di porre tale paramatro a false.
leadingZerosIn => nei display multipli, completa con degli zeri iniziali le cifre mancanti
void SevSeg::setNumber(tipo numerico numToShow, char decPlaces, bool hex): imposta i pin dei segmenti dell'i-esimo display attivato in modo che con l'istruzione refreshDisplay() si illuminino solo i led associati al numero numToShow da visualizzare.
void SevSeg::setChars(char str[]): imposta i pin dei segmenti dell'i-esimo display attivato in modo che con l'istruzione refreshDisplay() si illuminino solo i led associati all'i-esimo carattere della stringa str da visualizzare. La stringa può essere lunga tanti caratteri quanti sono i blocchi del display multiplo a 7-segmenti.
void SevSeg::setSegments(byte segs[]) imposta i pin dei segmenti dell'i-esimo display attivato in modo che con l'istruzione refreshDisplay() si illuminino solo i segmenti associati ai bit ad 1 della mappa di bit registrata in segs[i]. Gli elementi della mappa di bit in segs[i] sono associati alla seguente sequenza di segmenti: A B C D E F G Dp
void SevSeg::blank(void): imposta i pin dei segmenti in modo che con l'istruzione refreshDisplay() si spengano tutti i led del display
void SevSeg::setBrightness(int brightness): aumenta la luminosità (da 0%a 100%) dei led incrementando la durata di accensione dei led nella funzione refreshDisplay().
void SevSeg::refreshDisplay(): illumina i segmenti attivati in sequenza secondo lo schema illustrato in figura
come si può verificare caricando il seguente programma:
#include <SevSeg.h> // Definisco la mappatura tra pin e segmenti byte segDP = 4; // Quinto PIN del display 7Segment : PIN 7SEGMENT PIN ARDUINO byte segC = 5; // Quarto PIN del display 7Segment : byte segD = 6; // Secondo PIN del display 7Segment : -9A- -10- byte segE = 7; // Primo PIN del display 7Segment : 7F | | 10B 9| |11 byte segG = 8; // Sesto PIN del display 7Segment : |-6G-| |--8-| byte segF = 9; // Settimo PIN del display 7Segment : 1E | | 4C 7| |5 byte segA = 10; // Nono PIN del display 7Segment : -2D- .5DP --6- .4 byte segB = 11; // Decimo PIN del display 7Segment SevSeg sevseg; // Creo un'istanza dell'oggetto che controlla il display a 7 segmenti void setup() { byte numDigits = 1; // Questa libreria puo' gestire anche più display a 7-segmenti in serie byte digitPins[] = {12}; // Nel caso di display a catodo comune dovro' collegare il pin 3 o 8 (Gnd) del 7-segment // al pin digitale 12 (se viene posto a zero accenderà i segmenti posti a 1) byte segmentPins[] = {segA, segB, segC, segD, segE, segF, segG, segDP }; bool resistorsOnSegments = false; // 'false' indica che le resistenze sono sui pin indicati in digitPins byte hardwareConfig = COMMON_CATHODE; // valori ammessi COMMON_ANODE - COMMON_CATHODE bool updateWithDelays = false; // Default. Raccomandato bool leadingZeros = false; // Utilizzare 'true' se si vogliono gli zeri iniziali. Ha senso con + di un display sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros); sevseg.setBrightness(100); // 100 massima luminosità - 0 minima sevseg.setNumber(8,0); // oppure in alternativa: // byte AllPinOn[1]={ B11111111 }; // sevseg.setSegments(AllPinOn); } void loop() { sevseg.refreshDisplay(); delay(1000); // attendo un secondo prima di procedere con il successivo refresh }
Tecnicamente la funzione refreshDisplay gestisce un segmento alla volta ma per effetto della velocita’ del microcontrollore e della “latenza” nella luminosità dei led i segmenti settati ad ON appaiono tutti contemporaneamente accesi mostrando in chiaro il simbolo impostato con le funzioni:setSegments, setChars, setNumber.