Error en escritura y lectura de EEPROM struct

Buenos días

estoy haciendo un desarrollo arduino con base una WAVGAT 3 Nano, (en este caso es el control de una incubadora de huevos).

Pensando en que en algún momento se pueda ir la luz o reiniciar la placa he decidido guardar una variable en la memoria EEPROM del arduino y así al arrancar de nuevo leerla y continuar el proceso de incubación con los mismos parámetros que tenía antes de reniciarse.

El problema viene en que estoy intentando guardar un string, byte a byte, y luego leerlo… y me lo “descoloca” todo.

Estoy guardando en memoria: INCUBATOR;0;37.7;55;0;24;20
y recuperando de la memoria: NCUIATOB;0;R7.7355;;;24020

Adjunto el código fuente a ver si me podéis ayudar, no entiendo porqué falla:

#include <EEPROM.h>

int eeAddress1 = 100;
    //memoria = INCUBATOR; + TIPO ANIMAL (int 1) ; TEMPERATURA (FLOAT 35.5) ; HUMEDAD (INT 2) ; ALARMA (INT 1) ; DIA (INT 2); HORA (INT 2)
    //EJEMPLO = INCUBATOR;0;37.7;55;1;15;23;
String memoria = "INCUBATOR;0;37.7;55;0;24;20";



void setup() {
  Serial.begin(9600);   // 
   for( int index = 0 ; index < EEPROM.length() ; index++ )
 {
   EEPROM[ index ] = 0;
 } 
 // put your setup code here, to run once:
 Serial.println ("MEMORIA ANTES DE ESCRIBIR");
 Serial.println(memoria);
 for (int i=0;i<memoria.length();i++){
   EEPROM.write(i,memoria[i]);
   delay(10);
 }
 
memoria = "a";

}

void loop() {


String cadena2 = "";

 for (int i=0;i<27;i++){
   byte valor = EEPROM.read(i);
   char caracter = char(valor);
   Serial.print (caracter);
   cadena2.concat(caracter);
 }
 Serial.println();




 Serial.print ("cadena: ");
 Serial.println(cadena2);

 //recuperarTextos();

 delay (100000);
 // put your main code here, to run repeatedly:

}

Bueno, acabo de probar a en lugar de escribir en posiciones de memoria continuas, escribir en posiciones múltiples de 4

(en los bucles he puesto en lugar de posición i, posición de i*4)

//Escritura
 for (int i=0;i<memoria.length();i++){
    EEPROM.write(i*4,memoria[i]);
    delay(10);
  }

//Lectura

for (int i=0;i<28;i++){
byte valor = EEPROM.read(i*4);
char caracter = char(valor);
Serial.print (caracter);
cadena2.concat(caracter);
}

y así, la escritura y la lectura han ido correctamente, ni idea de porqué pasa así.

En tu caso te seria mas facil usar un struct junto con los metodos put/get/update de la libreria EEPROM:
https://www.prometec.net/struct/
https://www.arduino.cc/en/Reference/EEPROM

Por favor @zumbio, lee las normas del foro y edita tus dos primeros post!!

Volvemos a las andadas…

he seguido el consejo del compañero y he intentado guardar un struct

struct MemoryData {
      String validador;
      int tipoAnimal ;       
      float temperatura ;       
      int humedad ;          
      boolean verificarAlarma;
      int dia;
      int hora;
   } ;

lo guardo en memoria de la siguiente forma (en la posición 10):

void guardarMemoria(){
  borrarMemoria();
  generarVariableMemoria();
  EEPROM.put(10,memoria);
}

void borrarMemoria(){
  for( int index = 0 ; index < EEPROM.length() ; index++ ){
    EEPROM[ index ] = 0;
  }
}

