Arduino LED Mátrix Vezérlés MAX7219 IC-vel

Kedves Blogolvasó! Ez a leírás az Arduino ledmátrix vezérléssel foglalkozik, különös tekintettel a MAX7219 IC használatára. A téma magában foglalja a modul felépítését, az Arduino-hoz való csatlakoztatását, valamint a szoftveres vezérlést a népszerű LedControl könyvtár segítségé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 LED Mátrix Modul Felépítése

Első lépésben a modul felépítését szeretnénk ismertetni. A csomag tartalma:

  • 1 db 10 K-s ellenállás
  • 2 Kondi
  • A nyáklap
  • A DIP foglalat + MAX7219
  • Csatlakozó tüskék
  • És a 8×8-as led mátrix

Amikor összeállítjuk a kapcsolást, akkor arra figyeljünk, hogy a 0,1 uF-os kondit mindegy milyen oldalról és hogyan forrasztjuk be mert polaritás nélküli. Viszont a 10 uF-es kondit csak polaritáshelyesen forrasszuk be. Továbbá apró kis segítség a nyák megalkotóitól, hogy rajta van hova kerül a MAX7219. Ennek megfelelően illesszük az IC-t a helyére. („Feliratot a felirathoz :)”). A többi adja magát szerintem, ha még sem akkor alaposan nézzük meg a képeket.

A MAX7219 a LED-eket 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 rásüt a nap, akkor a halványabb fényerő nagy hátrány lehet. 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.

MAX7219 IC Áttekintés és Működése

A MAX7219 a LED meghajtó hasznos eszköz, ha egyszerre sok LED-et kell vezérelni. A Max7219-et kétféle eszközben használják: 8×8-as LED mátrixkijelzőben, és maximum 8 digites 7 szegmenses kijelzőkben. Röviden pár szó az IC-ről: 8 darab 7 (+1) szegmenses kijelzőt képes vezérelni egy IC. Az adatokat SPI-n tolhatjuk bele (soros kommunikáció), az IC pedig cserébe multiplexeli a szegmensek között. Vezérlés szempontjából teljesen mindegy, hogy több darab egy digites, vagy több digites kijelzőt használunk. A lábkiosztás és az alap áramköri séma egyszerű, könnyen értelmezhető/össze rakható.

Relé vezérlés Arduino segítségével

Az adatlap szerint az áramkorlátozó ellenállás minimális értéke 9.53kOhm. A tapasztalat nekem azt mutatta, hogy 22k ellenállással működött rendesen. Érdemes megjegyezni, hogy az itt található áramkörökben a zajok szűrésére használ két kondenzátort. Én ezt nem pakoltam bele az áramköreimbe, nem észleltem problémát, pedig egyszerű breadboardokon pakoltam össze mindent, ami nem a stabil kontaktról híres.

MAX7219 LED multiplexing tutorial

Több MAX7219 IC Sorba Kötése

Van még egy rendkívül hasznos tulajdonsága ennek az IC-nek: sorba köthetőek. 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, az első modul Din bemenetére természetesen az Arduino valamelyik kimenetét. A könyvtár 8 IC-t kezel egy sorban.

Fényerő Szabályozása

Fényerőt is szabályozhatunk. Összesen 16 fokozatban adható meg a LED-ek fényereje egy minimum és maximum között. A fényerőt ekkor PWM módon szabályozza, azaz 0 és maximális áram folyik át a LED-eken, és a kitöltési tényező változik, amikor a LED-nek világítania kell. Ez a szoftveres lehetőség. Azonban a chip egyik kivezetésére kötött ellenállás meghatározza a LED-eken á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!

A szoftveres beállítás viszont igen hasznos. Érdemes a környezet megvilágítását pl. egy fototranzisztorral ellenőrizi, és hozzáigazítani a kijelző fényerejét. A fényerő beállítása 16 fokozatban történik.

Energiatakarékos Mód

