Arduino: ottimizzare la EEPROM

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.

ottimizzare la eeprom

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:

  1. anche se gestiti correttamente, possono fare esplodere le dimensioni dello sketch compilato.
  2. 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:

ottimizzare la eeprom
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).

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:

ottimizzare la eeprom

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:

ottimizzare la eeprom shift

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

Permanent link to this article: https://www.mauroalfieri.it/informatica/arduino-ottimizzare-la-eeprom.html

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.