Sommario:

Matrice LED RGB: 5 passaggi
Matrice LED RGB: 5 passaggi

Video: Matrice LED RGB: 5 passaggi

Video: Matrice LED RGB: 5 passaggi
Video: How to Build a Massive LED Wall on a Budget 2024, Dicembre
Anonim
Image
Image
Progettazione hardware
Progettazione hardware

Cerca Instructable e puoi trovare molti progetti di matrici LED. Nessuno di loro era proprio quello che volevo, ovvero esplorare le interazioni tra progettazione hardware e software per produrre qualcosa e produrre il prodotto finale in un PCB pulito con un driver che mi permettesse di disegnare sullo "schermo LED" usando un alto livello costrutti (ad esempio, tracciare una linea invece di impostare pixel specifici). Questa parte è stata importante per me, poiché molti dei driver della matrice LED sono essenziali e non forniscono molto in termini di creazione programmatica di un'immagine o di un'animazione. Questo non significa che non puoi creare immagini e animazioni con gli altri driver, solo che dovresti fare un lavoro più ripetitivo da un progetto all'altro.

Così ho deciso di realizzare la mia visione. Il primo passo è stato quello di progettare l'hardware. Questo è stato probabilmente il più impegnativo per me, poiché il mio background è più software. Di nuovo, c'erano molti progetti precotti e li ho sicuramente usati per l'ispirazione, ma volevo imparare facendo, quindi ho prototipato una matrice 4x4 su una breadboard. Ho imparato molto attraverso quel processo, poiché le mie prime iterazioni non hanno funzionato. Ma ho fatto una progettazione hardware che ha funzionato, che a sua volta mi ha permesso di iniziare a sviluppare un driver.

Ho scelto Arduino come piattaforma driver perché è ampiamente disponibile e ha molti riferimenti online. Mentre l'esperienza professionale mi ha permesso di arrivare a una versione funzionante di un driver più facilmente dei miei sforzi hardware, c'erano ancora molte iterazioni mentre ottimizzavo le prestazioni del driver per il micro controller ATMega e sviluppavo un'API di programmazione che mi piaceva.

Questo Instructuctable documenta il design e alcuni insegnamenti chiave del mio progetto. Maggiori informazioni su questo progetto possono essere trovate sul mio sito web qui, inclusi i kit completi che puoi acquistare per costruire la tua matrice LED RGB.

Passaggio 1: progettazione dell'hardware

L'obiettivo principale della mia progettazione hardware era creare una serie di LED RGB che potevo programmare, ma non volevo nemmeno spendere molti soldi. L'approccio che ho scelto è stato quello di utilizzare i registri a scorrimento 74HC595 per controllare i LED. Per ridurre al minimo il numero di registri a scorrimento necessari, ho disposto i LED RGB in un layout a matrice in cui gli anodi comuni erano legati insieme in file e i cavi del catodo rosso, verde e blu erano legati insieme in colonne. Per la matrice 4x4, lo schema del circuito sembrava lo schema del circuito allegato.

Una cosa che noterai subito è che, dato il circuito a matrice, ci sono alcune configurazioni di illuminazione a LED che non possono essere eseguite con tutti i LED desiderati accesi contemporaneamente. Ad esempio, la matrice non può accendere contemporaneamente due LED diagonali l'uno dall'altro perché alimentando sia le righe che le colonne si accendono i due LED opposti sulla diagonale perpendicolare ai LED desiderati. Per ovviare a questo problema, utilizzeremo il multiplexing per scansionare ogni riga. Ci sono molte risorse sul web che trattano la tecnica del multiplexing, non cercherò di replicarle qui.

Poiché sto usando LED ad anodo comune, ciò significa che le righe forniscono potenza positiva e le colonne affondano a terra. La buona notizia è che i registri a scorrimento 74HC595 possono sia fornire che assorbire potenza, ma la cattiva notizia è che hanno un limite alla quantità di energia che possono generare o assorbire. I singoli pin del 74HC595 hanno un assorbimento di corrente massimo di 70 mA, ma è meglio mantenere meno di 20 mA. I singoli colori nei nostri LED RGB hanno ciascuno un assorbimento di circa 20 mA. Ciò significa che il 74HC595 non può alimentare direttamente un'intera fila di LED se desidero accenderli tutti.