A ledek elég sok energiát fogyasztanak, amikor világítanak. Előfordulhatnak olyan felhasználások, amikor ez számít és a MAX7219 támogatja az energia takarékos módot. Ebben a módban a chip kikapcsolja az összes LED-en a kijelző meghajtó feszültségét, 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, hiszen a chip egyéb részei működnek továbbra is. Ilyen esetben a chip felébresztésekor már az új adatok fognak látszani.

Gyakorlati útmutató az Arduino motorvezérléshez

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.

Scan Limit

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 MAX7219 és Arduino Nano Csatlakoztatása

A MAX7219 bekötése és vezérlése nagyon egyszerű. Összesen három kivezetést kell elhasználnunk az Arduino kimeneteiből. Lássuk hogyan kell bekötni a mi kis modulunkat:

  • VCC - 5V
  • GND - GND
  • CS (Chip Select) - D10 Pin
  • CLK (Órajel) - D11 Pin
  • DIN (Adat bemenet) - D12 Pin

A Din bemeneten 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. A CLK órajel bemenetre adott felfutó él beolvassa a Data bemeneten lévő jelszintet, és belépteti a chip adat regiszterébe. A Chip select aktív alacsony szintű.

Szoftveres Vezérlés a LedControl Könyvtárral

Ezután nincs más dolgunk, csak az, hogy a szoftveres oldalt előkészítsük. Ehhez szükségünk lesz a "LedControl" könyvtárra. Mint a képen látható, 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.

Potenciométeres szervóvezérlés Arduinóval

A LedControl inicializálásához 4 paramétert kell megadni. Ezek rendre: DataIn, CLK, LOAD lábak (digitális outputként lesznek használva). Negyedik paraméterként pedig meg kell mondanunk, hogy hány IC van sorbakötve. A könyvtár 8 IC-t kezel egy sorban.

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 kimeneteként, vagy beállítani azokat egy bizonyos állapotba, ezt a LedControl könyvtár megteszi. A negyedik paraméter sorba fűzött MAX7219 chip-ek esetén a lánc mérete.

Főbb LedControl Függvények

A LedControl könyvtár számos hasznos funkciót kínál a MAX7219 vezérléséhez:

  • shutdown(int addr, bool status): Amikor az IC-k feszültés alá kerülnek, energiatakarékos módban vannak. A shutdown(0, false) utasítással ébreszthetjük fel, ahol az első paraméter az IC sorszáma a sorban, a második pedig, false esetén felébreszti, true esetén energiatakarékos módba küldi az IC-t. 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.
  • setIntensity(int addr, int intensity): A fényerő beállítása. 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.
  • clearDisplay(addr): A kijelző törlése. 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.
  • setLed(addr, row, col, state): Egyedi LED vezérlése. 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 a felülről második sor jobb oldalán található harmadik LED-et, akkor a következőt kell beírni: 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.
  • setRow(addr, row, value): Egy egész sor vezérlése. Az egy sorban található ledeket egyetlen függvénnyel is lehet kapcsolni. 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. A setRow() függvénnyel nyilvánvalóan sokkal gyorsabban kiírható egy kép, mint a setLed()-el, 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.
  • setColumn(addr, column, value): Egy egész oszlop vezérlése. Az előbbiek alapján már nem szorul magyarázatra a működés és a paraméterek. Az egyes ledeket itt is bináris számmal lehet a legvizuálisabban kijelölni. 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. Később az oszlop vezérlő függvény nem optimális volt, rengeteg adatot mozgat. Átírtam tehát a sor vezérlő függvényre. Megérte, mert észrevehetően gyorsabb lett a karakterképek váltása!

7 szegmenses Kijelzők Vezérlése

Nyilvánvalóan nem csak mátrix kijelzőt köthetünk a chip-re. 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áromjegyű 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. Nem próbáltam ki, mert nem használtam még 7 szegmenses kijelzőt a MAX7219-el, de biztosan működik.
  • setChar(addr, digit, value, dp): Korlátozottan betűket is meg tud jeleníteni egy 7 szegmenses kijelző. 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:

