Cuprins:

RGB LED Matrix: 5 pași
RGB LED Matrix: 5 pași

Video: RGB LED Matrix: 5 pași

Video: RGB LED Matrix: 5 pași
Video: Pixel Dust on RGB Matrix displays 2024, Iulie
Anonim
Image
Image
Proiectare hardware
Proiectare hardware

Căutați instructabil și puteți găsi multe proiecte cu matrice LED. Niciunul dintre ei nu a fost ceea ce mi-am dorit, adică să explorez interacțiunile de design hardware și software pentru a produce ceva și să produc produsul final într-un PCB îngrijit cu un driver care să mă atragă pe "ecranul LED" folosind nivel înalt construcții (de exemplu, trasarea unei linii spre deosebire de setarea anumitor pixeli). Această parte a fost importantă pentru mine, deoarece mulți dintre driverele matricei LED sunt oase goale și nu oferă prea multe în ceea ce privește crearea programată a unei imagini sau a unei animații. Acest lucru nu înseamnă că nu puteți crea imagini și animații cu ceilalți drivere, ci doar că ar trebui să faceți o muncă mai repetitivă de la proiect la proiect.

Așa că mi-am propus să-mi împlinesc viziunea. Primul pas a fost proiectarea hardware-ului. Acesta a fost probabil cel mai provocator pentru mine, deoarece trecutul meu este mai mult software. Din nou, au existat multe modele pre-coapte și cu siguranță le-am folosit pentru inspirație, dar am vrut să învăț prin a face, așa că am prototipat o matrice 4x4 pe o placă de măsurare. Am învățat multe prin acest proces, deoarece primele mele iterații nu au funcționat. Dar am făcut un design hardware care a funcționat, ceea ce, la rândul meu, mi-a permis să încep să dezvolt un driver.

Am ales Arduino ca platformă de driver, deoarece este disponibil pe scară largă și are o mulțime de referințe online. În timp ce experiența în carieră mi-a permis să ajung la o versiune funcțională a unui driver mai ușor decât eforturile mele hardware, au existat încă o mulțime de iterații în timp ce am optimizat performanța driverului pentru microcontrolerul ATMega și am dezvoltat un API de programare care mi-a plăcut.

Acest manual instructabil documentează proiectarea și câteva învățări cheie din proiectul meu. Mai multe informații despre acest proiect pot fi găsite pe site-ul meu aici, inclusiv seturi complete pe care le puteți achiziționa pentru a vă construi propria matrice LED RGB.

Pasul 1: Proiectare hardware

Scopul principal al designului meu hardware a fost să creez o serie de LED-uri RGB pe care să le pot programa, dar nici nu am vrut să cheltuiesc mulți bani. Abordarea pe care m-am stabilit a fost să folosesc registre de schimb 74HC595 pentru a controla LED-urile. Pentru a minimiza numărul de registre de deplasare necesare, am aranjat LED-urile RGB într-un aspect matricial în care anodii comuni erau legați între ei în rânduri, iar cablurile catodului roșu, verde și albastru erau legate împreună în coloane. Pentru matricea 4x4, schema circuitului arăta ca schema circuitului atașat.

Un lucru pe care îl veți observa imediat este că, având în vedere circuitul matricial, există unele configurații de iluminare cu LED-uri care nu pot fi realizate cu toate LED-urile dorite fiind aprinse în același timp. De exemplu, matricea nu poate aprinde simultan două LED-uri diagonale unele de altele, deoarece alimentarea ambelor rânduri și coloane va face ca cele două LED-uri opuse să se aprindă pe diagonala perpendiculară pe LED-urile dorite. Pentru a rezolva acest lucru, vom folosi multiplexarea pentru a scana prin fiecare rând. Există o mulțime de resurse pe web care acoperă tehnica multiplexării, nu voi încerca să le reproduc aici.

Deoarece folosesc LED-uri anodice obișnuite, asta înseamnă că rândurile oferă putere pozitivă, iar coloanele se scufundă la sol. Vestea bună este că registrele de schimbare 74HC595 pot sursa și scufunda energie, dar vestea proastă este că au o limită a cantității de energie pe care o pot sursa sau scufunda. Pinii individuali ai modelului 74HC595 au un consum de curent maxim de 70 mA, dar cel mai bine este să păstrați mai puțin de 20 mA. Culorile individuale ale LED-urilor noastre RGB au fiecare o extragere de aproximativ 20 mA. Aceasta înseamnă că 74HC595 nu poate alimenta direct un întreg rând de LED-uri dacă doresc să le pornesc pe toate.

