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:

Display 7 segment - 4 digit

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.

   Schema Pin singolo display 7 segmenti

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

Display 7 segment - 4 digit

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

Foto circuito 7Segment 4 digit

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

Agiunta libreria

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.