Quindi, invece di alimentare direttamente la riga, il 74HC595 guiderà invece un transistor per ogni riga e il transistor accenderà o spegnerà la corrente che alimenta la riga. Poiché il design utilizza un LED ad anodo comune, il transistor di commutazione sarà PNP. Se stessimo usando un LED a catodo comune, il transistor di commutazione sarebbe NPN. Si noti che con l'utilizzo di un transistor PNP per pilotare una riga, l'impostazione del registro a scorrimento per accenderlo ora diventa bassa poiché un transistor PNP necessita di una tensione negativa tra l'emettitore e la base per essere accesa, il che consentirà alla corrente positiva di fluire nel riga.

Un'altra cosa da considerare è la disposizione dei bit desiderata dei registri a scorrimento. Cioè, tra i registri a scorrimento, quali bit controllano quali righe o colonne nella matrice. Il progetto che ho inviato è dove il primo bit, o "bit più significativo", inviato ai registri a scorrimento in daisy chain controllano l'elemento rosso della colonna dei LED, il secondo bit controlla l'elemento verde della prima colonna, il terzo bit controlla l'elemento verde della prima colonna elemento blu, il quarto bit controlla l'elemento rosso della seconda colonna, … questo schema viene ripetuto attraverso le colonne da sinistra a destra. Quindi il successivo bit inviato controlla l'ultima riga, o inferiore, il successivo la penultima riga, … questo ripetuto fino all'ultimo bit inviato, o "bit meno significativo", controlla la prima riga, o superiore, nella matrice.

Infine, avevo bisogno di determinare quali resistori avrei usato per ciascuno dei LED nel LED RGB. Sebbene sia possibile utilizzare la formula standard che combina la tensione diretta e la corrente desiderata per calcolare il resistore richiesto, ho scoperto che l'impostazione della corrente di ciascun LED su 20 milliampere determinava un colore bianco sporco quando tutti i LED rossi, verdi e blu erano accesi. Così ho iniziato a guardarlo negli occhi. Troppo rosso nel bianco significava aumentare gli ohm del resistore del LED rosso per ridurre la corrente. Ho ripetuto lo scambio di resistori di ohm diversi fino a quando non ho trovato una combinazione che ha prodotto un colore bianco che ritenevo giusto. La combinazione finale era 180 per il LED rosso, 220 per il LED verde e 100 per il LED blu.

Fase 2: Costruzione dell'hardware - Breadboard

Costruzione hardware - tagliere
Costruzione hardware - tagliere
Costruzione hardware - tagliere
Costruzione hardware - tagliere

La prima fase del costruttore dell'hardware è stata l'imbarco del pane. Qui ho realizzato una matrice 4x4 con i LED RGB. Questa matrice richiederebbe 16 bit per il controllo, 12 per le colonne RGB e 4 per ogni riga. Due registri a scorrimento 74HC595 possono gestire tutto. Ho prima ricercato e progettato un circuito che pensavo avrebbe funzionato, poi l'ho costruito sulla breadboard.

Probabilmente la sfida più grande della costruzione della breadboard è stata la gestione di tutti i cavi. Ho preso un kit di cavi preformato per breadboard, ma poi è stato un po' ingombrante. Un trucco che ho trovato utile è stato quello di creare una "porta" per il collegamento alla scheda Arduino. Cioè, piuttosto che collegare i pin di Arduino direttamente ai vari pin IC sulla breadboard, dedicare alcune righe sulla breadboard ad essere il punto di connessione per Arduino, quindi collegare i pin ID pertinenti a quelle righe. Per questo progetto, hai solo bisogno di cinque connessioni ad Arduino: +5V, terra, dati, orologio e latch.

Una volta completata la build della breadboard, dovevo testarla. Tuttavia, senza una sorta di driver per inviare i segnali giusti ai registri a scorrimento, non sono stato in grado di verificare se il layout dell'hardware funzionava.

Passaggio 3: progettazione del software del driver

Image
Image