A 7 szegmenses kijelzőkön megjeleníthető karakterek a következők:

Érték Megjelenítés
0-9 Számjegyek
'A' A (nagybetű)
'b' b (kisbetű)
'C' C (nagybetű)
'd' d (kisbetű)
'E' E (nagybetű)
'F' F (nagybetű)
'H' H (nagybetű)
'L' L (nagybetű)
'P' P (nagybetű)
'-' Mínuszjel

Készíthetünk saját jeleket is, most a % jel helyére tettem egy szivecskét.

Gyakori Problémák és Megoldások a MAX7219 Használatakor

Nemrég arra kényszerültem, hogy még alaposabban megismerjem a MAX7219 led vezérlő IC-t. Már fentebb is említettem, hogy gondjaim voltak. Az első időjárás állomás verzióm amit megépítettem, csak egyetlen hibát produkált, nevezetesen azt, hogy tápfesz bekapcsoláskor (vagy áramszünet után) nem működött a led mátrix kijelzők egyike sem. Tápfesz bekapcsoláskor minden sötét maradt. Ha azonban reset gombot megnyomtam az Arduino-n, akkor már rendben működni kezdett minden kijelző.

Később építettem egy új időjárás állomást, kissé átalakított kijelzővel, erre már csak 3 led matrix panel került. Ehhez kb. 2 m kábelt szereltem, ez kötötte össze a kijelzőket az Arduino-val. Ennek a tápfesz bekapcsolásakor speciel semmi baja nem volt, azonban pár perc működés után zagyvaságokat kezdett kijelezni, aztán teljesen le is fagyott a kijelzés. Tápfeszre gyanakodtam, és valóban egy extra 100 mikroF szűrőkondi segített. Megnyugodtam, hogy megtaláltam a hibát! Azonban az új időjárás állomás a végleges helyére történő felszerelés után, igen sok problémát generált, szinte semmi nem működött, pedig a próbapanelen még rendben volt.

Kezdeti néhány hónapos működés után a led mátrix kijelző megint elkezdett kriksz-kraszokat kijelezni. Bosszankodva szétszedtem, és nagy duzzogva beforrasztottam még egy szűrőkondit. És ismét működött. Aztán kis idő múlva elindult újra a folyamat. Már gyanítottam, hogy nem a szűrőkondi a megoldás. Egyszer aztán teljesen elsötétültek a kijelzők, és immár semmit nem jeleztek ki. Ha ekkor reset-et nyomtam, esetleg megjavult néhány percre, vagy kapásból krisz-kraksz, és megint sötétség. Érdekes módon olyan eset is előfordult, hogy a három sorba kötött kijelzőből a legelső (amire az Arduino kimeneteit kötöttem) rendben működött, de a többi már sötét maradt.

Elkezdtem valami másra gyanakodni. Az Arduino-ba betöltött programban a ledmatrix könyvtárat használtam. Belenéztem a forrásába, és azt láttam, hogy minden időzítés nélkül küldi az adatokat, ami csövön kifér. Talán az a baj, hogy a 2 m vezeték sok zavart szed össze? Ahhoz, hogy ez kiderüljön, elkezdtem egy saját ledmatrix függvényt írni, amibe késleltetéseket építettem be, és így csökkentettem a CLK frekvenciáját. Azért írtam meg inkább, mert a letöltött könyvtár programja túl bonyolult volt, hogy biztonsággal belejavítsak. Ráadásul a github-ról letöltött függvénykönyvtár túl sokat tud számomra, nekem nem kellett ennyire univerzális eszköz. Az időjárás állomás programom egyébként is olyan nagy volt már, hogy alig fért a memóriába, és a változóknak rendelkezésre álló memória is alig volt már szabadon. A fordításkor az Arduino IDE ki is írta, hogy kevés a szabad memória, stabilitási gondok lehetnek. Akár ez is okozhatta a jelenséget, erre is utaltak nyomok.

