Usare la matrice LED di Arduino UNO R4 WiFi

L’elemento caratterizzante più evidente di Arduino R4 è senza alcun dubbio la matrice di LED, che potremo utilizzare come sistema di output immediato, ma anche per creare animazioni o giochi, o ancora mettere in evidenza lo stato di un sensore. La matrice LED è costituita da 12×8 LED.

La matrice e la sua API sono sviluppate per essere programmate in diversi modi, ciascuno adatto per diverse applicazioni. Questa breve lezione vi guiderà attraverso i concetti di base per gestire la matrice di LED aiutandovi a creare le vostre animazioni, mostrando tre diversi metodi di gestione dei LED che potrete scegliere in funzione del progetto che desiderate implementare.

Per lo svolgimento di questa lezione avete necessità solamente della scheda Arduino UNO R4 e di un cavo USB C.

Inizializzare la matrice

L’inizializzazione della matrice di LED avviene in 3 passi:

  1. inclusione nel vostro sketch della libreria:
1#include "Arduino_LED_Matrix.h"
  1. creazione dell’oggetto matrix aggiungendo la seguente riga:
1ArduinoLEDMatrix matrix;

L’oggetto ovviamente potrà avere un nome a vostro piacimento nell’esempio è stato scelto: “matrix”

  1. avviare la matrice aggiungendo nel setup():
1matrix.begin();

Il codice di avvio sarà il seguente:

1#include "Arduino_LED_Matrix.h"
2 
3ArduinoLEDMatrix matrix;
4 
5void setup() {
6  Serial.begin(115200);
7  matrix.begin();
8}

Come realizzare un frame

Il principio di funzionamento della libreria di gestione della matrice di LED è quello basato sulla creazione di un frame (fotogramma) memorizzato in un buffer di memoria e poi visualizzato.

Un frame è ciò che viene chiamato anche “immagine” visualizzata in un dato momento sulla matrice di LED. Un’animazione è costituita da una serie di immagini pertanto possiamo dire in altro modo che un’animazione è costituita da una sequenza di frame .

Per controllare la matrice LED 12×8 è indispensabile utilizzare uno spazio in memoria che sia di almeno 96 bit e la libreria fornisce due modi per farlo.

Modo n. 1

Il primo è quello di creare un array bidimensionale di byte nel modo che segue:

