Display a 7 segmenti 4 digit

Per alcuni interessanti progetti, si potrebbe fare uso di display a 7 segmenti per la visualizzazione di una cifra oppure di un dato binario.

Per pilotare un display però, occorrono tanti decoder quanti i display e tante resistenze quanti i punti luminosi da accendere.

Sembra quindi un lavoro immane progettare un dispositivo con 4 o più display utilizzando questi metodi tradizionali.
Quello che affronteremo in questo articolo è l’uso di più display a 7 segmenti (cifre), utilizzando Arduino e facendo uso della tecnica del Multiplexing.

Il multiplexing non è altro che un sistema che permette il controllo di molti dispositivi, sfruttando l’alta velocità di commutazione dei segnali e il minimo delle porte di I/O, per interfacciarsi a tutti i dispositivi. Con “velocità di commutazione” si intuisce facilmente la funzione del multiplexer: commutare un segnale ad alta velocità per fare in modo che i dispositivi siano utilizzati “contemporaneamente” senza perdite di prestazioni “esagerate”.

In realtà, nel multiplexing non si inviano più comandi contemporaneamente (che solo processori a più core possono fare), ma su più display a 7 segmenti ad esempio, si invia una cifra alla volta e scorrendo da un display all’altro molto velocemente. A vista d’occhio sembra proprio che il numero su più display viene mandato tutto insieme, ma c’è l’inganno. Il nostro occhio infatti ha un tempo di risposta di circa 20 millisecondi (1/50 di secondo) tra un’immagine ed un’altra e questo ci permette appunto di utilizzare il multiplexing.
La magia della Persistenza visiva della retina è spiegato chiaramente qui.

Inviando più dati al display con una frequenza maggiore del “refresh” della retina del nostro occhio, ad esempio 200 Hz, ecco che il nostro dato sul display ci appare “unito”.

Ma come fare? La tecnica è molto semplice ed eccola spiegata:

Faremo uso di un timer interno dell’Atmega328 (microcontrollore di Arduino UNO) che appunto temporizzerà il passaggio tra un display e l’altro. La frequenza necessaria per scorrere tutti i display è di circa 200 Hz (si può salire e scendere, non è un valore critico), quindi 1,25 millisecondi per ogni display (in questo caso 4).
Il timer, ad ogni overflow (non sto a spiegare anche questo, rimando a quest’ottima pagina) avvia una funzione che è quella che si occuperà di scorrere i display uno ad uno.
Nel loop principale ci occuperemo invece di processare il nostro valore da inviare al display, dividendolo per ogni cifra per ogni singolo display (migliaia, centinaia, decine, unità).

Adesso passiamo al codice e per prima cosa dovete avere la libreria TimerOne nel vostro IDE che potete scaricare da qui.

Questo è lo schema:

Schema pilotaggio display 7 segmenti con Arduino

#include <TimerOne.h>

int dig1 = 5,dig2 = 6,dig3 = 7,dig4 = 8;
int a = 9,b = 10,c = 11,d = 12,e = 13,f = 2,g = 3;

char currDig = 0;
char migliaia,centinaia,decine,unita;

// Array delle cifre e lettere (A,B,C,D,E,F,G)
char letters[18][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
{0,0,0,1,0,0,0},        // A
{1,1,0,0,0,0,0},        // b
{1,1,1,0,0,1,0},        // c
{1,0,0,0,0,1,0},        // d
{0,1,1,0,0,0,0},        // E
{0,1,1,1,0,0,0},        // F
{0,1,0,0,0,0,1},        // G
{1,1,0,1,0,0,0}         // h
};

Nel primo pezzo di codice viene inclusa la libreria “Timer1” fornita dal PlayGround di Arduino. Come già detto, questa libreria si occuperà di gestire i timer interni al microcontrollore e ad ogni overflow del tempo prestabilito, avvia una funzione che si occuperà di mandare sul display le varie cifre.
Sono quindi dichiarate delle variabili:
– le variabili digX si riferiscono alle uscite verso i transistor che controlleranno tutti i segmenti delle singole cifre (4 cifre).
– le variabili alfanumeriche a,b,c etc. si riferiscono alle uscite dei singoli segmenti che compone la cifra (7 segmenti).

