La memoria arduino ha un numero limitato di celle, 1024 su arduino uno, per cui è necessario ottimizzare la EEPROM per cercare ridurne al minimo il suo utilizzo e poter memorizzare un maggior numero di informazioni.
Il tuo progetto potrebbe dover memorizzare dati sulla EEPROM di arduino.
In questo articolo apprenderai come memorizzare un intero arbitrariamente grande e ottimizzare la EEPROM e lo spazio.
Un po’ di teoria sugli interi con arduino
Esistono diversi tipi di interi che potrai utilizzare con arduino.
Tutti i tipi hanno diverse dimensioni in BYTE, gruppi di 8 bit che ne contengono il valore in base 2, detto comunemente valore binario, per esempio 241 in base 10 equivale a 11110001 binario.
Un breve elenco di alcuni tipi disponibili chiarisce meglio le idee:
int | Numeri interi a 16bit(2 BYTE) (in alcuni modelli di arduino a 32bit) Variano da -32.768 a +32.767. (nei modelli a 32 bit da -2.147.483.648 a +2.147.483.647) |
long | Numeri interi a 32bit(4 BYTE) Variano da -2.147.483.648 a +2.147.483.647 |
long long | Numeri interi a 64bit(8 BYTE) Variano da −9.223.372.036.854.775.808 a +9.223.372.036.854.775.807 |
unsigned int | Numeri interi a 16bit(2 BYTE) o in alcuni modelli di arduino a 32bit(4 BYTE) Variano da 0 a +65.535 oppure, nei casi in cui siano a 32 bit da 0 a +4.294.967.295 |
unsigned long | Numeri interi a 32bit(4 BYTE) Variano da 0 a +4.294.967.295 |
unsigned long long | Numeri interi a 64bit(8 BYTE) Variano da 0 a +18.446.744.073.709.551.615 |
come puoi osservare, hai a disposizione per gestire quasi tutto ciò che ti si presenterà nei tuoi progetti per ottimizzare la EEPROM.
Dovrai prestare attenzione ai tipi a 64bit per due motivi:
- anche se gestiti correttamente, possono fare esplodere le dimensioni dello sketch compilato.
- Non sono supportati direttamente da metodi come print() e println() dell’oggetto serial.
Potrai comunque gestirli con alcuni trucchi che ti spiegherò in un prossimo articolo.
Tornando al tema principale, come visto nell’articolo sulle EEPROM, ogni cella ha le dimensioni di 1 BYTE, ti serviranno quindi 2 celle per un intero a 16bit, 4 per quelli a 32bit ed 8 per quelli a 64bit.
Definizione del dominio e dei limiti per ottimizzare la EEPROM
Definisci il dominio come il range che contiene il numero massimo che vorrai memorizzare.
Vediamo come puoi definire i limiti del dominio di una determinata applicazione partendo con un esempio pratico un esempio:
Supponi di voler misurare la rotazione con un encoder ad impulsi, se l’albero di rotazione è fissato in modo che ad ogni giro del albero rotore l’encoder emetta 3000 impulsi e la velocità massima del motore è di 1500 giri al minuto potresti voler memorizzare 2 giorni consecutivi.
Definiti tutti i dati per definire il limite massimo del dominio usa la seguente moltiplicazione ed otterrai il valore limite del tuo dominio:
3000 impulsi * 1500 giri/minuto * 60 minuti * 24 ore * 2 giorni = 12.960.000.000
Questo numero equivale alla massima quantità di impulsi che dovrai memorizzare se la macchina mantenesse il suo massimo regime per tutti e due i giorni, inoltre gli impulsi daranno origine a un conteggio sempre positivo.
Nello sketch avrai bisogno di una variabile a 64bit, in quanto tutte quelle più piccole non saranno sufficienti, sarà indifferente la scelta di una variabile unsigned piuttosto che signed, in quanto i numeri saranno solo positivi e sufficientemente grandi.
Con variabili signed potresti incappare in problemi legati al bit di segno ti consiglio di usare variabili unsigned.
Per memorizzare i dati invece potrai ottimizzare ulteriormente, in quanto avrai a disposizione quante celle da 8bit vorrai.
Nella seguente tabella è indicato il valore massimo solo positivo per diversi multipli di celle (BYTE):
1 CELLA o 1 BYTE | 255 |
2 CELLE o 2 BYTES | 65.535 |
3 CELLE o 3 BYTES | 16.777.215 |
4 CELLE o 4 BYTES | 4.294.967.295 |
5 CELLE o 5 BYTES | 1.099.511.627.775 |
6 CELLE o 6 BYTES | 281.474.976.710.655 |
come puoi osservare è necessario usare almeno 5 celle, in quanto 4 sarebbero poche e 6 sarebbero insufficienti.
L’algoritmo per ottimizzare la EEPROM con gli operatori booleani
A questo punto hai a disposizione una variabile a 64 bit e le 5 celle per memorizzare la lettura in essa contenuta.
Il problema consiste nel trasferire il contenuto di un grosso contenitore (variabile) in 5 contenitori più piccoli (celle).
La soluzione è più semplice di quanto pensi !
Devi spezzare il numero in pezzi più piccoli e memorizzarlo per ottimizzare la EEPROM.
Puoi spezzare il numero grazie agli operatori booleani ereditati dal linguaggio C.
Il primo operatore di cui avrai bisogno è il prodotto booleano ( AND ) indicato negli sketch con il simbolo & (come in wiring, C++ e C).
Notice
NON CONFONDERE tale operatore con il passaggio per referenza delle variabili, oppure con l’operatore indirizzo. Entrambi usano lo stesso simbolo e ciò può creare confusione.Il secondo operatore che ti servirà è lo scorrimento a destra indicato negli sketch con il simbolo >> (come in wiring, C++ e C).
Anche in questo caso non dovrai confonderlo con l’operatore per lo streaming di dati, in quanto assolve tutt’altro compito.
Cosa fanno gli operatori booleani
Ti mostro cosa fanno questi operatori con degli esempi partendo dal prodotto logico:
167.665 & 255 = 241
Scritto così ha poco significato. La stessa operazione fatta in colonna, con i numeri tradotti in base2 ti sarà molto più chiara:
Puoi intuire l’analogia con l’applicazione di una maschera, infatti tutto ciò che è sopra gli 1 rimane tutto ciò che è sopra agli zero vene azzerato (mascherato). In questo caso preservi solo i primi 8 bit del numero di partenza.
Passa all’operatore di scorrimento:
167.655 >> 8 = 654
Analizzando in colonna questo esempio, capirai cosa succede:
Gli 8 bit meno significativi sono usciti a destra, 8 nuovi bit posti a 0 ed indicati in neretto sono entrati. In giallo puoi osservare i bit spostati a destra.
Riapplica la maschera AND ed otterrai il secondo pezzo del numero di partenza e così via per quanti pezzi ti serviranno.
Lo sketch per ottimizzare la EEPROM
Ora hai a disposizione un metodo risolutivo, dovrai solo tradurlo in uno scketch. Ecco come si fa con il seguente esempio:
#include <EEPROM.h> #define ENCODER_PIN 2 // Sul pin 2 è collegato l'encoder #define PUSH_BUTTON_STORE 4 // Il pulsante al pin 2 indica quando memorizzare il valore conteggiato #define COUNTER_INDEX 200 // Un valore a caso di esempio che indica l'indirizzo in cui memorizzare il dato #define DEBOUNCE_TIME_US 5 // Tempo antirimbalzo per evitare doppie letture tenendo conto che tra due impulsi passano minimo 13 microSecondi unsigned long long value=0; // Variabile che terrà il conto void setup() { pinMode(PUSH_BUTTON_STORE, INPUT); pinMode(ENCODER_PIN, INPUT); } void loop() { if(digitalRead(PUSH_BUTTON_STORE)==HIGH) { for(int indice = 0;indice < 5;indice ++) { EEPROM.write(COUNTER_INDEX + indice, byte(value & 255)); delay(5); value=value >> 8; } value=0; } if(digitalRead(ENCODER_PIN)==HIGH) { value ++; delayMicroseconds(DEBOUNCE_TIME_US); } }
Leggendo lo sketch riga per riga:
linea 1: includi la libreria EEPROM;
linee 2-6: definisci delle costanti per rendere più leggibile il codice;
linea 8: definisci la variabile che conterrà un valore sufficientemente grande e azzerala allo stesso tempo;
linee 11-12: indica che i due piedini saranno input, al primo sarà collegato un pulsante di memorizzazione ed azzeramento, al secondo l’encoder;
linea 16: rileva la pressione del tasto o non perdere tempo;
linea 17: sei qua se il tasto è stato premuto, inizia quindi un ciclo che si ripeterà per i 5 BYTE(Celle) che devi memorizzare;
linea 18: memorizza a partire da COUTER_INDEX i 5 byte, uno per ogni ripetizione del ciclo for(). Prendi gli ultimi 8 bit a destra (Il BYTE meno significativo);
linea 19: assicurati che la EEPROM abbia il tempo di memorizzare il dato;
linea 20: sposta a destra di 8 bit value, ora gli 8 bit meno significativi sono quelli che precedevano gli 8 memorizzati;
linea 21: chiudi il ciclo for() iniziato alla linea 16;
linea 22: azzera il conteggio e preparati a ricominciare tutto;
linee 25-26: se ricevi un impulso incrementa il contatore value, attendi qualche microSecondo per evitare rimbalzi del conteggio e procedi;
Con questo articolo abbiamo visto come procedere alla memorizzazione. Prossimamente spiegheremo come rileggere i dati memorizzati e ricostruire un intero, vedremo anche alcuni trucchi inviare numeri a 64 bit sulla seriale.
Prima di inserire un commento, per favore, leggi il regolamento
13 pings
Skip to comment form