Deci, în loc să alimenteze rândul direct, 74HC595 va conduce în schimb un tranzistor pentru fiecare rând, iar tranzistorul va porni sau opri curentul care alimentează rândul. Deoarece proiectarea utilizează un LED anodic comun, tranzistorul de comutare va fi PNP. Dacă am folosi un LED catodic comun, tranzistorul de comutare ar fi NPN. Rețineți că, folosind un tranzistor PNP pentru a conduce un rând, setarea registrului de schimbare pentru a-l activa devine scăzută, deoarece un tranzistor PNP are nevoie de o tensiune negativă între emițător și bază pentru a fi pornit, ceea ce va permite curentului pozitiv să curgă în rând.

Un alt lucru de luat în considerare este aspectul de biți dorit al registrelor de schimbare. Adică, printre registrele de deplasare, care biți controlează care rânduri sau coloane din matrice. Designul pe care l-am trimis este în cazul în care primul bit, sau „cel mai semnificativ bit”, trimis către registrele de schimbare cu lanț de margaretă controlează coloana elementului roșu cu LED-uri, al doilea bit controlează elementul verde al primei coloane, al treilea bit controlează prima coloană element albastru, al patrulea bit controlează elementul roșu al celei de-a doua coloane, … acest model se repetă pe coloanele de la stânga la dreapta. Apoi următorul bit trimis controlează ultimul rând sau ultimul rând, următorul rând al doilea până la ultimul rând … acest lucru se repetă până la ultimul bit trimis, sau „bitul cel mai puțin semnificativ”, controlează primul rând sau primul rând din matrice.

În cele din urmă, trebuia să stabilesc ce rezistențe aș folosi pentru fiecare dintre LED-urile din LED-ul RGB. În timp ce ați putea folosi formula standard care combină tensiunea înainte și curentul dorit pentru a calcula rezistența necesară, am constatat că setarea curentului fiecărui LED la 20 miliamperi a dus la o culoare alb murdar când toate LED-urile roșu, verde și albastru erau aprinse.. Așa că am început să-l fac cu ochii. Prea mult roșu în alb însemna creșterea ohmilor rezistenței LED-ului roșu pentru a reduce curentul. Am repetat schimbând rezistențe de ohmi diferiți până când am găsit o combinație care produce o culoare albă pe care am simțit-o corectă. Combinația finală a fost de 180 Ω pentru LED-ul roșu, 220 Ω pentru LED-ul verde și 100 Ω pentru LED-ul albastru.

Pasul 2: Construcții hardware - Breadboard

Construcții hardware - panouri de panificatie
Construcții hardware - panouri de panificatie
Construcții hardware - panouri de panificatie
Construcții hardware - panouri de panificatie

Prima fază a constructorului de hardware a fost îmbarcarea pâinii. Aici am realizat o matrice 4x4 cu LED-urile RGB. Această matrice ar necesita 16 biți pentru control, 12 pentru coloanele RGB și 4 pentru fiecare rând. Două registre de schimbare 74HC595 pot rezolva totul. Mai întâi am cercetat și proiectat un circuit pe care credeam că îl va funcționa, apoi l-am construit pe panoul de testare.

Probabil că cea mai mare provocare a construirii plăcii a fost gestionarea tuturor firelor. Am luat un kit de sârmă preformat pentru panouri, dar evenimentul a fost puțin greoi. Un truc pe care l-am găsit util a fost să creez un „port” pentru conectarea la placa Arduino. Adică, mai degrabă decât să conectați pinii de pe Arduino direct la diferiții pini IC de pe panou, dedicați câteva rânduri de pe panou pentru a fi punctul de conexiune pentru Arduino, apoi conectați pinii de identificare relevanți la acele rânduri. Pentru acest proiect, aveți nevoie doar de cinci conexiuni la Arduino: + 5V, masă, date, ceas și zăvor.

Odată ce s-a făcut construcția plăcii, a trebuit să o testez. Cu toate acestea, fără un fel de driver care să trimită semnalele corecte către registrele de schimbare, nu am putut testa pentru a vedea dacă aspectul hardware a funcționat.

Pasul 3: Proiectare software driver

Image
Image