1byte frame[8][12] = {
2  { 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
3  { 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
4  { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
5  { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
6  { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
7  { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
8  { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
9  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
10};

La prima modalità è molto semplice da capire, la struttura frame rappresenta la matrice di LED e la serie di 1 indicherà quali LED saranno accesi, mentre quelli a 0 rappresentano i LED spenti. L’array sopra permetterà di visualizzare sulla matrice un cuore.

Suggerimento: Potete vedere il cuore più facilmente se evidenziate tutti gli “1” sulla pagina premendo CTRL/command + F e cercando “1”.

Per fare riferimento ad un pixel specifico ricordare che l’origine degli assi si trova in alto a sinistra ed avrà coordinate (0, 0) pertanto il codice che segue permette di porre ad 1 (on) il terzo pixel da sinistra e secondo dall’alto:

1frame[2][1] = 1;
2matrix.renderBitmap(frame, 8, 12);

Questo metodo però richiede più memoria di quella necessaria. Anche se ogni LED ha bisogno solo di un singolo bit per memorizzare il suo stato, vengono usati per ognuno di esse otto bit (un byte). Il metodo più efficiente, in termini di memoria per memorizzare un fotogramma è utilizzare un array di interi a 32 bit, descritto di seguito.

Vedremo ora come realizzare uno o più fotogrammi, realizzazione che può anche essere svolta con il LED Matrix tool messo a disposizione da Arduino, ma al fine di comprenderne a pieno il funzionamento, consiglio di seguire le indicazioni che trovate di seguito.

La parte di programma che utilizza codici esadecimali e rappresenta l’immagine del cuore indicata sopra è:

1unsigned long frame[] = {
2  0x3184a444,
3  0x42081100,
4  0xa0040000
5};

Una variabile long senza segno contiene 32 bit, quindi per gestire 92 LED (bit) avremo necessità di 96/32 che corrisponde a 3 variabili long in grado di rappresentare ogni immagine che appare sulla matrice di LED, pertanto un array di tre variabili long senza segno è un modo efficiente per contenere tutti i bit necessari per rappresentare un’immagine sulla matrice di LED.

Ma come sono relazionate la serie dei 3 valori esadecimali con la posizione di ogni songolo pixel?

Ciò dovrà essere fatto convertendo i valori esadecimali in binario utilizzando il codice che segue:

1for (int b = 0; b < 3; b++) {
2    Serial.println(frame[b], BIN);
3  }

Che permetterà di stampare tutti i valori dei bit dell’array. L’output sarà il seguente:

1110001100001001010010001000100
21000010000010000001000100000000
310100000000001000000000000000000

Questo metodo, però, non mostra tutti i bit. Ogni elemento dell’array deve avere 32 bit. Se completiamo correttamente, aggiungendo gli zeri mancanti alla fine avremo i 32 bit di ogni elemento:

100110001100001001010010001000100
201000010000010000001000100000000
310100000000001000000000000000000

Ora suddividiamo il blocco precedente in gruppi da 12 bit ed otterremo nuovamente l’immagine del cuore:

1001100011000
2010010100100
3010001000100
4001000001000
5000100010000
6000010100000
7000001000000
8000000000000

Se si hanno diversi fotogrammi, è possibile caricarli e visualizzarli in questo modo:

1const uint32_t felice[] = {
2    0x19819,
3    0x80000001,
4    0x81f8000
5};
6 
7const uint32_t cuore[] = {
8    0x3184a444,
9    0x44042081,
10    0x100a0040
11};
12 
13  matrix.loadFrame(felice);
14  delay(500);
15 
16  matrix.loadFrame(cuore);
17  delay(500);

Proviamo il codice

Applichiamo questi concetti con due sketch che visualizzano fotogrammi diversi sulla tua scheda.

Esempio 01

Creiamo prima 3 fotogrammi interi a 32 bit e carichiamoli sulla scheda uno alla volta.

1#include "Arduino_LED_Matrix.h"
2 
3ArduinoLEDMatrix matrix;
4 
5void setup() {
6  Serial.begin(115200);
7  matrix.begin();
8}
9 
10const uint32_t felice[] = {
11    0x19819,
12    0x80000001,
13    0x81f8000
14};
15const uint32_t cuore[] = {
16    0x3184a444,
17    0x44042081,
18    0x100a0040
19};
20   
21void loop(){
22  matrix.loadFrame(felice);
23  delay(500);
24 
25  matrix.loadFrame(cuore);
26  delay(500);
27}

Lo sketch è molto semplice è permette di mostrate due stati diversi.

Esempio 02

Cambiamo ora approccio è creiamo un’immagine che cambia durante l’esecuzione del programma. Il programma include diverse funzioni che concorrono alla costruzione del volto e modificano alcuni pixel che permettono di fare l’occhiolino dall’occhio sinistro.

1#include "Arduino_LED_Matrix.h"
2 
3ArduinoLEDMatrix matrix;
4 
5void setup() {
6  Serial.begin(115200);
7  matrix.begin();
8}
9 
10uint8_t frame[8][12] = {
11  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
12  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
13  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
14  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
15  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
16  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
17  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
18  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
19};
20 
21void occhioSinistro() {
22  //Occhio sinistro
23  frame[1][3] = 1;
24  frame[1][4] = 1;
25  frame[2][3] = 1;
26  frame[2][4] = 1;
27}
28 
29void occhiolino() {
30  //Fare un occhiolino con occhio sinistro
31  frame[1][3] = 0;
32  frame[1][4] = 0;
33  frame[2][3] = 1;
34  frame[2][4] = 1;
35}
36 
37void occhioDestro() {
38  //Occhio destro
39  frame[1][8] = 1;
40  frame[1][9] = 1;
41  frame[2][8] = 1;
42  frame[2][9] = 1;
43}
44 
45void bocca() {
46  //Bocca
47  frame[5][3] = 1;
48  frame[5][9] = 1;
49  frame[6][3] = 1;
50  frame[6][4] = 1;
51  frame[6][5] = 1;
52  frame[6][6] = 1;
53  frame[6][7] = 1;
54  frame[6][8] = 1;
55  frame[6][9] = 1;
56}
57 
58void loop() {
59  occhioSinistro();
60  occhioDestro();
61  bocca();
62 
63  matrix.renderBitmap(frame, 8, 12);
64 
65  delay(1000);
66  occhiolino();
67 
68  matrix.renderBitmap(frame, 8, 12);
69  delay(1000);
70}

Esempio 03

Vediamo ora come, usando il LED Matrix tool, possono essere realizzati due visi sorridenti di cui uno che fa l’occhiolino.
Lascio a voi capire come usare gli strumenti da disegno, essenziale però descrivervi come effettuare il download dei frame.
Costruire due immagini una che riporta un viso con sorriso e l’altra un viso con sorriso che fa l’occhiolino:

Esportare il codice:

aprire il file scaricato: animazione.h ed includerlo all’interno del codice:

1#include "Arduino_LED_Matrix.h"
2#include <stdint.h>
3 
4ArduinoLEDMatrix matrix;
5 
6const uint32_t animazione[][4] = {
7    // viso sorridente - frame n. 0
8  {
9        0x18c18,
10        0xc0000000,
11        0x1041fc,
12        66
13    },
14  // viso sorridente con occhiolino - frame n. 1
15    {
16        0xc18,
17        0xc0000000,
18        0x1041fc,
19        66
20    }
21};
22 
23void setup() {
24  // inizializzazione della seriale
25  Serial.begin(115200);
26  // avvio della matrice di LED
27  matrix.begin();
28}
29 
30void loop() {
31  // caricamento dalla prima animazione e visualizzazione su display
32  matrix.loadFrame(animazione[0]);
33  // attesa di 1 secondo
34  delay(1000);
35 
36  // caricamento dalla seconda animazione e visualizzazione su display
37  matrix.loadFrame(animazione[1]);
38  // attesa di 1 secondo
39  delay(1000);
40}

Esempio 04

Vediamo ora come sincronizzare la visualizzazione alternata delle due immagini con il lampeggio del LED L. Nel setup() bisognerà impostare il pin a cui è connesso il LED L ad output, dopo di che richiamare accensione e spegnimento eattamente nella stessa posizione in cui viene richiamata la funzione matrix.loadFrame():

1#include "Arduino_LED_Matrix.h"
2#include <stdint.h>
3 
4ArduinoLEDMatrix matrix;
5 
6const uint32_t animazione[][4] = {
7    // viso sorridente - frame n. 0
8  {
9        0x18c18,
10        0xc0000000,
11        0x1041fc,
12        66
13    },
14  // viso sorridente con occhiolino - frame n. 1
15    {
16        0xc18,
17        0xc0000000,
18        0x1041fc,
19        66
20    }
21};
22 
23void setup() {
24  // inizializzazione della seriale
25  Serial.begin(115200);
26  // avvio della matrice di LED
27  matrix.begin();
28  // pin a cui collegato il LED L (pin 13) impostato come output
29  pinMode(LED_BUILTIN, OUTPUT);
30}
31 
32void loop() {
33  // caricamento dalla prima animazione e visualizzazione su display
34  matrix.loadFrame(animazione[0]);
35  // accensione del LED L
36  digitalWrite(LED_BUILTIN, HIGH);
37  // attesa di 1 secondo
38  delay(1000);
39 
40  // caricamento dalla seconda animazione e visualizzazione su display
41  matrix.loadFrame(animazione[1]);
42  // spegnimento del LED L
43  digitalWrite(LED_BUILTIN, LOW);
44  // attesa di 1 secondo
45  delay(1000);
46}

Buon Making a tutti 🙂

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.