EEPROM.h su architettura ESP8266

La commit() va fatta quando vuoi effettivamente scrivere i dati su EEPROM. Immagina che la EEPROM.put() (e .write()) di fatto scrivano in un buffer in RAM che viene scaricato su EEPROM solo quando fai commit(). Quindi se devi fare tante write/put, le fai e ci metti una unica commit in fondo.

Per la seconda domanda la risposta è sì. Forse fai meglio a mettere tutti i tuoi dati in una struct e a scrivere/leggere quella.

droidprova:
Guglielmo, stavo leggendo gli esempi su gitub x quel che riguarda l'esp. E il metodo put e get non gli ho visti...

Beh nella libreria (EEPROM.h per ESP ovviamente) leggo questo:

template<typename T> 
 T &get(int const address, T &t) {
   if (address < 0 || address + sizeof(T) > _size)
     return t;

   memcpy((uint8_t*) &t, _data + address, sizeof(T));
   return t;
 }

 template<typename T> 
 const T &put(int const address, const T &t) {
   if (address < 0 || address + sizeof(T) > _size)
     return t;
   if (memcmp(_data + address, (const uint8_t*)&t, sizeof(T)) != 0) {
     _dirty = true;
     memcpy(_data + address, (const uint8_t*)&t, sizeof(T));
   }

quindi direi che ci sono, se non erro sono implementate come template C++.

ma se float occupa 4 byte significa che la mia memoria sarà occupata in automatico su eeAddress 0,1,2,3 . Quindi per un eventuale float f2 successivo devo scrivere:
EEPROM.put(eeAddress +4, f2);

Eh certo. Ma come ha detto SukkoPera, fai prima a farti una tua struct e scrivere e leggere quella senza starti a dannare con questi calcoli.

SukkoPera:
Immagina che la EEPROM.put() (e .write()) di fatto scrivano in un buffer in RAM che viene scaricato su EEPROM solo quando fai commit().

Esattamente, ma senza condizionale, altrimenti lo confondi... :slight_smile:
Di fatto nel begin() dici quanta RAM allocare per il buffer, quindi le varie write() e put() scrivono in questa RAM, e col commit() si scrive nella flash (non c'è fisicamente una EEPROM su ESP).

qualcosa non va. Dunque invio questa stringa:

Gi11930-2030-23.5

e devo ottenere da codice che incollo 5 valori separati:

19, 30, 20, 30, 23.5

byte GI1ORAON;
byte GI1MINON;
byte GI1ORAOFF;
byte GI1MINOFF;
float t_set_gi1;

.....

else if (strncmp(stringa, "GI1", 3) == 0) { // GIOVEDI'

    

      strncpy(tmp, stringa + 3, 2); // Passo il puntatore al 2 carattere di stringa, e prelevo i caratteri necessari al confronto RTC nella funzione accensioni()
      tmp[2] = '\0';
      GI1ORAON = atoi(tmp);
      EEPROM.write(addr + 19, GI1ORAON);

      strncpy(tmp, stringa + 5, 2);
      tmp[2] = '\0';
      GI1MINON = atoi(tmp);
      EEPROM.write(addr + 20, GI1MINON);

      strncpy(tmp, stringa + 8, 2);
      tmp[2] = '\0';
      GI1ORAOFF = atoi(tmp);
      EEPROM.write(addr + 21, GI1ORAOFF);

      strncpy(tmp, stringa + 10, 2);
      tmp[2] = '\0';
      GI1MINOFF = atoi(tmp);
      EEPROM.write(addr + 22, GI1MINOFF);

      strncpy(tmp, stringa + 13, 4); // preleva valore temperatura
      //tmp[4] = '\0';
      t_set_gi1 = atof(tmp);//  e lo passa alla variabile
      EEPROM.put(addr + 23, t_set_gi1);

      EEPROM.commit();
      reply = "fascia oraria giovedì/1 memorizzata";
    }

con EEPROM.put(addr + 23, t_set_gi1); se stampo da seriale t_set_gi1 è zero, ovviamente con EEPROM.write(addr + 23, t_set_gi1); è 23.

Cosa sbaglio?

GI1MINOFF = atoi(tmp);
      EEPROM.write(addr + 22, GI1MINOFF);

quanti byte è lungo un int?

e quindi dove devi scrivere il prossimo dato?

 t_set_gi1 = atof(tmp);//  e lo passa alla variabile
      EEPROM.put(addr + 23, t_set_gi1);

un int occupa 2 byte, ma tutti gli atoi generano sempre valori minori di 255, per questo penso che il tutto prima dell'inserimento dell'atof e dell'eeprom.put() abbia funzionato correttamente. Puoi spiegarti meglio?

se il risultato è sempre un byte allora ok altrimenti essendo appunto un int 2 byte e scrivendo in posizione 22 la prossima posizione deve essere la 24 e non 23
soprattutto quando poi vai a leggerlo, se leggi un intero recupererai la posizione 22 e 23,

>Patrick_M: basta che guardi il pezzo di codice al post #22 per vedere che:

byte GI1MINOFF;

... quindi UN solo byte, indipendentemente da quello che ci mette dentro ! :wink:

Guglielmo

>droidprova: ... perché non metti una Serial.println() dopo la conversione e prima della scrittura in EEPROM?

t_set_gi1 = atof(tmp); //  e lo passa alla variabile
Serial.println(t_set_gi1); // stampa il valore così puoi verificarlo
EEPROM.put(addr + 23, t_set_gi1);

Inoltre, perché qui non inserisci il terminatore ? ? ?

strncpy(tmp, stringa + 13, 4); // preleva valore temperatura
//tmp[4] = '\0';  // perchè è commentato?

Guglielmo

si hai ragione Guglielmo.... ma non sono andato a rileggere i precedenti :slight_smile:

Ripeto:

struct Parametri {
  byte LU1ORAON;
  byte LU2ORAON;
  byte LU3ORAON;
  byte LU4ORAON;
  // ...
};

Parametri param;

void save() {
  EEPROM.put (0, param);
}

Ecc...

SukkoPera:
Ripeto ...

... quella è sicuramnete la soluzione più pulita e semplice :slight_smile:

Guglielmo

Grazie a tutti, forse ci sono, ho seguito il consiglio di Guglielmo di stampare la variabile prima della put.

Dopo aver sistemato il giusto numero di spazi qui:

strncpy(tmp, stringa + 13, 6); // preleva valore temperatura

e qui:

tmp[5] = '\0';

Ora ottengo il valore con virgola e lo vedo.

Poi per verifica ho stampato questo:

EEPROM.get(addr +23, t_set_gi1);
  Serial.println(t_set_gi1, 2);

E tutto combacia. Grazie mille!!!!

X Sukko, appena capisco bene questo passaggio e poi switcho sulle struct . Grazie mille

L'ESP8266 può riservare un pezzo della flash per creare una sorta di memoria di massa, con un file system SPIFFS.
Puoi creare file e scriverci come fosse una SD.
Le EEPROM mi sembra una cosa da Ufficio Complicazione Affari Semplici, in questo caso.

Grazie zoomx, che vantaggi ha praticamente lo SPIFFS rispetto alla gestione con EEPROM? E a tal proposito quale libreria consigli?

Grazie

Che puoi creare file come ti pare, come se fosse un PC, l'unico limite è la dimensione.
La libreria è già inclusa nel core ESP9266 e la documentazione è qui
http://esp8266.github.io/Arduino/versions/2.0.0/doc/filesystem.html
ma ci sono diversi esempi in rete.
E' molto usata per gestire file da restituire via web.
Puoi anche usarlo per un log.

Buondì,

nel programma che sto finendo, faccio uso della #include <EEPROM.h>, e finchè non utilizzo il ciclo for per fare un canc della eeprom e sovrascrivere tutti i byte a zero va tutto bene. Appena faccio il canc poi non riesco più a gestire la memoria, è come se non memorizzasse più . A quel punto per far rifunzionare tutto devo riflashare il programma cancellando tutto. Perchè?

int addr = 0;
.....

for (addr = 0; addr < 512; addr++) {
        EEPROM.write(addr, 0);
      }
      delay(50);
      EEPROM.commit();

Ragazzi ho bisogno di qualche spunto/input. Dunque sto costruendo un cronotermostato che dialoga con un bot di telegram per inviare e ricevere comandi e risposte.
Vorrei attraverso il comando PROG chiedere al bot il riepilogo della programmazione fatta in precedenza.

Esempio del codice che uso per comunicare con il bot:

String message = bot.message[i][5];
    message.toUpperCase();                         // rendo maiuscola tutta la stringa per evitare errori di sintassi
    message.toCharArray(stringa, 18);              // converto la stringa message nell'array stringa
    String reply;

.......
 
else if (strncmp(stringa, "PROG", 4) == 0) {     // chiede riepilogo programmazione
      
      reply = "Riepilogo programmazione";
    }

Tutti i dati inviati che compongono la programmazione settimanale, sono storati nella eeprom e all'occorrenza vengono letti e resi disponibili sotto rete locale cliccando sul link dell'indirizzo IP della schedina. A questo punto la schedina risponde con una pagina web. La pagina web è composta sostanzialmente da righe che leggono la eeprom:

.......

client.println("· Luned&igrave;:");                    // LUNED1'
    client.println("
");
    client.println("Fascia_1: ");
    if (EEPROM.read(addr + 15) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 15), DEC);
    client.print(':');
    if (EEPROM.read(addr + 16) < 10) client.print('0');
    client.print(EEPROM.read(addr + 16), DEC);
    client.print(" / ");
    if (EEPROM.read(addr + 17) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 17), DEC);
    client.print(':');
    if (EEPROM.read(addr + 18) < 10) client.print('0');
    client.print(EEPROM.read(addr + 18), DEC);
    client.print(" - ");
    client.print("T: ");
    client.print(EEPROM.get(addr + 19, t_set_lu1), 1);
    client.println("&deg;C");
    client.println("
");
    client.print("Fascia_2: ");
    if (EEPROM.read(addr + 23) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 23), DEC);
    client.print(':');
    if (EEPROM.read(addr + 24) < 10) client.print('0');
    client.print(EEPROM.read(addr + 24), DEC);
    client.print(" / ");
    if (EEPROM.read(addr + 25) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 25), DEC);
    client.print(':');
    if (EEPROM.read(addr + 26) < 10) client.print('0');
    client.print(EEPROM.read(addr + 26), DEC);
    client.print(" - ");
    client.print("T: ");
    client.print(EEPROM.get(addr + 27, t_set_lu2), 1);
    client.println("&deg;C");
    client.println("
");
    client.print("Fascia_3: ");
    if (EEPROM.read(addr + 31) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 31), DEC);
    client.print(':');
    if (EEPROM.read(addr + 32) < 10) client.print('0');
    client.print(EEPROM.read(addr + 32), DEC);
    client.print(" / ");
    if (EEPROM.read(addr + 33) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 33), DEC);
    client.print(':');
    if (EEPROM.read(addr + 34) < 10) client.print('0');
    client.print(EEPROM.read(addr + 34), DEC);
    client.print(" - ");
    client.print("T: ");
    client.print(EEPROM.get(addr + 35, t_set_lu3), 1);
    client.println("&deg;C");
    client.println("
");
    client.print("Fascia_4: ");
    if (EEPROM.read(addr + 39) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 39), DEC);
    client.print(':');
    if (EEPROM.read(addr + 40) < 10) client.print('0');
    client.print(EEPROM.read(addr + 40), DEC);
    client.print(" / ");
    if (EEPROM.read(addr + 41) < 10)  client.print('0');
    client.print(EEPROM.read(addr + 41), DEC);
    client.print(':');
    if (EEPROM.read(addr + 42) < 10) client.print('0');
    client.print(EEPROM.read(addr + 42), DEC);
    client.print(" - ");
    client.print("T: ");
    client.print(EEPROM.get(addr + 43, t_set_lu4), 1);
    client.println("&deg;C");