Având în vedere propria mea experiență în carieră cu dezvoltarea de software, aceasta a fost partea proiectului pe care probabil am fost cel mai clar despre o cale de urmat. Am analizat multe dintre celelalte drivere cu matrice LED bazate pe Arduino. Deși, cu siguranță, există drivere bune disponibile, niciunul nu avea designul dorit de mine. Obiectivele mele de proiectare ale șoferului au fost:

  • Oferiți un API de nivel înalt pentru a putea crea imagini și animații prin programare. Majoritatea driverelor pe care le-am văzut erau mai concentrate pe imagini codificate în mod dur. De asemenea, deoarece sunt programator C ++ de meserie, am vrut să folosesc un design bun orientat obiect pentru a implementa și gestiona activitățile de desenare la matricea LED.
  • Utilizați o abordare cu tampon dublu pentru a gestiona imaginea de pe ecran. Un tampon este ceea ce se atrage programatic, în timp ce celălalt reprezintă starea pixelilor matricei la un moment dat. Avantajul acestei abordări este că nu vi se cere să redați complet următoarea actualizare a cadrului pentru ecran între ciclurile de actualizare ale multiplexării.
  • Utilizați PWM pentru a permite mai mult de cele șapte culori primitive pe care le poate reda un RGB prin combinații simple de elemente roșu, verde și albastru.
  • Scrieți driverul astfel încât să „funcționeze” cu matrice LED RGB de dimensiuni diferite, care au urmat abordarea mea generală de proiectare a matricei. Rețineți că, în timp ce designul meu hardware utilizează registre de schimbare 74HC595, m-aș aștepta ca driverul meu să funcționeze cu orice mecanism de pornire / oprire a stilului de registru de schimbare care este prevăzut utilizând un aspect de biți similar cu cel al designului meu hardware. De exemplu, m-aș aștepta ca driverul meu să funcționeze cu un design hardware care utilizează cipuri DM13A pentru a controla coloanele și un cip 74HC595 pentru a controla rândurile.

Dacă doriți să mergeți direct la codul șoferului, îl puteți găsi pe GitHub aici.

Prima iterație a driverului meu a fost o curbă de învățare cu privire la capacitățile platformei Arduino. Cea mai evidentă limitare este memoria RAM, care este de 2K octeți pentru Arduino Uno și Nano. Folosirea obiectelor C ++ într-un astfel de scenariu nu este adesea recomandată din cauza memoriei generale a obiectelor. Cu toate acestea, am simțit că dacă este făcut corect, beneficiile obiectelor din C ++ au depășit costul lor (în RAM).

A doua provocare majoră a fost să ne gândim cum să implementăm modulația lățimii pulsului prin registrele de schimbare, astfel încât să pot genera mai mult decât cele șapte culori primitive ale LED-ului RGB. După ce am programat mulți ani pe platforme Linux, am fost obișnuit să folosesc constructe precum fire pentru a gestiona procese care necesită sincronizare consecventă. Momentul operației de actualizare a registrului de schimbare ajunge să fie destul de critic atunci când faci un driver pentru o matrice LED care utilizează multiplexarea. Motivul este că, deși multiplexarea se întâmplă atât de repede încât ochii tăi nu pot vedea LED-urile individuale clipind aprinse și oprite, ayes-urile tale pot percepe diferențe în timpul total agregat pe care oricare dintre LED-urile sunt aprinse. Dacă un rând de LED-uri este aprins constant pentru o perioadă mai lungă de timp decât celelalte, va arăta mai luminos în timpul multiplexării. Acest lucru poate duce la luminozitate neuniformă în matrice sau la strobare periodică a matricei în ansamblu (acest lucru se întâmplă atunci când un ciclu de actualizare durează mai mult decât celelalte).

De vreme ce aveam nevoie de un mecanism de sincronizare consecvent pentru a face ca actualizările registrului de schimbare să fie de acord, dar Arduino nu acceptă în mod oficial firul, am fost nevoit să îmi creez propriul mecanism de filetare. Prima mea iterație a acestui fapt a fost să creez pur și simplu un cronometru de buclă care să depindă de funcția Arduino loop () și să declanșeze o acțiune când a trecut o anumită perioadă de timp de la ultima declanșare a acțiunii. Aceasta este o formă de „multitasking cooperativ”. Sună bine, dar în practică acest lucru sa dovedit a fi inconsistent atunci când viteza de tragere a fost măsurată în microsecunde. Motivul pentru acest lucru este că, dacă aveam două dintre aceste cronometre de buclă, una dintre acțiunile lor a durat frecvent suficient de mult pentru a determina declanșarea celei de-a doua acțiuni mai târziu decât dorea.