Data la mia esperienza professionale con lo sviluppo di software, questa era la parte del progetto che probabilmente mi aveva più chiaro sul percorso da intraprendere. Ho esaminato molti degli altri driver a matrice LED basati su Arduino. Sebbene siano certamente disponibili buoni driver, nessuno aveva il design che volevo. I miei obiettivi di progettazione del driver erano:

  • Fornisci un'API di alto livello per essere in grado di creare immagini e animazioni a livello di codice. La maggior parte dei conducenti che ho visto erano più concentrati su immagini hard-coded. Inoltre, poiché sono un programmatore C++ di professione, ho voluto utilizzare un buon design orientato agli oggetti per implementare e gestire le attività di disegno sulla matrice LED.
  • Utilizzare un approccio a doppio buffer per gestire l'immagine sullo schermo. Un buffer è ciò che viene disegnato in modo programmatico, mentre l'altro rappresenta lo stato dei pixel della matrice in un dato momento. Il vantaggio di questo approccio è che non è necessario eseguire il rendering completo del prossimo aggiornamento del frame per lo schermo tra i cicli di aggiornamento del multiplexing.
  • Usa PWM per consentire più dei sette colori primitivi che un RGB può riprodurre attraverso semplici combinazioni degli elementi rosso, verde e blu.
  • Scrivere il driver in modo che "funzioni" con matrici LED RGB di dimensioni diverse che hanno seguito il mio approccio generale alla progettazione della matrice. Si noti che mentre il mio progetto hardware utilizza i registri a scorrimento 74HC595, mi aspetto che il mio driver funzioni con qualsiasi meccanismo di attivazione/disattivazione dello stile di registro a scorrimento disposto utilizzando un layout di bit simile a quello del mio progetto hardware. Ad esempio, mi aspetto che il mio driver funzioni con un design hardware che utilizza chip DM13A per controllare le colonne e un chip 74HC595 per controllare le righe.

Se vuoi andare direttamente a guardare il codice del driver, puoi trovarlo su GitHub qui.

La prima iterazione del mio driver è stata una sorta di curva di apprendimento sulle capacità della piattaforma Arduino. La limitazione più ovvia è la RAM, che è di 2K byte per Arduino Uno e Nano. L'utilizzo di oggetti C++ in uno scenario di questo tipo è spesso sconsigliato a causa del sovraccarico di memoria degli oggetti. Tuttavia, ho sentito che se fatto bene, il vantaggio degli oggetti in C++ superava il loro costo (in RAM).

La seconda grande sfida è stata capire come implementare la modulazione dell'ampiezza dell'impulso tramite i registri a scorrimento in modo da poter generare più dei sette colori primitivi del LED RGB. Avendo programmato per molti anni su piattaforme Linux, ero abituato a utilizzare costrutti come i thread per gestire processi che richiedono tempistiche coerenti. La tempistica dell'operazione di aggiornamento del registro a scorrimento finisce per essere piuttosto critica quando si realizza un driver per una matrice LED che utilizza il multiplexing. Il motivo è che anche se il multiplexing sta accadendo così velocemente che i tuoi occhi non possono vedere i singoli LED che si accendono e si spengono, i tuoi sì possono rilevare differenze nel tempo totale aggregato in cui uno qualsiasi dei LED è acceso. Se una fila di LED è costantemente accesa per un periodo di tempo più lungo delle altre, apparirà più luminosa durante il multiplexing. Ciò può portare a una luminosità non uniforme nella matrice o a effetti stroboscopici periodici della matrice nel suo insieme (questo si verifica quando un ciclo di aggiornamento richiede più tempo degli altri).

Dal momento che avevo bisogno di un meccanismo di temporizzazione coerente per consentire agli aggiornamenti del registro di scorrimento di essere il consenso, ma Arduino non supporta formalmente il thread, ho dovuto creare il mio meccanismo simile al threading. La mia prima iterazione di questo è stata semplicemente quella di creare un timer di loop che dipendesse dalla funzione Arduino loop() e che attivasse un'azione quando è trascorso un certo periodo di tempo dall'ultima volta che l'azione è stata attivata. Questa è una forma di "multitasking cooperativo". Suona bene, ma in pratica si è rivelato incoerente quando la velocità di fuoco è stata misurata in microsecondi. La ragione di ciò è che se avessi due di questi timer di loop in funzione, una delle loro azioni spesso impiegava abbastanza tempo da far scattare la seconda azione più tardi del previsto.

