Afișare valori numerice pe display cu MAX7219

 Autor:   Publicat pe:   Actualizat pe:  2020-07-07T08:29:11Z

Folosirea unui afișaj cu 7 segmente și 8 digits controlat de MAX7219 ca volt-ampermetru de panou pentru o sursă de alimentare

MAX7219 este un controller pentru afișaje cu LED-uri în conexiune catod comun. Integratul este cunoscut mai ales datorită afișajelor matriciale 8x8, însă acesta poate controla la fel de bine și afișaje cu 7 segmente. Fiindcă vreau să construiesc un volt-ampermetru pentru o sursă de alimentare, am ales un afișaj cu 7 segmente și 8 caractere (digits) controlat de acest integrat. Conectarea la placa de dezvoltare este simplă, interfața fiind una serială de tip SPI, iar nivelele de tensiune sunt 5 V. Dar, partea de software nu este la fel de simplă, biblioteca LedControl pentru MAX7219 neavând funcții care să afișeze valori numerice de tipul float.

În acest articol voi realiza un montaj cu o placă de dezvoltare cu microcontroller ATmega328p care evaluează două intrări analogice și afișează tensiunea citită pe un afișaj cu 8 caractere controlat de MAX7219. Mai mult de atât, voi crea și câteva mesaje predefinite cu caractere ce pot fi afișate și pe afișaje cu 7 segmente.

Afișare valori numerice pe display cu MAX7219

Afișare valori numerice pe display cu MAX7219

Montajul este mult mai simplu față de ce am arătat mai demult în legătură cu modul de conectare a unui afișaj cu 7 segmente fără controller la placa de dezvoltare. Modulele cu MAX7219 au nevoie doar de alimentare și de 3 linii de semnal pentru a controla afișajul. Există inclusiv posibilitatea ajustării nivelului de luminozitate. Eu am pus pe placa de test doi senzori de lumină, unul cu fotodiodă și celălalt cu fotorezistor (LDR). Voi converti valorile analogice citite în tensiune pe care o voi afișa pe display. În cele din urmă, montajul va fi realizat pe un cablaj imprimat, iar cei doi senzori de lumină vor fi înlocuiți după necesitate, fie cu divizoare rezistive, fie cu amplificatoare operaționale care multiplică o cădere de tensiune pe un rezistor. Iată schema montajului actual, realizat pe placa de test.

Afișajul MAX7219 conectat la Arduino

Afișajul MAX7219 conectat la Arduino

Voi folosi biblioteca LedControl pentru acest afișaj. Se poate instala direct din Library Manager în Arduino IDE. În secțiunea setup() va trebui să activăm afișajul, acesta fiind in mod implicit într-o stare de economisire energie. După setarea intensității (sunt acceptate valori între 1 și 15), se recomandă „ștergerea” display-ului, chiar dacă nu a fost afișat nimic. Așa arată codul - se mai observă setarea pinilor analogici ca intrări și apelarea unei funcții despre care voi vorbi în acest articol.

void setup() {
  lc.shutdown(0, false);
  lc.setIntensity(0, 8);
  lc.clearDisplay(0);

  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  startUp();
}

Ca și în cazul afișajelor matriciale cu 8x8 LED-uri, MAX7219 suportă și în configurația cu 7 segmente conectarea mai multor astfel de dispozitive (modulul are două rânduri de pini în acest scop). Din acest motiv, primul parametru necesar funcțiilor din bibliotecă este adresa (indexul) dispozitivului care va fi controlat. Fiind doar unul (în configurația mea), acest argument trebuie să fie 0.

Acum, să vedem cum citim o tensiune aplicată la una din intrările analogice ale Arduino. Convertorul analog-digital al microcontroller-ului ATmega328p are o rezoluție de 10 biți, adică poate aprecia până la 210 valori individuale. Astfel, funcția analogRead(pin) returnează un număr cuprins între 0 și 1023. În mod implicit, ADC-ul folosește ca referință de tensiune chiar tensiunea de alimentare de 5 V, astfel numărul maxim 1023 corespunde acestei tensiuni.