Am constatat că soluția la această problemă este utilizarea mecanismului nativ de întrerupere a ceasului Arduino. Acest mecanism vă permite să rulați un pic de cod la intervale foarte consistente. Așa că am proiectat codul driverului în jurul elementului de proiectare al utilizării unei întreruperi de ceas pentru a declanșa codul pentru trimiterea schimbării matricei înregistrează următoarea actualizare din ciclul multiplex. Pentru a face acest lucru și a permite să apară actualizări ale imaginii ecranului pentru a nu interfera cu o descărcare activă a registrelor de schimbare (ceva ce am numi „condiție de cursă”), am folosit o abordare de a avea tampoane duble pentru biții de registru de schimbare, unul pentru scris și unul pentru lectură. Când utilizatorul actualizează imaginea matricei, aceste operații au loc în memoria tampon de scriere. Când acele operații sunt finalizate, întreruperile sunt suspendate temporar (aceasta înseamnă că întreruperea ceasului nu poate declanșa) și tamponul de scriere este schimbat cu tamponul de citire anterior și nu este noul tampon de citire, apoi interpretele sunt reactivate. Apoi, când întreruperea ceasului se declanșează, indicând că este timpul să trimiteți următoarea configurație de biți către registrele de schimbare, acele informații sunt citite din memoria tampon de citire curentă. În acest fel, nicio scriere nu se întâmplă vreodată într-un buffer care ar putea fi în prezent citit din timpul unei întreruperi de ceas, ceea ce ar putea corupe informațiile trimise către registrele de schimbare.

Proiectarea restului șoferului a fost un caz relativ simplu de proiectare orientată pe obiecte. De exemplu, am creat un obiect pentru a gestiona imaginea de biți a registrului de schimbare pentru orice stare de ecran dată. Prin încapsularea codului referitor la gestionarea imaginii de biți, crearea abordării menționate mai sus a bufferelor gemene a fost în sine un exercițiu direct. Dar nu am scris acest Instructable pentru a exalta virtuțile proiectării orientate pe obiecte. Un alt element de design include conceptul de glif și imagine RGB. Un glif este o construcție de bază a imaginii care nu are informații despre culoare înnăscute. Vă puteți gândi la aceasta ca la o imagine alb-negru. Când gliful este desenat pe ecranul cu LED-uri, sunt date informații despre culoare pentru a indica modul în care pixelii „albi” ar trebui să fie colorați. O imagine RGB este o imagine în care fiecare pixel are propriile informații despre culoare.

Vă încurajez să examinați exemplele de schițe Arduino și să examinați documentația antetului driverului pentru a vă familiariza cu modul de utilizare a driverului pentru a crea imagini și animații pe o matrice LED RGB.

Pasul 4: LED Ghosting

LED Ghosting
LED Ghosting
LED Ghosting
LED Ghosting

Într-o matrice cu LED-uri, „ghosting” este fenomenul unui LED din matrice care aprinde atunci când nu este dorit, de obicei un nivel foarte redus. Designul meu original de hardware a fost susceptibil de ghosting, mai ales în ultimul rând. Cauza acestui fapt se datorează a două lucruri: tranzistoarele nu se opresc imediat și capacitatea parazită în LED-urile RGB.

Pe măsură ce scanăm rândurile, datorită faptului că tranzistoarele nu se opresc imediat, rândul anterior din ciclul de scanare este încă parțial alimentat când rândul următor este pornit. Dacă o anumită coloană care a fost oprită în rândul anterior este nou pornită când noul rând este alimentat, LED-ul acelei coloane din rândul anterior se va aprinde puțin timp în timp ce tranzistorul de comutare al rândului anterior este încă în proces de rotire oprit. Ceea ce face ca tranzistorul să ia o perioadă notabilă de timp pentru a opri este saturația în baza tranzistorului. Acest lucru face ca traseul colector-emițător al tranzistorului să continue să se conducă atunci când curentul este îndepărtat de la bază, cel puțin până la disiparea saturației. Având în vedere că ciclul nostru de actualizare multiplexare face ca rândurile să fie pornite în mod intenționat pentru o perioadă de timp măsurată în microsecunde, cantitatea de timp pe care tranzistorul saturat al rândului anterior rămâne conductiv poate fi o fracțiune vizibilă din aceasta. Ca urmare, ochiul tău poate percepe acea cantitate foarte mică de timp pe care LED-ul rândului anterior este aprins.