Dopodiché viene creato un’array che contiene le informazioni per ogni singolo segmento: essendo il display a anodo comune, lo 0 accende il segmento e 1 lo spegne. Il primo a sinistra e il segmento A mentre l’ultimo, in sequenza, è il segmento G.
Questo è un’array bidimensionale o anche detto 2D, per questo ad ogni elemento della prima dimensione (cifra) vengono associati sette elementi nella seconda dimensione (segmenti). Per non allungare troppo nelle spiegazioni, vi rimando a questa bella paginetta che descrive gli array bidimensionali perfettamente.
Attenzione: in questo progetto non viene utilizzato un Driver/Decoder-BCD a 7 segmenti esterno tipo CD4511 perchè ne ero sprovvisto. Quindi mi sono interfacciato direttamente ad ogni singolo segmento tramite Arduino.

void setup()
{

  Timer1.initialize(1250);         // initialize timer1, and set a 1,5 millisecond period
  Timer1.attachInterrupt(setDigit);  // attaches callback() as a timer overflow interrupt
  pinMode(dig1,OUTPUT);
  pinMode(dig2,OUTPUT);
  pinMode(dig3,OUTPUT);
  pinMode(dig4,OUTPUT);
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  pinMode(e,OUTPUT);
  pinMode(f,OUTPUT);
  pinMode(g,OUTPUT);
  Serial.begin(9600);

}

void loop()
{
  int i=0;
  for(i=0;i<=9999;i++)
  {
    migliaia=i/1000;
    centinaia=(i%1000)/100;
    decine=(i%100)/10;
    unita=i%10;
    delay(10);
    Serial.println(i);
  }

}

Nel setup() del programma, viene dapprima inizializzato il Timer1 per scandire lo scorrimento dei display e in seguito vengono impostate tutte le porte utilizzate come uscite.
Infine viene inizializzato una comunicazione seriale con il PC.

Nel loop() invece, viene creato un ciclo for che incrementa una variabile.
Questa variabile viene quindi divisa in altre variabili: migliaia, centinaia, decine e unità. Questo serve per associare una singola cifra della variabile i ad un singolo digit del display a 7 segmenti.
Per chi non lo sapesse, il simbolo % in C/C++ e altri linguaggi è il simbolo del “modulo”.

void SendLetters(unsigned char digs)
{

  digitalWrite(a,letters[digs][0]);
  digitalWrite(b,letters[digs][1]);
  digitalWrite(c,letters[digs][2]);
  digitalWrite(d,letters[digs][3]);
  digitalWrite(e,letters[digs][4]);
  digitalWrite(f,letters[digs][5]);
  digitalWrite(g,letters[digs][6]);

}

La funzione SendLetters() si occupa di inviare ad ogni singolo segmento il suo stato, acceso (0) o spento (1).
A seconda della cifra/lettera che vogliamo inviare al display, viene interpellato l’array che è stato creato precedentemente con i valori di acceso o spento per ogni segmento.

void setDigit()
{

  if(currDig++>3) currDig=0;
  digitalWrite(dig1,LOW);
  digitalWrite(dig2,LOW);
  digitalWrite(dig3,LOW);
  digitalWrite(dig4,LOW);
  switch(currDig)
  {

  case 0:
    SendLetters(migliaia);
    digitalWrite(dig1,1);
    break;

  case 1:
    SendLetters(centinaia);
    digitalWrite(dig2,1);
    break;

  case 2:
    SendLetters(decine);
    digitalWrite(dig3,1);
    break;

  case 3:
    SendLetters(unita);
    digitalWrite(dig4,1);
    break;


  }

}

Quindi nell’ultimo pezzo di codice, la funzione setDigit() è quella che ad ogni overflow del Timer1 viene richiamata.
Ad ogni richiamo di funzione, viene incrementato una variabile, che controllata, fa in modo di assegnare ad ogni singola cifra del display la sua corrispondente cifra di migliaia, centinaia, decina o unità.
Per ogni scorrimento, tutti i display vengono spenti, viene inviata la cifra delle migliaia e viene acceso il display corrispondente alle migliaia, si vede quindi il suo valore sul display. Di nuovo, vengono spenti tutti i display, viene inviata la cifra delle centinaia e viene acceso il display delle centinaia e così di seguito, all’infinito.

Una foto (scusate l’horror dei collegamenti ma è tutto fatto al volo e per prova e l’arduino è in standalone) vale più di tante parole:

Arduino e display a 7 segmenti

E questo è un video di funzionamento:

Bene, questo era un piccolo articolo per descrivere il multiplexing utilizzando Arduino.
Spero vi sia piaciuto 😉 …
Restate sintonizzati!!