Tartalom:
- A MAX7219 működése, műszaki adatok, felépítése
- Letölthető programkönyvtár függvényei és működésük
- A chip elemi szintű protokollja, vezérlés programkönyvtárak nélkül
- Saját kijelző meghajtó függvények
- Gyakorlati tapasztalatok a használat során, rossz földelés miatti hibák
- Vékony vezeték, elégtelen tápellátás, minden hiba, ami elkövethető
- Kijelző reset programfutás közben. Ez is kellhet!
—————————————————————————-
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 kétféle eszközben használják. 8×8-as LED mátrixkijelzőben, és maximum 8 digites 7 szegmenses kijelzőkben. Az alábbi ismertetőben összeszedtem az infókat egy LedControl nevű könyvtár függvényeinek használatához, de a legvégén találsz egy általam megírt saját függvényre is példát, ami akkor hasznos, ha kevés már a memória, és ezért kevésbé univerzális programra van szükséged, mint a LedControl.
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. Ekkor hasznosabb lehet inkább 8db 74HC595 léptetőregiszter, az képes folyamatosan áramot adni egy-egy LED-nek! 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 kell elhasználnunk az Arduino 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
- Din – 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. Minden 8-as LED csoporthoz tartozik memória, amibe beléptethetjük, hogy mely LED-eknek kell világítania.
- 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.
- Chip select – Aktív alacsony szint. Amikor erre a bemenetre alacsony szint kerül, akkor lehet az órajel felfutó éleivel adatokat írni a chip-be, illetve a sorban felfűzött chip-ekbe.
Műszaki adatok
Paraméter | MAX7219 |
Tápfesz: | 4,0 V ~ 5,5 V |
Tápáram: | 330mA |
A szegmens meghajtó árama | 40mA |
Szegmens frissítés | 500–1300 Hz (800 Hz tipikus) |
órajel | legfeljebb 10MHz |
MAX7219 adatlap: http://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf
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! Alább egy táblázat annak, aki valamilyen rejtélyes okból ezzel az ellenállással akarna fényerőt beállítani:
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 léptetőregiszter. Az első 8 bit meghatároz egy címet, a második 8 bit pedig maga az adat, amit a címmel meghatározott belső memóriába be kell írni (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, az első modul Din bemeneté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ó, 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 (azt hiszem objektum példánynak nevezik szakszerűen, de ehhez nem igazán értek), 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(dinPin, 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 0..7 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 é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. 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 led-eket, energia takarékos mód
lc1.shutdown(0,false); //visszakapcsoljuk a led-ek fényét
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.
A kijelző fényerő beállításának lehetőségei
Három tényező határozza meg a kijelző fényerejét.
- a kijelző szegmens áramát beállító RSET ellenállás értéke, amiről már az 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örnyezet 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 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. 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ék | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Led On? | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
Sor-érték | 128 | 0 | 32 | 16 | 0 | 0 | 2 | 0 |
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énnyel nyilvánvalóan sokkal gyorsabban kiírható egy kép mit 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. 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. Kicsit később még részletesen olvashatsz a problémáról. Én igen sokat tanultam az esetből. 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. Megérte, mert észrevehetően gyorsabb lett a karakterképek váltása!
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á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. 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, illetve pár sorral lejjebb találunk a számjegyenként történő törlésre is példát.
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)
Saját kezelőfüggvény
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 történt, hogy a kezdetben jól működő időjárás állomásom led mátrix kijelzői idővel vacakolni kezdtek. Már kezdettől fogva bajom volt velük. 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ő. Mivel évente egy-két áramszünetünk volt akkoriban, nem okozott nagy lelki konfliktust és nem törődtem a hibajelenséggel. Telt múlt az idő, és é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. Mivel már volt tapasztalatom, kapásból a véglegesnek szánt panelt építettem meg, amire 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. Vártam, hogy mi történik. És történt is valami! Időnként magától helyreállt a kijelzés. Kis idő múlva megint kriksz-karaksz, aztán megint jó. 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. Azt elfelejtettem megemlíteni, hogy a DS18B20 hőmérők egyike szintén vacakolt, állandóan paritás hibát jelzett a kiolvasás, de a négyből mindig csak az egyik. 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. Esetleg a párt tehet róla, vagy keveset adakoztam a templomban?
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. Várhatóan az eltelt időben a hosszú vezetéken lezajlanak a tranziens jelenségek, beáll az adat bemeneten a jelszint, és nem fog váratlan értéket beolvasni a MAX7219.
Ahhoz, hogy megírjam a saját vezérlő programomat, meg kellett érteni a MAX7219 írásnak protokollját. Tanulmányozni kezdtem tehát az adatlapot. Szeretném is közreadni azt, amit megfejtettem belőle.
Lássuk először az adatok írásának idő diagrammját. Ami ebből számomra lényeges volt, hogy a CS bemenetre kapcsolt 0 szint (engedélyezés) után, várni kell egy kis időt amíg mehet az első órajel felfutó éle (t CSS, nyíl mutatja). Azt régebbi tapasztalatamból tudom, hogy itt nanosec időkről van szó, így ide biztosan jó lesz néhány mikrosec várakozás. A másik lényeges információ, hogy az adatbemeneten lévő jelszint beléptetése az órajel bemenet felfutó élénél történik meg, és jelzi is az ábra, hogy itt is kell egy kis várakozási időt hagyni (t DS, nyíl mutatja), tehát az adat bemenetre előbb kell odarakni az adatnak megfelelő jelszintet, mint ahogy megjelenik a felfutó él. Ebben semmi meglepő nincs szövegesen is leírták az adatlapban.
Most következzék az a rész, hogy milyen adatokat is léptethetünk be az adatbemeneten a chip-be. A kijelzőnek egy írással 16 bit információt kell átadni. Ebből 8 bit megcímzi a chip adatregiszterét, a következő 8 bit pedig maga az adat, amit a megcímzett regiszterbe beleírunk. Így néz ki egy írási bitsorozat:
Ahhoz, hogy a chip megjelenítse a 64 led ponton az általunk megkívánt információt, 8db 8 bites adatregiszterbe kell beírni soronként az információt. Minden sorban az 1 esetén ég a led, 0 esetén meg nem. Ezek az adatregiszterek. Van ezen kívül még néhány vezérlő regiszter, amivel a működést lehet befolyásolni, fényerőt állítani (PWM módon, de azt maga a MAX7219 IC csinálja a megfelelő regiszter tartalma alapján), kikapcsolni a kijelzőt energiatakarékos módba stb. Alább az egyes regiszterek felsorolása. Ebben a táblázatban rögtön azt is láthatjuk, hogy milyen bináris értéket kell az ADRESS bitekben megadnunk, hogy a második 8 bit adata a megfelelő regiszterbe íródjon.
Lássuk is sorban status regiszterek működését.
Shutdown regiszter:
Tehát a shutdown regiszterbe 1-et kell írni, ha azt akarjuk, hogy megjelenlenek a beírt információk a kijelzőn. Ha 0-at allítunk be, akkor a chip működik tovább, lehet bele adatokat írni, mindössze lekapcsolja a led-eket, így az áramfelvétel drasztikusan csökken. Ugyanezt érjük el azzal is, ha az adatregiszterek mindegyikébe 0-át írunk. Így lehet a kijelzőt törölni. A shutdown értelemszerűen nem törli a kijelzőt, csak kikapcsolja.
Fényerő regiszter:
Erről nem kell sokat regélni. 16 fokozatban lehet fényerőt állítani, amit a led áramának kapcsolgatásával, illetve a led áram kitöltési tényezőjének állítgatásával ér el a chip. A 0 érték a minimális fényerő. Itt már világit.
Decode mód regiszter:
Ez a regiszter akkor használatos, ha nem mátrix panelt kötünk a MAX7219 kimeneteire, hanem maximum 8db 7 szegmenses led számkijelzőt. Ekkor nem kell szenvednünk azzal, hogy kiszámoljuk melyik számjegy kijelzéshez melyik biteket kell az adatregiszterekben 1-re állítani. Megteszi helyettünk a chip, beírjuk az adatregiszterbe a számot, amit szeretnénk látni, chip pedig megjeleníti a kijelzőn. Persze ehhez a kijelző kivezetéseit jól kell bekötni. Ezzel azonban nem foglalkoztam, így ezt fejtse meg az akinek szüksége van rá. Minden esetre nekem ebbe a regiszterbe 0-át kellett írni, mert nem kell dekódolás a mátrix kijelzőhöz. Úgy tapasztaltam, ez a gyári alapbeállítás, ha tápot adok a chip-nek akkor erre áll be a regiszter tartalom.
Scan-Limit Register:
Ennek a regiszternek szintén csak akkor van jelentősége, ha 7 szegmenses számjegyek meghajtására használjuk a chip-et. Ha 8db 7 seg ledet kapcsolunk rá, akkor mindegyik csak 1/8-ad ideig világít. Emiatt a kijelzők fényereje lényegesen kisebb, mintha külön-külön mindet folyamatosan árammal hajtanánk meg. Persze pont ez ennek a chip-nek a lényege, hogy nem kell minden led meghajtáshoz külön kivezetés. Azonban ha kevesebb digitet használunk fel, pl. egy órában csak 4 számjegy kell, beállíthatjuk a számjegyek számát, és növekedni fog a fényerő. Ennek oka, hogy a chip nem fog foglalkozni a fennmaradó számjegyeknek megfelelő sorokkal, azokat ki fogja hagyni a megjelenítés ciklusából, és így hosszabb ideig fognak világítani a fennmaradó digitek. Bocsi, de ezzel sem foglalkoztam, nincs is kéznél ennyi 7 seg kijelzőm, hogy kipróbáljam, de biztosan működik. Megjegyzem, az időjárás állomásomban pont azért használtam 74LH595 léptetőregisztert, mert az képes folyamatosan árammal meghajtani a led-et, így nagyobb a fényerő. A nagy fényerő meg azért kell, mert időnként rásüt a nap. Még max. folyamatos áramnál is alig látszik a kijelzett érték ilyenkor. Lakásban azonban tökéletes lenne egyetlen MAX7219 az összes 7 szegmenses kijelzőnek amit használtam.
És akkor következhet a saját ledmátrix vezérlő program. Igazán nem nagy durranás. Én úgy gondoltam, egyetlen függvényt írok, ami egy 16 bites adatot fog kiléptetni a három kivezetésre. A működés tök egyszerű: a függvénynek átadok két byte-ot, először az egyiket, aztán a másodikat léptetem ki az adat kivezetésre. Közben a fenti protokoll szerint kapcsolgatom a CS és CLK kivezetéseket. A léptetések közben a megfelelő pontokon a delayMikros() függvénnyel késleltetéseket építettem be. Egy karakterkép kiléptetése 8 db függvényhívás a 8 sornak megfelelően. Ha valamelyik státus regisztert kell írni az is egy-egy függvényhívás.
/*********************************** * Ledmatrix kivezetések bekötése: * * D10 - CS * * D11 - CLK * * D12 - DIN * ***********************************/ const byte adat=12; //MAX7219 adat in bemenetének vezérlésére szolgáló Arduino kimenet száma const byte cs=10; //MAX7219 CS bemenetének vezérlésére szolgáló Arduino kimenet száma const byte clk=11; //MAX7219 CLK bemenetének vezérlésére szolgáló Arduino kimenet száma const byte idozites=50; //A késleltetetés ideje mikrosecundum-ban long kezdoido; //az időméréshez használt változó, amit most nem használok void setup() { // Serial.begin(9600); //az időméréshez használt sor, amit most nem használok pinMode(adat,OUTPUT); pinMode(cs,OUTPUT); pinMode(clk,OUTPUT); digitalWrite(cs,1); //a max7219 cs bemenete 1-en van, amikor nincs kiválasztva, és nem kommunikálunk vele ledmatrix(9,0); //Decode mód kikapcsolása ledmatrix(11,7); //Scan limit regiszter beállítása (8 számjegy kijelzését kapcsoljuk be) ledmatrix(10,0); //Intenzitás minimum ledmatrix(12,1); //Shutdown kikapcsolva } void loop() { // kezdoido=micros(); //az időméréshez használt sor, amit most nem használok ledmatrix(1,85); ledmatrix(2,170); ledmatrix(3,85); ledmatrix(4,170); ledmatrix(5,3); ledmatrix(6,15); ledmatrix(7,63); ledmatrix(8,255); delay(1000); //időmérés esetén ezt a sort kell kimmentezni ledmatrix(1,0); ledmatrix(2,0); ledmatrix(3,0); ledmatrix(4,0); ledmatrix(5,0); ledmatrix(6,0); ledmatrix(7,0); ledmatrix(8,0); delay(1000); //időmérés esetén ezt a sort kell kimmentezni // Serial.println(micros()-kezdoido); //az időméréshez használt sor, amit most nem használok } void ledmatrix(byte felsobyte, byte alsobyte) { digitalWrite(cs,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok delayMicroseconds(idozites); //késleltetés mielőtt bármit csinálunk for (byte i=0;i<8;i++) { //először a felsobyte adatot fogjuk kiléptetni bitenként jobbról balra digitalWrite(adat,(felsobyte<<i) & 128); //Minden ciklusban eggyel többször léptetjük balra, és a baloldali bitet kimaszkoljuk delayMicroseconds(idozites); //késleltetés (adat már az adatvezetéken van) digitalWrite(clk,1); //beállítunk a clk vezetéken eg felfutóélet, ennek hatására belép az adat a chip-be delayMicroseconds(idozites); //késleltetés (adat még mindig az adatvezetéken, órajel felfutóéllel beléptetve) digitalWrite(clk,0); //levesszük az órajel vezetéken az 1-et, órajel lefutóél ezzel együtt változhat az adat is } for (byte i=0;i<8;i++) { //az alsóbyte-ot is kiléptetjük, ugyanaz mint előző ciklusnál, bitenként léptetünk digitalWrite(adat,(alsobyte<<i) & 128); delayMicroseconds(idozites);digitalWrite(clk,1);delayMicroseconds(idozites);digitalWrite(clk,0);delayMicroseconds(idozites); } digitalWrite(cs,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn }
A program magáért beszél. A setup() részben beállítom a státus regisztereket, a loop()-ban pedig másodperces ciklusban más-más karakterképet írok ki a kijelzőre. Fontos tanulság, hogy a scan limit regisztert be kell állítani, mert tápfesz ráadásakor nem alapértelmezett, hogy minden számjegyet megjelenítsen. Pedig ebben az üzemmódban nem is karaktereket jelenítünk meg, mivel decode mód nincs beállítva. Bár karaktereket attől még lehet megjeleníteni, mert nincs dekódolás!
Azért építettem fel így a demó programot, hogy lássam és mérhessem a késleltetések hatását. Pl. a ha 1milisec-re állítom az órajel váltások közötti időt, akkor már jól láthatóan soronként jelenik meg az infó a kijelzőn. Ez nem is csoda, hiszen egy órajel periódus 2msec, így egyetlen regiszter írása 16×2=32misec. Mivel 8 regisztert kell írni, ami 256msec, ami negyed másodperc. Kísérletezgetéssel azt állapítottam meg, hogy 50mikrosec tökéletesen megfelelő késleltetés, ekkor egy órajel periódus idő 100mikosec, vagyis kb. 10Khz. Méltán számíthatok arra, hogy ekkora késleltetési időkkel nem fog számítani a vezeték hossza. Egy karakterkép kiléptetésének ideje ekkor 18000mikrosec. Ezt nem kiszámoltam, hanem megmértem. A példa programban benne is hagytam a szükséges sorokat, csak kikommenteztem. A méréshez a micros() függvényt használtam. Lekérdeztem a loop() elején és végén az eltelt időt, miközben kétszer frissítettem a kijelző teljes tartalmát. A delay()-t természetesen kikommenteztem a mérés idejére. A soros porton kijelzett adat 36000mikrosec volt, de az két karakterkép. Ebből következően egy karakterkép frissítése 18milisec. Vagyis kb. 50 karakterkép váltást lehet csinálni 1 másodperc alatt, menne a mozgófilm.
Kíváncsiságból megírtam teljesen ugyanezt a funkcionalitást a ledmatrix könyvtár függvényeivel. Ebben ugyebár nincs semmi késleltetés.
/*************************************************** * Ledmatrix kivezetések bekötése: * * D10 - CS * * D11 - CLK * * D12 - DIN * * LedControl(DIN,CLK,CS,sorbakötött modulok száma) * ****************************************************/ #include "LedControl.h" LedControl lc=LedControl(12,11,10,1); //long kezdoido; void setup() { Serial.begin(9600); lc.shutdown(0,false); //shutdown kikapcsolva lc.setIntensity(0,0); //intenzitás minimum } void loop() { //kezdoido=micros(); lc.setRow(0,0,85); lc.setRow(0,1,170); lc.setRow(0,2,85); lc.setRow(0,3,170); lc.setRow(0,4,3); lc.setRow(0,5,15); lc.setRow(0,6,63); lc.setRow(0,7,255); delay(1000); lc.setRow(0,0,0); lc.setRow(0,1,0); lc.setRow(0,2,0); lc.setRow(0,3,0); lc.setRow(0,4,0); lc.setRow(0,5,0); lc.setRow(0,6,0); lc.setRow(0,7,0); delay(1000); //Serial.println(micros()-kezdoido); }
Ugyanezzel a módszerrel megmértem a végrehajtási időt is. 3632mikrosec-nek adódott, ami ezt jelenti, hogy egy karakterkép kiírása 1,8milisec. Pont tízszer gyorsabb, mint az én függvényem. Majdnem elfelejtettem megemlíteni, hogy mindkét programban egy modult használtam, bár van jelenleg is 4 ledmatrix modulom. Kísérletezgetek még egy kicsit, mert ugyebár az időjárás állomásomon három modul van. De most elfogyott az időm. Folyt .köv.!
Rossz hírem van magamnak, a saját ledmatrix() függvény nem oldotta meg a problémámat. Kicseréltem az időjárás állomásban az Arduino nano-t egy olyan példányra, amiben a saját függvénnyel írogatom a kijelzőt. A hibajelenség gyakorlatilag ugyanaz maradt, a kijelzők nem működnek. Tehát valamilyen külső körülmény befolyásolja a működést. Közben egyre mélyebben ástam bele magam a mátrix kijelző vezérélésébe, és eljutottam a shiftout() függvényhez, ami ténylegesen az adatok kijelzőre küldését végzi. Csináltam egy próba programot, hogy megmérjem ennek a függvénynek működési idejét. Különösen az órajel kimeneten megjelenő frekvencia érdekelt. Írtam egy programot a méréshez:
//az időmérési kísérletet egy 74HC595 shift regiszterrel végeztem //a 74HC595-re egy 7 szegmenses kijelzőt kötöttem const byte SH_CP = 8; //chip 11-es láb, órajel bemenet (felfutó élre lépteti be az adatot) const byte ST_CP = 9; //chip 12-es láb, Latch bemenet (beléptetett adat kimenetre írása felfutó éllel const byte OE_negalt = 10; //chip 13-as láb, kimenet engedélyező (pwm fényerő szabályozáshoz) const byte DS = 11; //chip 14-es láb, adatbemenet long kezd; long veg; void setup() { Serial.begin(9600); pinMode(7, OUTPUT);digitalWrite(7,LOW);delay(10);digitalWrite(7,HIGH);delay(10); //kap egy reset jelet a chip pinMode(SH_CP, OUTPUT); pinMode(ST_CP, OUTPUT); pinMode(OE_negalt, OUTPUT);analogWrite(OE_negalt,253); //kis fényerő, hogy ne világítson a szemembe pinMode(DS, OUTPUT); kezd=micros(); digitalWrite(ST_CP,0); //Latch bemenetre 0-at kapcsolunk, jöhetnek az adatok shiftOut(DS, SH_CP, MSBFIRST, 255); //adatok kiléptetése, az adatvezetéket és az órajelet a shiftout() vezérli shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); shiftOut(DS, SH_CP, MSBFIRST, 255); digitalWrite(ST_CP,1); //Latch bemenetet vissza állítjuk 1-re, a beléptetett adtok megjelennek a //shiftregiszter kimenetein. Csak egy shiftregiszterem volt, de sokkal több //adatot léptettem ki a bemenetére, nyilván csak az utolsó 8 bit tárolódik //a 74HC595 chip-ben. veg=micros(); Serial.println(veg-kezd); //végrehajtási idő kiírása (Arduino UNO-n 988mikrosec) } void loop() { }
A program 10 shiftout() függvényhívást végez, és a végrehajtási idő (amit kiírok a végén a soros portra) 988 mikrosec. Mivel ez 10×8 bit írását jelenti, az órajel kimeneten 80 impulzus jelenik meg. Vagyis egy impulzus ideje kb. 988/80=12,35 mikrosec. Ez kb. 81kHz frekvenciának felel meg. 2m vezetéken ekkora frekvenciának át kell mennie érzésem szerint, tehát a saját függvénnyel ezért nem mentem semmire. Marad a tápegység, vagy valamilyen más külső körülmény, ami zavarja a működést.
Közben hideg lett, és egyszer csak elkezdett működni magától a kijelző. Két napig minden rendben volt. Aztán egy napra 14 fokra emelkedett a hőmérséklet, és ismét zagyvaságok jelentek meg a kijelzőn, kis idő múlva pedig újra teljesen sötétek a kijelzők. Talán a tápegység lehet a ludas, hamarosan kicserélem. Azért lehet más is. Eddig nem gondoltam rá, de a akár zavarjelek is okozhatják a problémát. Van egy 1,5KW-os naperőművünk itthon. Most vettem észre, hogy szerencsétlen módon az időjárás állomás vezérlő egységének dobozát a naperőmű invertere mellé szereltem. Ez ugyebár egy kapcsolóüzemű tápegység, ráadásul nem is kicsi teljesítménnyel. Télen nem sokat süt a nap, kicsi a teljesítmény, talán ezért működik újra a kijelző. A meleg napon a nap is sütött, és újra elromlott a kijelző. Nem meggyőző érv, mert éjszaka se működik az inverter, a kijelzők mégsem működnek.
Az utolsó sorok írása közben eltelt újabb néhány hét, és rávettem magam, hogy a nagy hideg ellenére tovább kísérletezzek. Szétszedtem a központi vezérlőt (amin a két Arduino nano található), és barkácsoltam rá egy plusz föld kivezetést. Így már nagyon egyszerűen egy külső tápegységről is tápot adhattam a kijelzőknek. Egy 2,5A-es USB telefontöltőt használtam. Természetesen nem működött, túl egyszerű lett volna. Nem volt mit tenni, szétszedtem a kijelző oldalt is. Már nem emlékeztem rá hogyan is lettek ott a dolgok bekötve, felmerült bennem a gyanú, hogy esetleg nem tökéletes a földelés, vagy valami más rendellenességet találok. Minden rendben volt látszólag, kimértem a föld és a jelvezetékeket, nem volt semmi megszakadva. Azonban felfigyeltem arra, hogy a mátrix kijelző táp és jelvezetékeit meglehetősen vékony vezetékből készítettem, és ráadásul a mátrix „lánc”-nak csak az egyik végét kötöttem be. Ez a kép mutatja azokat a szürke sorkábeleket, amiket használtam. A bal oldali kijelző a lánc vége:
Ebben az esetben azonban egyik mátrix a másiknak adja át a tápfeszt egy nagyon vékony vezetéken. Ezek a vezetékek nem hosszúak, de hátha mégis ez gondot okoz. Többé kevésbé jól hozzáférhető volt a „lánc” másik vége (bal oldali kijelző a képen), és egy vastagabb vezetékkel bekötöttem oda is a földet és a +5V-ot. …és csoda történt. Azóta minden rendben működik.
Még sincs minden rendben! Egyik nap barkácsoltam, és beindítottam a gyorsvágót. Nem csak a mátrixkijelzők, hanem az egész időjárás állomás lefagyott. Összevissza világított minden kijelző. Hamarosan ismét új verziót építek, ezért most ezzel nem foglalkozom, ha elkészül az új időjárás állomásom (már lesz a lakásban beltéri egység is), előveszem a gyorsvágót és újra nekifutok a hibakeresésnek!
Eltelt pár hónap, és újabb tapasztalatokkal okosodtam. Nem csak a tapasztalat van meg, hanem a hiba oka is. Tervbe volt véve az időjárás állomásom módosítása, mert szerettem volna, ha 433Mhz-s rádió adókkal beküldi az adatokat a lakásba. Időközben már megint elkezdtek krikszkrakszok megjelenni a kijelző. Ez lendületet adott az átépítésre is, hiszen olvashatatlanok voltak a megjelenő betűk. Előtte hónapokig működött így már biztos voltam benne, hogy nem a programmal van a baj. Az átépítéshez egyébként is szét kellett szerelni a kijelzőt és a vezérlő elektronikát, így behoztam a lakásba. Az átalakítások nem a kijelzőt érintették, de a lakásban könnyebb a fejlesztés. Nagyon előrelátó voltam, és a kijelzőt a falon átmenő vezeték miatt úgy konstruáltam, hogy a lakásban asztalon közvetlenül hozzá lehet csatlakoztatni a vezérlő elektronikához. Persze a végleges helyén a téglafalon átmegy egy „hosszabbító” vezeték amin azonosak a csatlakozók. Ez a vezeték lényegében csak egy hosszabbító. Szóval behoztam a cuccot a lakásba, közvetlenül összedugtam a hosszabbítás nélkül és működött. Nézegettem egy darabig, míg rájöttem az összefüggésre: Rövid vezeték- működik! Hosszú vezeték – nem működik! Rövid vezeték – működik! Hoppá! Hosszú a vezeték! Azonban az adatok kiléptetésének a lassításán már túl vagyok, és nem használt. Visszaépítettem mindent a helyére, és immár a 7 szegmensek kijelzők is elromlottak. Időnként ott is összevissza világítottak a szegmensek. Hát ez remek! Már semmi nem működik, ennél jobb állapot nincs, most van esély a hiba megfejtésére. Feltételeztem, hogy a mátrix kijelzők és a 7 szegmenses kijelzők hibájának oka azonos, ezért most a 7 szegmenses kijelzővel folytattam. A mátrix kijelzőt már untam, és nem is boldogultam vele! Első lendületből arra gondoltam, hogy túl gyors a shiftOut() függvény, amivel kiléptetem az adatokat a 74HC595 léptetőregiszterekre, amik a led kijelzőket hajtják meg. Mivel nem találtam lehetőséget a shiftOut függvény lassítására, írtam egyet magamnak (találtam a neten). Ez a forrása:
void shiftOutx(uint8_t dataPin, uint8_t clockPin, byte val) { int i; for (i = 0; i < 8; i++) { digitalWrite(dataPin, !!(val & (1 << (7 - i)))); delayMicroseconds(10); digitalWrite(clockPin, HIGH); delayMicroseconds(10); digitalWrite(clockPin, LOW); delayMicroseconds(10); } }
Ennek csak három paramétere van, mert nem volt szükségem a bitsorrend állítására. Természetesen nem használt, sőt rontott a működésen. Ahogy növeltem a késleltetési időket a delayMicrosecond()-al, egyre zavarosabb lett minden a kijelzőn. Tehát nem a sebesség a gond. Mivel megfigyeltem, hogy csak az első néhány számjegy romlik el, valahol a bitsorozat elején keletkezik a hiba. Beugrott, hogy esetleg a kijelző tekintélyes 7-800mA áramfelvételével függhet össze a dolog, azaz amikor változnak az adatok az áramfelvétel változása okozza a hibát. Az áramfelvételről tervezéskor teljesen megfeledkeztem, nem is tudtam mennyi, most mértem meg először. Pontosabban sejtettem, hogy a tápegységgel lehet valami, ezért egy dögös tápegységet tettem már előzőleg a szerkezetre, ami szerencsémre kijelezte az áramerősséget is. Most hogy már sejtettem valamit, változtattam a programon. Az adatok kiléptetése előtt kikapcsoltam a kijelzőt, és amikor minden adatot kiléptettem, akkor kapcsoltam vissza. Erre a 74HC595 chip Output Enable kivezetését használtam, amivel egyébként a fényerőt szabályoztam PWM jellel. Ekkor már nyomon voltam, és megsejtettem, hogy a PWM jel okozhatja a galibát, ami 400Hz körüli frekivel ki és bekapcsolgatja a közel 1A-es terhelést. Így azonban az adatok léptetésének idején minden sötét, nincs is áramfelvétel. Természetesen a 74LS595 chip-ek léptetik az adatokat. Bár adatok váltásakor a kijelző villant egyet, minden probléma megoldódott. Tehát már tudtam, hogy csak akkor van hiba, ha van áramfelvétel változás. Innen már nem nagy kunszt kitalálni, hogy valamelyik vezetékkel van a baj. Megnéztem a „hosszabbító” vezetéket, mit is barmoltam el. Megdöbbenve vettem észre, hogy azt a közel 1A áramot egy riasztóvezeték egyik erén engedtem át. Spóroltam ugyanis, mert nagyon kicsi volt a lyuk a téglafalon. Kerítettem gyorsan egy 220V-os hosszabbítót és azon vittem át a vezérlőtől a kijelzőre az 5V tápot megkerülve a falat. Teljes siker. Be kellett húzni még egy vezetéket a falba, jó vastagot, és azóta működik minden kijelző! Tudom, hogy túl hosszan írtam le a folyamatot, de szerettem volna ha olvasóim is ugyanúgy megszenvednek az információért mint én!
…és még sincs vége! Eltelt néhány hét, és újra kezdődött!! Krikszkrakszok, vagy éppen az összes pont világít teljes fényerővel egy-egy modulon! Kész idegbaj! Olvasgattam a neten, és fórumokban többen panaszkodnak a jelenségre, de okosat senki nem mond! Azonban a még okosabbak szintén a tápegységre gyanakodnak, és erre gyanakszom én is. Olyan nagy marhaságok is megjelentek a profi fórumozók részéről, ami már Hofi Géza poénjaival vetekszik! Ugyanis valaki kiszámolta az áramfelvételt egy négy tagból álló kijelzőn. Egy led 20mA, egy modul az 64x20ma és még ennek a négyszerese = 5,12A!!! Dögös táp kéne, ha ezt bevenném! De félre a tréfával! Most már tényleg meg van a megoldás! A kényelmem az oka mindennek. Egy 2A-es mobiltelefon töltőt használtam tápnak. 5A nem ad le, de nem is kell annyi, max. 1A-el kell tervezni, az is csak csúcsban néha néha. Valahogyan el kell vezetni a töltőből az áramot, és ehhez egy USB kábelt nyírtam szét. Az USB csatlakozóból a kábelen elég vékonyka vezeték jött ki, de gondoltam 10cm-en ez nem lesz gond. Most végre vettem a fáradságot és kicipeltem egy feszültségmérőt a kábelhez, és rámértem. 4,7V és hullámzik! Csak magamat szidhatom, azóta is kukoricán térdepelek a sarokban. Látszik, hogy amatőr vagyok!
Kerestem gyorsan egy 5V-os konnektoros kapcsoló üzemű tápegységet, és az abból kivezetett vastag kábelt kötöttem a kijelző felé menő villanyvezetékre. Úgy 16A áramerősségre tervezett kábelen immár „kiért” az 5V a kijelzőig. Ki lehetett venni a programból az adatküldés idejére történő shutdown parancsot is. Világíthat közben.
Tanulság: nem elég a nagy teljesítményű tápegység, „igazi” kábellel kell vinni az áramot a fogyasztóig!
Ez a kijelző az őrületbe kerget! Hónapok teltek el, és megint jelentkezett a hiba! Igaz, hogy akkoriban tapasztaltam újra, amikor hőhullám söpört végig az országon, és 40-42 fokot jelzett a hőmérő. Azóta azonban már jóval hidegebb van, 20-30 fok között, de a hiba megmaradt. Annyi a hiba jellegében a változás, hogy most általában a 3 kijelzőből a sorban legutolsó teljesen elsötétül, a többi kijelző pedig csak megzavarodik, a kijelzett karakter felismerhető, de néhány olyan led is világít, aminek nem kellene. Egy reset minden esetben segít, és csak órák vagy napok múlva tapasztalom újra a problémát. Két okot tartok valószínűnek, a tápegység a melegben megromlott, mert nagy a fehérje tartalma, a másik lehetőség, hogy megharagudott rám a a mátrix kijelző istene! Ideje áldozatot bemutatni. Eszembe jutott, hogy áldozatként kukába dobom az időjárás állomásomat, de meggondoltam magam az utolsó pillanatban. Eszembe jutott, hogy régebben sokkal súlyosabb hibajelenségnél segített, ha kikapcsoltam az adattovábbítás alatt a világító ledeket. Sajnos ettől a kijelző mindig villant egyet! Ezért most új módszerrel kísérletezek, csak minden órában egyszer kapcsolom ki a mátrix kijelző ledjeit az adattovábbítás idejére. Így néha majd észreveszem, ha elromlik, és ha megjavul max egy órán belül, akkor azt is. Kísérlet indul!
A kísérlet nem sikerült! A kijelző hibája nem javult meg attól, hogy az adatok kiküldése előtt kikapcsolom a kijelzőket (shutdown be). Azonban a koncentrált figyelem meghozta gyümölcsét. Megfigyeltem, hogy a kijelző háromféle hibát produkál.
- Valamelyik kijelző a háromból teljesen elsötétül, semmi nem jelenik meg a továbbiakban rajta.
- Valamelyik kijelző, gyakran mindhárom, összes ledje világít, és így is marad.
- Valamelyik kijelző néhány sora elsötétül, a többi sorban azonban a pontok nagyobb fényerővel világítanak.
Az első esetben a kijelző egy shutdown be parancsot kap. Ezen az eseten segített a program módosításom, hiszen a kommunikáció végén egy shutdow ki parancsot adok ki, ami visszakapcsolja az alvó kijelzőt! És valóban, miután ezt beépítettem, már nem tapasztaltam azt, hogy valamelyik kijelző elsötétülne. Da a többi hiba megmaradt. A második esetben bekapcsolódik a kijelző test funkció. Mivel a program könyvtárban nincs függvény ennek kezelésére, semmilyen módon nem kapcsolja vissza a program, és így is marad. A harmadik esetben valószínűleg egy scanlimit parancsot kap, ami kikapcsolja a parancsban megadott led sorokat, a többi így nagyobb fényerővel tud világítani. Azt hiszem scanlimit kezelő függvény sincs a könyvtárban. Ezen tapasztalatok alapján már van működő megoldásom.
Mivel a kijelző inicializálása beállítja a az alap paramétereket, kezdetben a kijelző jól működik. Amikor aztán a zajos környezetben sérülnek az adatok és valamelyik értelmezhető parancsot kapja meg a kijelző véletlenül, végre is hajtja. Azonban a programban nincs lehetőségem, hogy minden rossz beállítást helyrehozzak, de a program reset segít. Tehát program futása közben is kellene tudnom reset eljárást végrehajtani, ami nem csak a program indulásakor állítja alaphelyzetbe a kijelzőket, hanem bármikor. Gyorsan meg is írtam ezt a reset eljárást. Valamilyen számomra is ismeretlen megérzésből csak percenként egyszer küldöm ki a reset parancs sorozatot. Magam sem tudom, hogy miért nem minden kijelző tartalom változtatás előtt, hiszen nem kerülne semmibe, nincs számottevő ideje a kiküldésnek és nem lassítja a működést. De már így csináltam, így marad! Azóta, hogy a programba beillesztettem a percenkénti kijelző resetet, már soha nem látok hibás kijelzést (egy hete már működik). Valószínűleg továbbra is keletkeznek hibák a kommunikációban, de maximum egy percen belül a program helyrehozza a kijelzést a resettel, amit mindig kiküld a kijelzőre, ha kell, ha nem.
Íme a reset eljárás forrása! Sajna a kezelő könyvtártól független, tehát a ledmatrix függvényben megadott kivezetés számokat be kell másolni a megfelelő helyre, ezért kicsit átalakítottam a programot a legelején is. Ez itt nem a teljes program, csak egy részlet, akinek hasznos, az érteni fogja, mit hová kell beírni. A matrix_reset() függvény tetszőleges ponton meghívható a programban.
#include "LedControl.h" const byte MATRIX_MOSI=8; const byte MATRIX_CLK=7; const byte MATRIX_CS=6; LedControl lc=LedControl(MATRIX_MOSI , MATRIX_CLK , MATRIX_CS ,3); void matrix_reset() { //az összes chip-re kiküldjük sorban az alapbeállításokat matrix_comm(15,0); //displaytest kikapcsolása matrix_comm(9,0); //decode mód beállítása matrix_comm(11,7); //scanlimit beállítása matrix_comm(12,1); //shutdown kikapcsolása } void matrix_comm(byte parancskod,byte adat) { //három chip lett sorbakötve, ezért háromszor küldünk ki minden parancskódot. //A chip-ek egymásnak adják tovább az adatokat digitalWrite(MATRIX_CS,LOW); //most kezdődik az adatok kiléptetése a chip-ekre for(int i=0;i<3;i++) { //matrix_beleptet(parancskod,adat); shiftOut(MATRIX_MOSI,MATRIX_CLK,MSBFIRST,parancskod); //ez jelöli ki a parancsot shiftOut(MATRIX_MOSI,MATRIX_CLK,MSBFIRST,adat); //ez a parancs értéke } digitalWrite(MATRIX_CS,HIGH); }
Sajna ezt az eljárást 3 láncra fűzött kijelzőre írtam meg, tehát nem általános megoldás, újrafelhasználás esetén „testre kell szabni”! Valójában az időjárás állomásomban teljesen kicseréltem a ledmatrix könyvtárat, már semmit nem használok belőle, ezért született a matrix_comm() függvény. Hamarosan megjelenik majd az időjárás állomásom új programja, és abban benne lesz a teljes forrás, ami a kijelzőt kezeli. Ez a szerkezet már olcsó RF433Mhz-s adóvevővel beltéri egységnek is küldi az adatokat, valamint a beltéri egységen beállított pontos időt átszinkronizálja az időjárás állomás saját órájára. Vége a nyári időszámítás óraállítgatási gyötrelmeinek! Már csak ezért is, mert a nyári időszámítás kezelése is automatikus lett! De ez is elég speciális megoldás, ezért nem erőltettem a teljes forrást, a megoldás elvét tartom lényegesnek!
Ez a megoldás is egy példa arra, hogy a problémák megkerülése néha egyszerűbb mint a megoldása. Lehetett volna küzdeni azzal, hogy árnyékolom a vezetékeket, vagy a napelemeim inverterét átépítem a szomszédba stb. Ehhez azonban csak kis pötyögés kellett a billentyűzeten.
Fogfájás esetén nem javaslom a módszer elvét, hosszútávon jobb a fogorvos, mint a fájdalomcsillapító!
Nagyon remélem, hogy ez az utolsó bejegyzésem ehhez a modulhoz, mert már nagyon elegem van ebből a kijelzőből. Rendeltem is még egyet, mert nagyon jó kis órát sikerült fabrikálnom piros kijelzővel, megtetszett és kiderült van zöld színben is, ami jobban megy a nappalink színeihez.