LED matrix MAX7219 IC-vel

A MAX7219 LED meghajtó hasznos eszköz, ha egyszerre sok LED-et kell vezérelni, mert kevesebb chip kivezetést kell elhasználnunk a LED-ekre. Összesen 8×8=64 ledet vezérelhetünk. A Max7219-et jellemzően kétféle eszközben használják. 8×8-as LED mátrixkijelzőben, és maximum 8 digites 7 szegmenses kijelzőkben.

A MAX7219 a ledeket időszeletekben villogtatja, vagyis egyszerre mindig csak 8 világíthat, a többi éppen sötét. A 8-as led csoportokat kb 800Hz frekvenciával váltogatja, így szemünk úgy érzékeli, mintha mind folyamatosan világítana, de természetesen kicsit halványabban. Ha a kijelzőkre sokszor süt rá a nap, akkor ez nagy hátrány lehet. Ekkor hasznosabb lehet inkább 8db 74HC595 léptetőregiszter, az képes folyamatosan áramot adni egy-egy lednek! Az általam használt LED mátrix kijelző esetén azonban erről szó sem lehet, mert a LED-eket összeépítették egy tokba, és sorokba, illetve oszlopokba rendezték. Kizárólag időszeleteléses módon lehet használni. Így néz ki a kapcsolási rajza egy led mátrix kijelzőnek:

A MAX7219 bekötése és vezérlése nagyon egyszerű. Összesen három kivezetést használunk el a vezérlő kimeneteiből. Az egyes modulok felfűzhetők egymás után, és egyik a másiknak adja át a beléptetett adatokat.

A MAX7219 (vezérlő) kivezetései a következők

  1. Data – Ezen keresztül léptetjük be az adatokat. Az összes led állapotának megváltoztatásához 8×2 byte adatot kell a chipbe küldenünk. A ledek 8-as csoportokban egyedileg írhatók 2 byte adattal.
  2. CLK – órajel bemenet. Minden órajel bemenetre adott felfutó él beolvassa a Data bemeneten lévő jelszintet, és belépteti a chip adat regiszterébe. A 2byte beküldése tehát 16 órajelciklus.
  3. Chip select – Aktív alacsony szint. Amikor erre a bemenetre egy lefutó él érkezik, az azt jelenti a chipnek, hogy beléptettük az összes adatot a Data és a CLK bemenetek segítségével, és a bejutott adatokat lehet értelmezni, megjeleníteni amit kell.

Műszaki adatok

ParaméterMAX7219
Tápfesz:4,0 V ~ 5,5 V
Tápáram:330mA
A szegmens meghajtó árama-40mA
Szegmens frissítés500–1300 Hz (800 Hz tipikus)
órajellegfeljebb 10MHz

MAX7219 adatlap: http://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf 

Fényerőt is szabályozhatunk. Összesen 16 fokozatban (4 bit) adható meg a LED-ek fényereje a 0 és a maximum között. A fényerőt ekkor PWM módon szabályozza, azaz 0 és maximális áram folyik át a ledeken, és a kitöltési tényező változik, amikor a led egyébként világít. Ez a szoftveres lehetőség. Azonban a chip egyik kivezetésére kötött ellenállás meghatározza a ledeken átfolyó áram nagyságát, így ezzel is lehet fényerőt szabályozni. Ezt az ellenállást a kijelző modulokra ráépítik, gyakorlatban nem kell vele foglalkozni! Azért itt egy táblázat annak, aki ennek cseréjére kényszerül valamilyen rejtélyes okból:

A táblázatban szerelő értékek Kohm-ban lettek megadva. Egy átlagos led esetén a maximális 40mA meghajtóáramhoz kb 10Kohm ellenállás szükséges, ezzel nem lehet nagyot tévedni.

A MAX7219 belső felépítése

A MAX7219 bemeneti interfésze egy 16 bites regiszter. Az első 8 bit meghatároz egy parancsot, a második 8 bit pedig a parancs adatait (lásd később):

Több MAX7219 eszközt felfűzhetünk egymásra. A Din bemenetre mindig az előző chip Dout kivezetését kell kötni. Ez elsőre természetesen az Arduino valamelyik kimenetét. A CLK és Chip Select bemeneteket párhuzamosan kötjük az összes chipre.

Az biztosan nyilvánvaló, hogy ennek az IC-nek a használatához is van programcsomag. A szokásos helyen, a eszközök/könyvtárak kezelése menüpontban keressünk rá a “ledcontrol” szóra:

Mint a képen látható, és két programcsomagot is letöltöttem magamnak. Valójában csak a “LedControl” programcsomagot használom, de a “LEDMatrixDriver” nevű csomagot is megnézegettem. Utóbbiban inkább animációk, mozgó feliratok kezelését megkönnyítő programokat lehet találni. Nekem ez még nem kellett, elég volt néhány statikus felirat és ábra.