void generarVariableMemoria(){
  memoria.validador = "IncubatorPrototype";
  memoria.tipoAnimal = tipoAnimal;
  memoria.temperatura = TEMPERATURASET;
  memoria.humedad = HUMEDADSET;
  memoria.verificarAlarma = verificarAlarma;
  memoria.dia = currentDays;
  memoria.hora = currentHours;
}

La idea es controlar, en un reinicio inesperado, que se carguen los datos que estaban en ese momento en memoria, para ello leo de memoria en el setup() llamando a este método:

boolean recuperarDatosMemoria(){
   
  EEPROM.get(10, memoria);

  
  if (isnan(memoria.tipoAnimal) || isnan(memoria.temperatura)|| isnan(memoria.humedad)|| isnan(memoria.verificarAlarma)|| isnan(memoria.hora)|| isnan(memoria.dia)){
    return false;
  }
  if (!memoria.validador.equals("IncubatorPrototype")){
     return false;
  }
  tipoAnimal = memoria.tipoAnimal;
  TEMPERATURASET = memoria.temperatura;
  HUMEDADSET = memoria.humedad;
  verificarAlarma = memoria.verificarAlarma;
 
  return true;
}

El problema que he encontrado es que, sale por la comprobación del “if (!memoria.validador.equals(“IncubatorPrototype”))” he mostrado esa variable en pantalla y me muestra “”, como si no tuviera contenido.

¿Qué estoy haciendo mal?

Muchas gracias.

Otro error, aunque esta vez no es relacionado con la memoria eeprom es relacionado con guardar un struct en la memoria.

Tengo la definición de este struct justo debajo de los includes de las librerías .h

 typedef struct {
      String validador;
      int tipoAnimal ;       
      float temperatura ;       
      int humedad ;          
      boolean verificarAlarma;
      int dia;
      int hora;
 } MemoryData;

al compilar.. siempre me da el siguiente error:

'MemoryData' does not name a type

otro error que no se resolver...

Gracias a todos

Creo que el problema se debe al uso del objeto String.

He utilizado el siguiente código de ejemplo:

#include <EEPROM.h>

String s="El perro de San Roque no tiene rabo";

void setup()
{
  EEPROM.put(0, s);
}

void loop()
{
  
}

Y he tenido de resultado esto:

eeprom1.jpg

Como ves, no es la cadena que se esperaba.

Mi consejo, no utilices clases, ni objetos que puedan tener una longitud variable (como es el caso de
string).

Por ejemplo:

#include <EEPROM.h>


char s[64]="El perro de San Roque no tiene rabo";

void setup()
{
  int i=0;
  while (s[i]!=0)
  {
    EEPROM.put(i, s[i]);
    i++;
  }
}

void loop()
{
  
}

He utilizado un array y escribo byte a byte. Es un ejemplo, que se puede mejorar, así que no es perfecto, pero el resultado es el siguiente:

eeprom3.jpg

Prueba a ver que ocurre si en el struct cambias el string por char variable[longitud]
y nos cuentas.

Hola, gracias por la respuesta, he quitado del struct el string

 typedef struct {
      int tipoAnimal ;       
      float temperatura ;       
      int humedad ;          
      boolean verificarAlarma;
      int dia;
      int hora;
 } MemoryData;

parece que guarda y lee pero lee lo que le sale de las narices jajajaj,

Por ejemplo, guardando como datos, tipoAnimal=2, temperatura=37.8, humedad=60, verificarAlarma=true, dia=1 y hora =3

al reiniciar me recupera: tipoAnimal = 0, temperatura = 37,8 (OK), humedad = 51, día = 32 y hora = 10…

flipante jajaj

Se me olvidó el detalle de indicar que cada vez que subes un sketch el ide de arduino borra la eeprom, asi que hay que tener eso en cuenta.

Vamos a más… digo pues voy a escribir un array de chars… a ver si así…

ahí va el código, tan sencillo como escribir y leer tras una pausa:

#include <EEPROM.h>

void setup() {
   Serial.begin(9600);   // 

}