Pentru a remedia problema de saturație a tranzistorului, o diodă Schottky poate fi adăugată la tranzistorul dintre bază și colector pentru a provoca un pic de curent înapoi la bază atunci când tranzistorul este pornit, împiedicând tranzistorul să se satureze. La rândul său, acest lucru va face ca tranzistorul să se oprească mai repede atunci când curentul este îndepărtat de la bază. Consultați acest articol pentru o explicație aprofundată a acestui efect. După cum puteți vedea din imaginea din această secțiune, fără diodă, fantoma este destul de vizibilă, dar adăugarea diodei la circuit pentru fiecare rând elimină semnificativ fantoma.

LED-urile RGB sunt susceptibile la un alt fenomen numit capacitate parazită. Cauza principală a acestui fapt este faptul că fiecare dintre cele trei LED-uri color din unitatea LED RGB au fiecare tensiuni diferite înainte. Această diferență în tensiunile directe poate provoca efectul capacității electrice între fiecare dintre culorile LED individuale. Deoarece o încărcare electrică este acumulată în unitatea cu LED-uri atunci când este alimentată, atunci când curentul este scos, capacitatea parazită trebuie descărcată. În cazul în care coloana cu LED-ul respectiv este aprinsă pentru alimentarea unui alt rând, încărcarea parazitară se va descărca prin LED-ul coloanelor respective și va face să lumineze scurt. Acest efect este explicat frumos în acest articol. Soluția constă în adăugarea unei căi de descărcare pentru această încărcare parazită, alta decât prin LED-ul în sine, și apoi acordarea timpului de descărcare a LED-ului înainte ca coloana să fie alimentată din nou. În proiectarea mea hardware, acest lucru se realizează prin adăugarea unui rezistor la linia de alimentare a fiecărui rând care conectează puterea la masă. Acest lucru va face ca mai mult curent să fie tras cu rândul este alimentat, dar oferă o cale de descărcare pentru capacitatea parazită atunci când rândul nu este alimentat.

Cu toate acestea, este demn de remarcat faptul că, în practică, efectul capacității parazitare este abia vizibil (dacă îl căutați, îl puteți găsi) și, prin urmare, consider că adăugarea acestui rezistor suplimentar este opțională. Efectul timpului de oprire lentă pentru tranzistoarele saturate este mult mai puternic și vizibil. Cu toate acestea, dacă inspectați cele trei fotografii furnizate în această secțiune, puteți vedea că rezistențele elimină complet orice fantomă care apare încă dincolo de timpul de oprire a tranzistorului lent.

Pasul 5: Fabricarea finală și pașii următori

Image
Image

Faza finală a acestui proiect a fost pentru mine să creez o placă cu circuite imprimate (PCB). Am folosit programul open source Fritzing pentru a-mi proiecta PCB-ul. Deși a fost o mulțime de sarcini repetitive de îndeplinit pentru a aranja 100 de LED-uri pe o placă de 10x10, de fapt am găsit această fază a proiectului ciudat de satisfăcătoare. Descoperirea modului în care fiecare cale electrică ar fi trasată a fost ca un puzzle și rezolvarea acelui puzzle a creat un sentiment de realizare. Din moment ce nu sunt configurat să produc plăcile de circuite, am folosit una dintre numeroasele resurse online care fac runde mici de PCB personalizate. Lipirea pieselor împreună a fost destul de simplă, deoarece designul meu a folosit toate piesele prin găuri.

În momentul redactării acestui Instructable, am următoarele planuri pentru proiectele mele RGB LED Matrix:

  1. Continuați să îmbunătățiți driverul la nivelul API pentru a permite mai multă funcționalitate la nivel înalt programatorului, în special defilarea textului.
  2. Creați modele cu matrice mai mari, cum ar fi 16x16 sau chiar 16x32.
  3. Explorează folosind MOSFET-uri în loc de BJT-uri pentru comutarea puterii pe rând
  4. Explorează folosind drivere de curent constant DM13A, mai degrabă decât 74HC595 pentru comutarea coloanei
  5. Creați drivere pentru alte platforme de microcontrol, precum Teensy, ODROID C2 sau Raspberry Pi.

Rețineți că atât designul hardware cât și driverul au fost lansate sub licența GPL v3 open source la acest depozit GitHub. Mai mult, deoarece, chiar dacă producătorii de PCB realizează „mici rulaje” ale designului meu de PCB, totuși obțin mult mai mult decât am nevoie personal. Așadar, vând kituri complete pentru diversele modele de matrice LED RGB (PCB și toate părțile incluse) de pe site-ul meu aici.

Recomandat: