Come risparmiare memoria su Arduino
Per memorizzare la struttura dei caratteri da visualizzare su un display a led a 8 righe (es. display 8x32 di led WS2812) serve un’array boolean a due dimensioni da 8 righe per 40 colonne.
In Libreoffice Calc ho dimensionato le Righe con Formato > Righe > Altezza e Formato > Colonne > Larghezza 0,75 cm:
e colorato le celle contenenti 0 e 1 con Formato > Formattazione condizionata > Condizione…:
In A8 introduco la formula:
=A1*1+A2*2+A3*4+A4*8+A5*16+A6*32+A7*64+A8*128
e la copia a destra nelle altre 39 celle.
Ottenendo questo risultato:
Questo è il codice necessario a creare la matrice booleana in Arduino:
boolean matnumeri[8] [40] {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,0,1,1,1,0,0,1,0,0,0,1,0},
{0,1,0,1,0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1},
{0,1,0,1,0,1,0,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,1,1,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,1},
{0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,1,1,0,0,0,1,0,1,0,1,0,0,1,0,0,1,0,1,0,1,1,1},
{0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1},
{0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,0,1,0,1,1,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
Ho scoperto che le variabili booleane su Arduino occupano comunque un byte di memoria di:
byte matnumeri[8] [40]
Capite che una matrice contenente una stringa di meno di venti caratteri da 8 x 6 pixel ciascuno andrebbe, da sola, a riempire tutta la memoria per le variabili globali di un Arduino Mega.
Come risolvere il problema risparmiando molta memoria usando una sola riga al posto di otto?
Trasformo ogni singola colonna della matrice, considerandola come numero binario a 8 bit, in un numero decimale.
La dichiarazione della matrice nel codice diventerà:
byte matnumeri[40] = {0,126,66,126,0,8,4,126,0,70,98,94,0,66,74,126,0,30,16,120,0,78,74,122,0,126,74,122,0,98,26,6,0,126,74,126,0,94,82,126};
Ora però, al momento di visualizzare i caratteri sul display dovrò fare la conversione inversa.
int valbyte = matnumeri[n];
for (int l = 0; l < 8; l++) { // Scorre le 8 righe della matrice
bitinbyte = 0.5 + pow(2, l); // calcola la potenza di 2 corrispondente alla riga
int findbitinbyte = valbyte & bitinbyte;
boolean valbit = findbitinbyte == bitinbyte; // Estrae il valore del bit corrispondente
…
}
Esempio:
per n = 1
matnumeri[1] è 126, 00111100 in binario
per l = 3;
bitinbyte = 0.5 + pow(2, 3) è 8
N.B.: pow(base, exponent) usa come parametri (base) e (exponent) variabili di tipo float (a virgola mobile). Ho scoperto che pow(2, 3) da come risultato 7 perché è il risultato 7.99999999… visualizzato come intero. Per risolvere il problema ho aggiunto 0.5.
& [Operatore bit a bit]
L'operatore AND bit a bit in C ++ è una singola e commerciale (&), utilizzata tra altre due espressioni integer. Bitwise AND opera indipendentemente su ogni posizione di bit delle espressioni circostanti, in base a questa regola: se entrambi i bit di input sono 1, l'uscita risultante è 1, altrimenti l'uscita è 0.
Per chiarire meglio usiamo il nostro esempio (valbyte = 126) e (bitinbyte = 8):
int findbitinbyte = valbyte & bitinbyte;
0 0 1 1 1 1 0 0 valbyte
0 0 0 0 0 1 0 0 bitinbyte
----------
0 0 0 0 0 1 0 0 (valbyte & bitinbyte) - risultato restituito è 8
boolean valbit = findbitinbyte == bitinbyte;
Se findbitinbyte e bitinbyte sono uguali il risultato sarà 1 (true) altrimenti 0 (false);
Il terzo bit (di valore 8 23) di 126 (00111100) da destra a sinistra è 1.
4 agosto 2018
Scritto da Giuseppe Tamanini con licenza CC BY-SA
|