Átalakítottam a DS18B20 hőmérők kezelését, ami felszabadított egy kicsi memóriát, és néhány hétig megint rendben volt minden. Ezzel a memória növelő program átalakítással a hűmérők meggyógyultak. A kijelzők is megjavultak, de aztán megint elromlottak. Mással próbálkoztam, elkezdtem a programban valamilyen kijelző írással kapcsolatos hibát keresni. Kezdetben a ledmatrix könyvtárnak azt a függvényét használtam, ami oszlopokat írt, és nem sorokat. Nem vettem észre, hogy így sokkal több adatot kommunikál a kijelző felé a program, hiszen egy sor írása nem egy, hanem 8 külön 16bites írási ciklussal csinálható meg. Amikor ezt kijavítottam, a kijelző hirtelen életre kelt, és néhány hétig hibamentesen működött. Ezt annak tudtam be, hogy kevesebb kommunikáció zajlott, és az esetleges vezeték zavarok ritkábban zavarták meg az adatátvitelt. Egyszerűen érthetetlen számomra, hogy mitől romlott el ismét. Mindegy, bármi is a baj, segíthet, ha optimálisabb a program, több a változóknak fenntartott memória, és ezzel együtt lelassítom a kommunikációt, hogy a 2m vezeték-ben esetleg megjelenő zavarok ne legyenek hatással. Az elképzelés az, hogy amikor egy adatot beállítok a MAX7219 bemenetén, akkor jó sokáig várok, (mondjuk 10-50mikrosec-ig) és csak ekkor kapcsolok felfutó élet a CLK bemenetre.

Más Típusú LED Mátrixok

Hozzál egy kis Times Square hangulatot otthonodba ezzel a remek 64x32 pixeles négyzet alakú RGB LED mátrix panellel. Ezeket a paneleket általában videofalak készítésére használják. New Yorkban a buszok és buszmegállók oldalán láthatóak, ahol animációk vagy rövid videoklipek megjelenítésére használják őket. Ez a változat az 5 mm-es osztású 64x32-es RGB LED mátrix. Vedd figyelembe, hogy nem használhatsz egy Arduino UNO-t ennek a méretnek a meghajtására, mert túl nagy! Ez nagyon hasonlít a 6mm Grid 32x32 RGB LED mátrix panelünkhöz, de körülbelül kétszer olyan széles, és messziről nagyon jól néz ki. Ez a mátrix 2048 fényes RGB LED-et tartalmaz, amelyek 64x32-es rácsba vannak elrendezve az elülső oldalon. Ezek a panelek 13 digitális pint (6 bites adat, 7 bites vezérlés) és egy jó 5V-os tápfeszültséget igényelnek, panelenként akár 4A-ig. Javasoljuk a szabályozott 4A 5V-os adapterünket, majd egy 2,1 mm-es jack csatlakoztatását. Ne feledd, hogy ezeket a kijelzőket FPGA-k vagy más nagy sebességű processzorok általi vezérlésre tervezték: nem rendelkeznek semmilyen beépített PWM vezérléssel. Ehelyett újra és újra át kell rajzolnod a képernyőt, hogy "kézzel" PWM-ezd az egészet. Egy 16 MHz-es Arduino Megan sikerült 12 bites színt (4096 szín) 40%-os CPU-használattal kipréselnünk, de ez a kijelző igazán ragyogna, ha bármilyen FPGA, CPLD, Propeller, XMOS vagy más nagy sebességű többmagos vezérlő vezérelné.

Remélem segítség volt az elinduláshoz ez a kis leírás. Nem szándékom bőlére ereszteni, mert mindenki saját magának fejleszt. A forrásoldalon található arra is kész forráskód, hogy karaktereket jelenítsünk meg.

tags: #arduino #nano #led #matrix #vezerles