Fiindcă tensiunea de alimentare poate să nu fie exact 5 V, ATmega328p poate folosi și alte referințe de tensiune pentru ADC, una internă de 1,1 V (situație în care 1023 citit pe un pin analogic reprezintă această tensiune) sau o referință externă de maximum 5 V (se pot folosi integrate specializate pentru obținerea referinței de tensiune; ieșirea lor va fi conectată la pinul AREF sau REF). În acest circuit de test voi folosi doar referința de tensiune implicită de 5 V.

Deci, conversia în volți se face înmulțind valoarea analogică citită cu tensiunea de referință și împărțind la numărul maxim posibil de valori (1024). Astfel, U = adc * Vref / 1024, unde Vref = 5. În cod, putem scrie astfel:

int av = analogRead(A2) * 5 / 1024.0;

Pentru a afișa acest număr cu două zecimale, îl voi înmulți cu 100:

av *= 100;

Aceste două rânduri de cod pot fi scrise și astfel (2,048 = 5 / 1024 * 100):

int av = analogRead(A2) / 2.048;

Afișarea se poate face simplu, fără conversii la float, cifră cu cifră. Se determină restul împărțirii la 10 al variabilei av, apoi se divide această variabilă cu 10. Data viitoare când se calculează restul împărțirii, se obține cifra următoare - procedura se repetă până ce variabila ajunge la 0, obținându-se pe rând toate cifrele, de la dreapta la stânga.

void readVoltage() {
  int av = analogRead(A2) / 2.048;

  byte d;

  d = av % 10;
  lc.setDigit(0, 4, d, false);

  av /= 10;
  d = av % 10;
  lc.setDigit(0, 5, d, false);

  av /= 10;
  d = av % 10;
  lc.setDigit(0, 6, d, true);

  av /= 10;
  d = av % 10;
  if (av != 0) lc.setDigit(0, 7, d, false);
  else lc.setChar(0, 7, ' ', false);
}

Implementarea codului este ușoară, având maxim 4 cifre de afișat nu se justifică un ciclu de tip while (av), iar numerotarea afișajului, tot de la dreapta la stânga, vine în ajutor. Ultimul argument solicitat de funcția lc.setDigit() este de tip boolean și controlează punctul zecimal. Deoarece voi afișa valori cu două zecimale, în dreapta celei de-a treia cifre afișate se activează LED-ul punctului zecimal.

Pentru MAX7219, fiecare cifră de pe afișaj este reprezentată ca un rând, iar segmentele sunt coloane. Știind acest lucru, am creat funcția startUp() al cărei rol este de a afișa o „animație” la alimentarea montajului. Astfel, „coloanele” (segmentele) sunt aprinse succesiv până ce apare peste tot cifra 8, iar apoi „rândurile” (cifrele) sunt șterse dinspre margini spre mijloc. Codul este următorul:

void startUp() {
  lc.setColumn(0, 1, 0xFF);
  delay(100);
  lc.setColumn(0, 2, 0xFF);
  delay(100);
  lc.setColumn(0, 3, 0xFF);
  delay(100);
  lc.setColumn(0, 4, 0xFF);
  delay(100);
  lc.setColumn(0, 5, 0xFF);
  delay(100);
  lc.setColumn(0, 6, 0xFF);
  delay(100);
  lc.setColumn(0, 7, 0xFF);
  delay(100);
  lc.setRow(0, 7, 0x00);
  lc.setRow(0, 0, 0x00);
  delay(100);
  lc.setRow(0, 6, 0x00);
  lc.setRow(0, 1, 0x00);
  delay(100);
  lc.setRow(0, 5, 0x00);
  lc.setRow(0, 2, 0x00);
  delay(100);
  lc.setRow(0, 4, 0x00);
  lc.setRow(0, 3, 0x00);
  delay(100);
}