Ho scoperto che la soluzione a questo problema è utilizzare il meccanismo di interruzione dell'orologio nativo di Arduino. Questo meccanismo consente di eseguire una piccola porzione di codice a intervalli molto coerenti. Quindi ho progettato il codice del driver attorno all'elemento di progettazione dell'utilizzo di un interrupt di clock per attivare il codice per l'invio dei registri a scorrimento della matrice al successivo aggiornamento nel ciclo multiplex. Per fare ciò e consentire agli aggiornamenti di verificarsi sull'immagine dello schermo per non interferire con un dump attivo sui registri a scorrimento (qualcosa che chiameremmo una "condizione di gara"), ho usato un approccio di avere due buffer per i bit del registro a scorrimento, uno per scrivere e uno per leggere. Quando l'utente sta aggiornando l'immagine della matrice, queste operazioni si verificano nel buffer di scrittura. Quando queste operazioni sono complete, gli interrupt vengono temporaneamente sospesi (questo significa che l'interrupt di clock non può essere attivato) e il buffer di scrittura viene scambiato con il precedente buffer di lettura e non è il nuovo buffer di lettura, quindi gli interpreti vengono riabilitati. Quindi, quando l'interruzione dell'orologio si attiva indicando che è il momento di inviare la configurazione di bit successiva ai registri a scorrimento, tale informazione viene letta dal buffer di lettura corrente. In questo modo, non si verifica mai alcuna scrittura su un buffer che potrebbe essere attualmente in lettura durante un'interruzione del clock, che potrebbe danneggiare le informazioni inviate ai registri a scorrimento.

La progettazione del resto del driver è stata un caso relativamente semplice di progettazione orientata agli oggetti. Ad esempio, ho creato un oggetto per gestire l'immagine di bit del registro a scorrimento per un dato stato dello schermo. Incapsulando il codice relativo alla gestione dell'immagine bit, la creazione del suddetto approccio ai doppi buffer è stato di per sé un esercizio semplice. Ma non ho scritto questo Instructable per esaltare le virtù del design orientato agli oggetti. Altri elementi di design includono il concetto di un glifo e un'immagine RGB. Un glifo è un costrutto di immagine di base che non ha informazioni innate sul colore. Puoi immaginarlo come un'immagine in bianco e nero. Quando il glifo viene disegnato sullo schermo LED, vengono fornite informazioni sul colore per indicare come devono essere colorati i pixel "bianchi". Un'immagine RGB è un'immagine in cui ogni pixel ha le proprie informazioni sul colore.

Ti incoraggio a rivedere gli esempi di sketch Arduino e la documentazione dell'intestazione del driver per acquisire familiarità con come utilizzare il driver per creare immagini e animazioni su una matrice LED RGB.

Passaggio 4: LED fantasma

Fantasma LED
Fantasma LED
Fantasma LED
Fantasma LED

In una matrice di LED, il "ghosting" è il fenomeno di un LED nella matrice che si accende quando non è desiderato, di solito a un livello molto ridotto. Il mio design hardware originale era suscettibile di ghosting, in particolare nell'ultima riga. La causa di ciò è dovuta a due cose: i transistor non si spengono immediatamente e la capacità parassita nei LED RGB.

Durante la scansione delle righe, poiché i transistor non si spengono immediatamente, la riga precedente nel ciclo di scansione è ancora parzialmente alimentata quando viene attivata la riga successiva. Se una determinata colonna che era spenta nella riga precedente viene riaccesa quando la nuova riga viene alimentata, il LED di quella colonna nella riga precedente si accenderà per un breve periodo mentre il transistor di commutazione della riga precedente è ancora in fase di accensione spento. Ciò che fa sì che il transistor richieda una notevole quantità di tempo per spegnersi è la saturazione nella base del transistor. Ciò fa sì che il percorso collettore-emettitore del transistor continui a condurre quando la corrente viene rimossa dalla base, almeno fino a quando la saturazione non si dissipa. Dato che il nostro ciclo di aggiornamento del multiplexing fa sì che le righe siano intenzionalmente attive per un periodo di tempo misurato in microsecondi, la quantità di tempo in cui il transistor saturo della riga precedente rimane conduttivo può essere una frazione notevole di ciò. Di conseguenza, il tuo occhio può percepire quella brevissima quantità di tempo in cui il LED della riga precedente è acceso.