Az Arduino Ledcontrol könyvtár használata

A könyvtár legfeljebb nyolc láncra fűzött MAX7219 IC használatát támogatja.
A könyvtár inicializálásának tipikus kódja így néz ki:

#include “LedControl.h”
LedControl lc1=LedControl(12,11,10,1);

Ezzel a két sorral készen is vagyunk. Létrehoztuk az lc1 nevű változót, amivel a továbbiakban dolgozni fogunk a programban. Az inicializálás során 4 paramétert kellett megadni. Az első 3 paraméter az Arduino kivezetéseinek számai, amelyek a MAX7219-hez kapcsolódnak. Ezek lehetnek az Arduino tetszőleges digitális IO-érintkezői.  Nem kell inicializálni a megadott kivezetéseket kimenetekként, vagy beállítani azokat egy bizonyos állapotba, ezt a LedControl könyvtár megteszi. Az egyes megadott kivezetések szerepe:

LedControl(dataPin,clockPin,csPin,numDevices)

A negyedik paraméter sorba fűzött MAX7219 chip-ek esetén a lánc mérete. A könyvtár maximum 8 eszközt képes kezelni egyetlen LedControl változóból, így itt csak 1..8 közötti értékek megengedettek.

Ha a programnak 8-nál több MAX7219-et kell vezérelnie, akkor egy másik -változót kell létrehozni, amely 3 másik kivezetést használ:

#include “LedControl.h”
LedControl lc1=LedControl(12,11,10,8); // első 8 eszköz… 
LedControl lc2=LedControl(9,8,7,8); // második 8 eszköz…  

Energiatakarékos üzemmód

A ledek elég sok energiát fogyasztanak, amikor világítanak. Előfordulhatnak olyan felhasználások, amikor ez számít a MAX7219 támogatja az energia takarékos kikapcsolási módot.

Ebben a módban a készülék a chip kikapcsolja az összes LED-et a kijelzőn, de az adatok megmaradnak. Amikor a chip-et vissza kapcsoljuk, ugyanazok a LED-ek világítanak, mint az alváskor. Lehetőség van az adatok frissítésére energia takarékos módban is. A chip felébresztésekor már az új adatok fognak látszani. Az energia takarékos mód ki és bekapcsolására az alábbi kód szolgál:

shutdown(int addr, bool status)

ahol az “addr” a modulnak a száma, tehát ha minden egyes MAX7219 IC-t energia takarékos módba akarunk küldeni, akkor annyiszor kell meghívnunk ezt a függvényt, ahány IC-t kapcsoltunk sorba. A visszakapcsolásra természetesen ugyanez vonatkozik! A “status” egy logikai érték, 1 (true) esetén bekapcsolódik az energia takarékos mód, míg 0 (false) esetén visszakacsolódik a led-ek fénye. Konkrét példa:

lc1.shutdown(0,true); //kikapcsoljuk a ledeket, energia takarékos mód elindul
lc1.shutdown(0,false); //visszakapcsoljuk a ledek fényét, újra sokat fogyaszt a modul

Találtam az egyik leírásban egy megjegyzést arra vonatkozóan, hogy az energia takarékos mód a kijelző inicializálásakor nem biztos, hogy kikapcsolt állapotba kerül. Volt egy kijelzőm, aminek a hibás működésben lehetséges, hogy ez játszott szerepet. A hiba az volt, hogy áramszünet után a bekapcsolódást követően a matrix kijelző sötét maradt. Ekkor mindig a készülékhez kellett menni, és az Arduino reset gombjával kellett elindítani a készüléket, és így már működtek a kijelzők. Később az eszközt szétszedtem és újat építettem (nem az említett hiba miatt). Már nincs meg az áramkör, így nem tudom kipróbálni, de valószínűleg segített volna, ha a programba a kijelző inicializálást követően,kikapcsoltam volna az energia takarékos módot.

Az új kütyünek amit megépítettem az volt a baja, hogy teljesen váratlanul időnként kikapcsoltak a kijelzők, vagy összevissza itt-ott világított egy-egy led. A program rendben futott tovább, ezt más jelekből érzékeltem, illetve amikor más más betűket írt a program a kijelzőre, változtak az éppen világító ledek, de továbbra is összevisszaságot lehetett látni. Sokat vesződtem a problémával, és végül az derült ki, hogy kicsik voltak a MAX7219 tápegységének szűrőkondenzátorai. Beforrasztottam közvetlenül az IC-re egy-egy 100mikroF elektrolit kondenzátort, és a probléma eltűnt. Utólag visszatekintve az gyanítom, hogy valamilyen tápegység szűrési probléma miatt sérült az adat, amit megkapott a kijelző!

A kijelző fényerejének beállítása

Három tényező határozza meg a képernyő fényerejét.

  • a kijelző szegmens áramát beállító RSET ellenállás értéke, amiről már előbbiekben volt szó
  • a MAX7219 ugyanazon pillanatban megvilágított led csoportjainak a száma. Alapértelmezetten ez 8 led csoport, ami egy mátrix kijelző esetén egyértelmű. Ha azonban 7 szegmenses kijelzőket hajtunk meg a MAX7219-el, akkor nem feltétlenül használunk 8 számjegyet. Ha pl. csak 4 számjegyünk van, akkor hosszabb ideig tudja kivilágítani a használt digiteket a chip. A mátrix kijelző esetén ez nem lehetőség, de megemlítem, ha valakinek szüksége lenne rá, akkor a “scanlimit” szavakkal keresgéljen az IC adatlapjában. A LedControl könyvtárnak is van erre funkciója, de nem foglalkoztam vele.
  • egy fényerő beállító függvény, amely lehetővé teszi a LED-ek fényerejének a szoftverből történő vezérlését.

Az RSET áram beállító ellenálláshoz egy mátrix kijelző modul esetében nagyon nehezen férünk hozzá (smd ellenállás, nagyon nehéz kicserélni), ezért ezzel nem foglalkoztam. A szoftveres beállítás viszont igen hasznos. Érdemes a környezete megvilágítását pl. egy fototranzisztorral ellenőrizi, és hozzáigazítani a kijelző fényerejét. Ha a fototranzisztor működése érdekel, kattints ide a leírás elolvasásához! A fényerő beállítása 16 fokozatban történik, a függvény így néz ki:
setIntensity(int addr, int intensity);
ahol az “addr” a sorba kötött mátrix kijelző modulok közül a kiválasztott modul sorszáma. Vagyis minden egyes modulra meg kell hívni a függvényt. Az “intensity” a fényerő numerikus értéke. 0 a legkisebb, míg a 15 a maximális fényerő. Ha 15-nél nagyobb értéket adunk meg, akkor a maximális fényerőt állítja be a függvény. Konkrét példa közepes fényerő beállításra:
setIntensity(0,8);

A kijelző törlése

A függvény neve:
clearDisplay(addr);
ahol az “addr” a modul sorszáma. Működése egyértelmű, törli az összes led fényét, alaphelyzetet állít be a kijelzőn. Nem azonos a shutdown függvénnyel, ami szintén kikapcsolja az összes ledet, de nem törli az információt a chip memóriájából.

Egyetlen LED ki és bekapcsolása

A függvény neve:
setLed(int addr, int row, int col, boolean state);
ahol az “addr” a modul sorszáma, “row” a sor index, “col” az oszlop index, “state” pedig az állapot, amit szeretnénk (kikapcsolásnál 0, bekapcsolásnál 1).

A mátrixban 8 sor van (indexelve 0..7-től) és 8 oszlop (szintén indexelve 0..7-től). Ha fel szeretnénk kapcsolni egy ledet a felülről a második sor jobb oldalán található harmadik LED-et, akkor a LED indexét kell használni sor- és oszlop argumentumként:
setLed(0,1,2,true);
A paraméterek értelmezésénél vegyük észre, hogy a második sor indexe 1, mivel az indexek 0-val indulnak. A harmadik led indexe a sorban ennek megfelelően 2. Természetesen a matrix kijelző vezetékezésének ilyennek kell lennie:

Sor ledjeinek vezérlése

Az egy sorban található ledeket egyetlen függvénnyel is lehet kapcsolni. Ennek a függvényenek a neve:
setRow(addr,row,value);
ahol az “addr” a modul sorszáma, “row” a sor index (felülről számolva), “value” pedig az állapot, amit szeretnénk ez egyes ledeken látni. Az utolsó paraméter egy byte, aminek a bitjei megmondják az egyes led-ek állapotát (kikapcsolásnál 0, bekapcsolásnál 1). Az egyes biteket megadhatjuk binárisan pl. lc.setRow(0,7,B10110000) vagy ha ez nem lehetséges, akkor decimális értékben is. Utóbbi esetben hasznos az alábbi táblázat:

Bit-érték1286432168421
Led On?10110000
Sor-érték128032160020

A táblázatban a “Led On” feliratú sorban 1-el jelezték, ha a led be van kapcsolva. A konkrét példában a függvény value értéke 176 (128+32+16), és ekkor balról a az első, harmadik és negyedik led világít.


A setRow() függvény nyilvánvalóan sokkal gyorsabb mit a setLed(), mert egy sor tartalmát utóbbi függvénnyel nyolc hívással lehetne kiírni. Ráadásul azt is tudjuk, hogy a MAX7219-ben egy 8×8-as regiszter található, melyet byte-onként lehet írni. A regiszter szervezése olyan, hogy egy byte egy sor adatait tartalmazza, és amikor adatokat írunk a MAX7219-re, akkor egyszerre egy sor adatait adjuk át. A következő függvény a setColumn() ami egy oszlopot tud beállítani, szintén nyolc írási ciklussal tudja frissíteni az oszlopban található led-ek állapotát. Ezért ha csak lehetséges a setRow() függvényt használjuk.

Oszlop ledjeinek vezérlése

Már említettem az előbb a függvényt:
setColumn(addr,column,value);
Magyarázatra az előbbiek alapján már nem szorul a működés és a paraméterek. Az egyes ledeket itt is bináris számmal lehet a legvizuálisabban kijelölni, de ha erre nincs lehetőség, az előző táblázat itt is működik.
Megosztanék egy tapasztalatot. Amikor a matrix kijelzőt először használtam, véletlenszerűen ezzel az oszlop vezérlő függvénnyel írtam ki a karaktereket. Nem vettem észre, hogy az adatok átküldése így sokkal tovább tart. E közben “műszaki” problémákkal is küzdöttem, mert a kijelzés időnként “lefagyott” vagy nem a várt karakterek jelentek meg, hanem véletlenszerű ledek világítottak. Egy kicsivel előbb már említett tápfesz szűrési problémát ekkor még nem derítettem ki. Olyan eset is előfordult, hogy a kijelző csak pár percig jól működött, és ezt követően fagyott le. Jellemzően néhány óra után eset szét a karakterkép. Amikor ezt a leírást készítettem, felfigyeltem arra, hogy az oszlop vezérlő függvény nem optimális, rengeteg adatot mozgat. Átírtam tehát a sor vezérlő függvényre a programot, ami nem volt egyszerű,mert a karakterképeket át kellett számolgatni. Megérte! Amikor kicseréltem a programot, sokkal kevesebb esetben eset szét a kijelző képe. Már-már azt hittem meg is javult, de aztán néhány hét elteltével újra jelentkezett a hiba. Ekkor támadt az extra szűrőkondik beforrasztásának ötlete, amitől a probléma megoldódott. Lehet, hogy a probléma eredete a tápegység körül volt, de a sokkal kevesebb adatküldés is segített!!

7 segmens kijelző vezérlése

Nyilvánvalóan nem csak mátrix kijelzőt köthetünk a chip-re. Összesen 8 db 7 szegmenses kijelzőt is tud vezérelni:

Ehhez is találunk függvényt:
setDigit(addr, digit, value, dp);
A paraméterekben az “addr” a modul sorszáma, a “digit” a 8 kijelző egyikének indexe, a “value” a kijelezni kívánt érték, a “dp” pedig a tizedespont. A tizedespontot true vagy false értékekkel vezérelhetjük. Pl a következő programrészlet egy háromjegű számot jelenít meg:
byte egyes=2; 
byte tizes=3;
byte szazas=4;
lc.setDigit(0,2,szazas,false);
lc.setDigit(0,1,tizes,false);
lc.setDigit(0,0,egyes,false);
A program futásának eredménye a 432 szám kijelzése a kijelzőn. Bevallom nem próbáltam mi, mert nem használtam még 7 szegmenses kijelzőt a MAX7219-el, de biztosan működik.Nyilván a chip nem tudja, hogy mátrix vagy 7 szegmens kijelzők lógnak rajta, így a számjegyek törlésére a clearDisplay(addr); függvényt használhatjuk.
Korlátozottan betűket is meg tud jeleníteni egy 7 szegmenses kijelző. Ezért csináltak egy másik függvényt is:
setChar(addr, digit, value, dp);
A működését nem kell magyarázni az előző függvény alapján, de kérdés, hogy mit lehet a value értékhez írni? Hát ezt:
0 1 2 3 4 5 6 7 8 9
A a (nagybetűt jelenít meg)
B b (kisbetűt jelenít meg)
C c (kisbetűt jelenít meg)
D d (kisbetűt jelenít meg)
E e (nagybetűt jelenít meg)
F f (nagybetűt jelenít meg)
H h (nagybetűt jelenít meg)
L l (nagybetűt jelenít meg)
P p (nagybetűt jelenít meg)
– (mínuszjel)
. , (kigyullad a tizedes pontot)
(aláhúzás)
<space> (üres vagy szóköz)

Mennyire volt hasznos amit olvastál?

Kattints egy csillagra az értékeléshez!

Sajnálom, hogy amit olvastál nem volt hasznos számodra!

Szeretném ha elégedett lennél!

Írd le kérlek, hogy mi nem tetszett!?