Iar rezultatul arată cam așa:

Efect de animație pe afișajul MAX7219

Efect de animație pe afișajul MAX7219

Spuneam că se poate afișa inclusiv text pe acest display. Biblioteca LedControl suportă doar câteva caractere, necesare pentru a afișa numere în sistem hexazecimal (A, B, C, D, E, F) și cuvântul „HELP”. Spațiul unei cifre este de fapt un „rând” după cum am demonstrat prin funcția de mai sus. Știind că funcția lc.setRow() acceptă ca ultim argument o variabilă de 8 biți care conține starea LED-urilor (segmentelor) ce vor fi aprinse, putem crea și alte caractere (litere). Fiecare bit din acel argument corespunde unui LED (segment), iar această asociere bit-LED poate fi aflată încărcând o schiță cu următoarea funcție:

void segmentBit() {
  lc.clearDisplay(0);
  lc.setRow(0, 7, 0x01); // B00000001
  lc.setRow(0, 6, 0x02); // B00000010
  lc.setRow(0, 5, 0x04); // B00000100
  lc.setRow(0, 4, 0x08); // B00001000
  lc.setRow(0, 3, 0x10); // B00010000
  lc.setRow(0, 2, 0x20); // B00100000
  lc.setRow(0, 1, 0x40); // B01000000
  lc.setRow(0, 0, 0x80); // B10000000
}

Codul de mai sus aprinde, începând de la stânga, câte un segment, în ordine. Astfel, se poate deduce modul de numerotare al segmentelor (se pare că este total diferit față de cel folosit de funcția lc.setColumn()):

Numerotare segmente placă afișaj MAX7219

Numerotare segmente placă afișaj MAX7219

O funcție care afișează „Err. HEAt” va avea următorul cod:

void displayError() {
  lc.clearDisplay(0);
  lc.setRow(0, 7, 0x4F);
  lc.setRow(0, 6, 0x05);
  lc.setRow(0, 5, 0x85);
  lc.setRow(0, 4, 0x00);
  lc.setRow(0, 3, 0x37);
  lc.setRow(0, 2, 0x4F);
  lc.setRow(0, 1, 0x77);
  lc.setRow(0, 0, 0x0F);
}

Posibilități de utilizare a unui astfel de montaj sunt multe. Afișaj pentru temperatură și umiditate cu posibilitatea de acționare a unui releu la atingerea unui prag ar fi o altă posibilitate. Eu îl voi folosi ca afișaj de tensiune și curent la o sursă de alimentare, cu câteva funcții suplimentare: afișare temperatură radiator de răcire (la apăsarea unui buton), afișare mesaj la scurtcircuit și la supraîncălzire, cu acționarea unui releu de oprire în aceste situații. O schemă simplificată de măsurare a tensiunii și curentului ar putea arăta cam așa:

Voltampermetru cu Arduino și afișaj MAX7219

Voltampermetru cu Arduino și afișaj MAX7219

Această metodă de măsurare a curentului prin circuit, multiplicând căderea de tensiune pe un rezistor de valoare mică poate fi utilizată la curenți de până la 4-5 A. Mai mult de atât și căderea de tensiune pe rezistor devine importantă (> 0,5 V), lucru nedorit. Pentru a evita intercalarea unui rezistor în circuit și, implicit, căderea de tensiune ce apare pe acesta, se poate folosi un modul cu senzor inductiv de curent, cum sunt cele cu ACS712. Realizarea practică a unui voltampermetru, pe care-l voi conecta la o sursă de alimentare, va fi abordată într-un articol viitor.

Schița Arduino folosită pentru acest afișaj este: max7219_analog_values.ino.

Niciun comentariu :

Trimiteți un comentariu

Vă recomandăm să citiți regulamentul comentariilor înainte de a scrie un comentariu.