OUTPUT DIGITALE: Esempio DISPLAY 7 SEGMENTI (versione 17/05/2017)

Per costruire gli esempi proposti è necessario procurarsi un display a 7 segmenti.

Single Digit 7 Segment Display

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).

   Schema Pin singolo display 7 segmenti

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:

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.