void loop() {
  char memory [11] ={'a','b','c','d','e','f','g','h','i','j','k'};
 for (int i=0;i<11;i++){
   Serial.print ("escribiendo en posicion ");
   int posicion = 10*i;
   Serial.print (posicion);
   Serial.print (" el valor ");
   Serial.println (memory[i]);
   EEPROM.write(posicion, memory[i]);
 }
  delay(3000);
  leerMemoria();
}

void leerMemoria(){
  
  int b;
  char a;
  for (int i=0;i<11;i++){
    int posicion = 10*i;
    b = EEPROM.read(posicion);
    a = b;
    Serial.print("recuperando posición ");
    Serial.print (posicion);
    Serial.print (" con el valor ");
    Serial.println (a);
  }
}

pues esto me muestra en el monitor de serie lo siguiente:

escribiendo en posicion 0 el valor a
escribiendo en posicion 10 el valor b
escribiendo en posicion 20 el valor c
escribiendo en posicion 30 el valor d
escribiendo en posicion 40 el valor e
escribiendo en posicion 50 el valor f
escribiendo en posicion 60 el valor g
escribiendo en posicion 70 el valor h
escribiendo en posicion 80 el valor i
escribiendo en posicion 90 el valor j
escribiendo en posicion 100 el valor k

recuperando posicion 0 con el valor k
recuperando posicion 10 con el valor
recuperando posicion 20 con el valor
recuperando posicion 30 con el valor
recuperando posicion 40 con el valor
recuperando posicion 50 con el valor
recuperando posicion 60 con el valor
recuperando posicion 70 con el valor
recuperando posicion 80 con el valor
recuperando posicion 90 con el valor
recuperando posicion 100 con el valor

Creo que hay algo mal con tu arduino.

El código que posteaste lo simulé en proteus y ok. Lo puse en un Arduino y ok.

Gracias,

Me estaba volviendo loco, Trevi le tengo pedidas otras dos placas iguales (wavgat nano o algo así) probaré con una de ellas...

A mi tambien me funciona en un arduino nano

Como te han dicho funcion put y get de la clase eeprom no trata bien ni objetos(como String) ni punteros.

Usa un array de char de longitud fija para las cadena y solo tipos básicos.
El siguiente código funciona bien, guardando y recuperando los datos desde una estructura.
Para las cadenas hay que copiarlas al miembro de la estructura, si viene de una variable o constante se usa así:

strcpy(datos.validador,"INCUBATOR");

Pero si viene de un String, se usa la funcion miembro c_str();

String a = "INCUBATOR";

strcpy(datos.validador,a.c_str());

saludos

#include <Arduino.h>
#include <eeprom.h>

struct MemoryData {
      char validador[15];
      int tipoAnimal ;
      float temperatura ;
      int humedad ;
      boolean verificarAlarma;
      int dia;
      int hora;
    };


MemoryData datos,datosR;

void setup() {
  String validador="INCUBATeR";


  Serial.begin(9600);



  strcpy(datos.validador,validador.c_str());
  datos.tipoAnimal=0;
  datos.temperatura=37.7;
  datos.humedad=55;
  datos.verificarAlarma=0;
  datos.dia=24;
  datos.hora=20;

  // Se guardan los datos en la direccion 0 de la eeprom.
  EEPROM.put(0,datos);

  // Se recuperan los datos en la otra estructura.
  EEPROM.get(0,datosR);

  Serial.println(datosR.validador);
  Serial.println(datosR.tipoAnimal);
  Serial.println(datosR.temperatura,1);
  Serial.println(datosR.humedad);
  Serial.println(datosR.verificarAlarma);
  Serial.println(datosR.dia);
  Serial.println(datosR.hora);



  }

void loop() {

  }

Gracias, creo que como dijo el compañero es un problema de la placa, he probado en otra y el funcionamiento ha sido correcto. De todas formas gracias por los consejos