.......

come posso accedere a tale marea di dati per consentire al reply di spedirmeli via bot così da abbattere il limite fisico della rete locale?

Grazie mille

droidprova:
come posso accedere a tale marea di dati per consentire al reply di spedirmeli via bot così da abbattere il limite fisico della rete locale?

Come farei io? Lascerei perdere le scritture a livello di byte ed userei la struct, come consigliato all'inizio.

Riprendo l'argomento, devo gestire una struct:

// struct dati 
struct prog {
  int a = EEPROM.read(addr + 15);
  String string1 = ":";
  int b = EEPROM.read(addr + 16);
  String string2 = "-";
  int c = EEPROM.read(addr + 17);
  String string3 = ":";
  int d = EEPROM.read(addr + 18);
  String string4 = "/";
  float e = EEPROM.get(addr + 19);
  String string5 = "°C";
};
struct prog PROG;

una volta dichiarata, come si gestisce per stamparla e far si che dalla libreria di telegram la si possa inviare come risposta?

Erm, no, devi separare dichiarazione e utilizzo:

// struct dati - Qui definisci solo come è fatta la struct, ovvero quali campi contiene
struct prog {
  int a;
  String string1;
  int b;
  String string2;
  int c;
  String;
  int d;
  String string4;
  float e;
  String string5;
};

struct prog PROG; // Qui definisci una variabile PROG di tipo prog, che dunque contiene tutti i campi di cui sopra. Nota che "struct" è opzionale in C++

void setup() {
  // Qui (o ovunque tu voglia) riempi i singoli campi della struct
  PROG.a = EEPROM.read(addr + 15);
  PROG.string1 = ":";
  PROG.b = EEPROM.read(addr + 16);
  PROG.string2 = "-";
  PROG.c = EEPROM.read(addr + 17);
  PROG.string3 = ":";
  PROG.d = EEPROM.read(addr + 18);
  PROG.string4 = "/";
  PROG.e = EEPROM.get(addr + 19);
  PROG.string5 = "°C";

Per stamparla lo devi fare un campo alla volta, come fossero tante variabili separate. Ma la cosa bella è che ora puoi fare:

EEPROM.put(0, PROG);