Per risolvere il problema della saturazione del transistor, è possibile aggiungere un diodo Schottky al transistor tra la base e il collettore per causare una piccola corrente di ritorno alla base quando il transistor è acceso, evitando che il transistor si satura. Questo a sua volta farà sì che il transistor si spenga più rapidamente quando la corrente viene rimossa dalla base. Vedi questo articolo per una spiegazione approfondita di questo effetto. Come puoi vedere dall'immagine in questa sezione, senza il diodo il ghosting è abbastanza evidente, ma aggiungendo il diodo al circuito per ogni riga si rimuove in modo significativo il ghosting.

I LED RGB sono soggetti a un altro fenomeno chiamato capacità parassita. La causa principale di ciò è il fatto che ciascuno dei tre LED a colori nell'unità LED RGB ha tensioni dirette diverse. Questa differenza nelle tensioni in avanti può causare l'effetto della capacità elettrica tra ciascuno dei singoli colori del LED. Poiché una carica elettrica si accumula nell'unità LED quando viene alimentata, quando l'alimentazione viene rimossa, la capacità parassita deve essere scaricata. Se la colonna di quel LED è altrimenti accesa per l'alimentazione di un'altra riga, la carica parassita si scaricherà attraverso quel LED della colonna e lo farà illuminare brevemente. Questo effetto è spiegato bene in questo articolo. La soluzione consiste nell'aggiungere un percorso di scarica per questa carica parassita oltre che attraverso il LED stesso, e quindi dare al LED il tempo di scaricarsi prima che la colonna venga nuovamente alimentata. Nella mia progettazione hardware, ciò si ottiene aggiungendo un resistore alla linea di alimentazione di ciascuna riga che collega la forza a terra. Ciò farà assorbire più corrente con la riga alimentata, ma fornisce un percorso di scarica per la capacità parassita quando la riga non è alimentata.

Vale la pena notare, tuttavia, che in pratica trovo che l'effetto della capacità parassita sia appena percettibile (se lo cerchi, lo puoi trovare), e quindi considero opzionale l'aggiunta di questo resistore aggiuntivo. L'effetto del tempo di rallentamento per i transistor saturi è molto più forte e evidente. Tuttavia, se controlli le tre foto fornite in questa sezione, puoi vedere che i resistori rimuovono completamente qualsiasi ghosting che si verifica ancora oltre quello dei tempi di spegnimento del transistor lento.

Passaggio 5: produzione finale e passaggi successivi

Image
Image

La fase finale di questo progetto è stata per me creare un circuito stampato (PCB). Ho usato il programma open source Fritzing per progettare il mio PCB. Mentre c'erano molte attività ripetitive da svolgere per disporre 100 LED su una scheda 10x10, ho trovato questa fase del progetto stranamente soddisfacente. Capire come sarebbe stato disposto ogni percorso elettrico era come un puzzle, e risolverlo ha creato un senso di realizzazione. Dal momento che non sono impostato per produrre i circuiti stampati, ho utilizzato una delle tante risorse online che realizzano piccole serie di PCB personalizzati. Saldare le parti insieme è stato piuttosto semplice poiché il mio progetto utilizzava tutte le parti a foro passante.

Al momento della stesura di questo Instructable, ho i seguenti piani per i miei progetti RGB LED Matrix:

  1. Continua a migliorare il driver a livello di API per consentire al programmatore più funzionalità di alto livello, in particolare lo scorrimento del testo.
  2. Crea progetti di matrici più grandi, come 16x16 o anche 16x32.
  3. Esplora l'utilizzo di MOSFET anziché BJT per la commutazione dell'alimentazione di riga
  4. Esplora l'utilizzo di driver a corrente costante DM13A anziché 74HC595 per la commutazione della colonna
  5. Crea driver per altre piattaforme di microcontrollo, come Teensy, ODROID C2 o Raspberry Pi.

Nota che sia il design dell'hardware che il driver sono stati rilasciati sotto la licenza open source GPL v3 in questo repository GitHub. Inoltre, dal momento che anche se i produttori di PCB eseguono "piccole tirature" del mio progetto di PCB, ottengo comunque molto più di quello di cui ho personalmente bisogno. Quindi vendo kit completi per i miei vari design a matrice di LED RGB (PCB e tutte le parti incluse) dal mio sito web qui.

Consigliato: