Utilizar EEEPROM guardando String y recogiendo String

Buenas! como están queridos amigos.

Empecé un proyecto con una App, el objetivo es enviar una palabra (String) a través de Bluetooth y el Micro reconozca esa palabra, la procese y la compare con una palabra almacenada en la EEPROM del Micro,y luego realice una acción:
Encender una luz Verde si la palabra es correcta y encender una luz roja si la palabra es incorrecta.
Puedo realizar este procedimiento utilizando una variable con una palabra (String) fija pero no puedo lograr compararla con una palabra almacenada en la EEPROM.
Quiero utilizar la EEPROM por dos razones:
1- Crear una rutina que pueda cambiar la palabra almacenada en la EEPROM, y desde ahi empezar a comparar los valores que ingresan desde el Bluetooth con la nueva palabra.
2- En caso de que se corte la luz del dispositivo, la palabra que se cambió quede siempre guardada.

Les paso el Codigo que ya tengo.

#include <EEPROM.h>
#include <SoftwareSerial.h>
  SoftwareSerial mySerial(2,3); // 2=TX, 3=RX
  int i;
  char inicio=19;                     //variable que indica el inicio del programa
  char correcto=18;                   // variable que indica el dato correcto 
  char error=17;                      // variable que indica dato incorrecto
  char salida=16;                     // salida del rele/actuador
  String rxbt;                          // variable donde se almacena la informacion recibida del BLE
  String memoria;                     // variable donde se guarda el dato recibido despues del caracter de programacion
  String apertura[9];
  String prog="programar";
void setup() 
{
  mySerial.begin(9600);               // inicio del puerto serie del BLE
  Serial.begin(9600);                 // inicio del puerto serie de la PC
  pinMode(correcto,OUTPUT);           // modo de los pines i/o
  pinMode(inicio,OUTPUT);
  pinMode(error,OUTPUT);  
  
}

void loop() 
{
  digitalWrite(inicio,HIGH);          // estado de los pines
  digitalWrite(correcto,LOW);
  digitalWrite(error,LOW);

  if (mySerial.available())             // se chequea si el puerto seria del BLE esta disponible
{
    
  rxbt=mySerial.readStringUntil('\n');// leo valor y se lo asigno a la variable rxbt
  Serial.println("DATO RECIBIDO");    // muestro en pantalla el dato recibido
  Serial.println(rxbt); 
  Serial.println();


  
  Serial.println("Apertura...");
  Serial.println(apertura[9]); 
  Serial.println();
  Serial.println("Memoria...");
  Serial.println(memoria); 
  Serial.println();
  Serial.println();
  Serial.println("EEPROM...");


    char cero=EEPROM.get(0,memoria[0]);
    char uno=EEPROM.get(1,memoria[1]);
    char dos=EEPROM.get(2,memoria[2]);
    char tres=EEPROM.get(3,memoria[3]);
    char cuatro=EEPROM.get(4,memoria[4]);
    char cinco=EEPROM.get(5,memoria[5]);
    char seis=EEPROM.get(6,memoria[6]);
    char siete=EEPROM.get(7,memoria[7]);
    char ocho=EEPROM.get(8,memoria[8]);
    char nueve=EEPROM.get(9,memoria[9]);


    Serial.println(cero); 
    Serial.println(uno); 
    Serial.println(dos); 
    Serial.println(tres); 
    Serial.println(cuatro); 
    Serial.println(cinco); 
    Serial.println(seis); 
    Serial.println(siete);
    Serial.println(ocho); 
    Serial.println(nueve); 

 



    if(rxbt==apertura[9])                // se compara variables para hacer lo siguiente
    {
    digitalWrite(correcto,HIGH);  // enciende luz verde
    digitalWrite(inicio,HIGH);    //
    digitalWrite(salida,HIGH);    // activa la salida del actuador
    digitalWrite(error,LOW);      //
    Serial.println("ABIERTO");    // muestra en pantalla que se abrio la puerta
    mySerial.println("TRUE");
    delay(2000);                  // despues de 2seg. los pines vuelven a su estado inicial
    digitalWrite(correcto,LOW);   //
    digitalWrite(salida,LOW);     //
    digitalWrite(inicio,HIGH);    //
    digitalWrite(error,LOW);      //    
    Serial.println("CERRADO");    //
    }

       if (rxbt==prog)                // si el valor ingresado es cualquier cosa menos el valor de PROG hace lo siguiente
      { 
            delay (3000);                  
            memoria=mySerial.readStringUntil('\n');
            Serial.println("Valor de Memoria Cambiado a...");// Imprime en pantalla el valor nuevo 
            Serial.println(memoria);
            apertura[9]=memoria;
              for(i=0;i<9;i++)
                  {
                   EEPROM.put(i,memoria[i]);
                  } 
                          
            digitalWrite(correcto,HIGH);  // El led verde titila 3 veces para mostrar que el proceso es correcto.
            delay (500);
            digitalWrite(correcto,LOW);
            delay (500);
            digitalWrite(correcto,HIGH);
            delay (500);
            digitalWrite(correcto,LOW);
            delay (500);
            digitalWrite(correcto,HIGH);
            delay (500);
            digitalWrite(correcto,LOW);
            delay (500);
            mySerial.println("TRUE");// Imprime en pantalla el valor nuevo 
            mySerial.println(memoria);
            delay (500);

       }
    else if ((rxbt!=prog)&&(rxbt!=apertura[8])&&(rxbt!='?')&&(rxbt!='⸮'))                     // si el valor ingresado es cualquier cosa menos el valor de PROG hace lo siguiente
  { 
    digitalWrite(error,HIGH);          // se enciende led rojo
    Serial.println("Dato Incorrecto"); // se imprime en pantalla
    mySerial.println("FALSE");
    delay(2000);                       // luego de 2 seg. vuelve a su estado inicial
    digitalWrite(error,LOW);
    delay(1000);                       // luego de 2 seg. vuelve a su estado inicial
    
  }     
 }
}

Como puedo hacer para almacenar los valores de la palabra nueva? El ciclo for que utilice para almacenar la palabra en la EEPROM no me funciona. Si pudieran guiarme a una solución estaría muy agradecido.

Te paso dos funciones que pueden serte utiles:

void StringToEEPROM(int offset, const String &str) {
  byte len = str.length();
  EEPROM.write(offset, len);
  for (int i=0; i<len; i++)
    EEPROM.write(offset+i+1, str[i]);
}

String readStringFromEEPROM(int offset) {
  int len = EEPROM.read(offset);
  int i;
  char data[len+1];
  for (i=0; i<len; i++)
    data[i]=EEPROM.read(offset+i+1);
  data[i]=0;
  return String(data);
}

La primera de ellas escribe un string en la EEPROM. En realidad lo que guarda es, primero el tamaño del string y luego los caracteres que componen el string.

La segunda función lee el string de la EEPROM, primero lee el tamaño y después lee los caracteres guardandolos en un string.

La clave está en usar bien el offset, es decir, la posición en la eeprom donde vas a empezar a escribir, sobretodo evitando que haya colisiones: una cadena en la eeprom se guarda dentro de la posición de memoria que ocupa otra.

Puedes por ejemplo asignar un tamaño maximo de palabra, por ejemplo 31 bytes mas otro de tamaño y guardar las cadenas en las posiciones, 0, 32, 64, 96, 128, etc. Y cuando leas por Serial ir comparando leyendo cada posición.

Tan solo es una idea.

Esta forma es tal vez la mas adecuada porque EEPROM.get y EEPROM.put soportan Strings.

#include <EEPROM.h>

String val = "1234abcdef";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  int address = 0;
  EEPROM.put(address, val);
  Serial.println("Esto almaceno =" + val);
  String str = "";
  EEPROM.get(address, str);
  Serial.println("Esto he leido =" + str);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Esto almaceno =1234abcdef
Esto he leido =1234abcdef

Saludos, me parece muy interesante ambas soluciones.

Quisiera preguntar algo antes de probarlo yo a lo bestia

¿ EEPROM.get y EEPROM.put ? serían las herramientas más adecuadas para grabar y leer una estructura personal de datos ?

De esa manera se podría grabar toda la configuración de un sketch de un sólo plumazo en la EEPROM ¿estoy en lo cierto?

Es correcto Tony. EEPROM.get y put trabajan a escala grande permitiendo que cualqueir variable pueda leída o almacenada respetando el tipo o tipos de variable utilizadas y las versiones read y write trabajan solo a nivel byte como en las primeras versiones de Arduino. Digamos que get y put son la evolución obviamente apoyadas en read y write.

Gracias por responder, de todas maneras y dado que voy a utilizar un DUE, esa opción ha quedado descartada, pero aprovecho para preguntar a nivel general

Ya que la vida de la EEPROM es limitada en cuanto a escritura (pensando en otras cosas a futuro) ¿Alguien tiene noción o ha experimentado sobre la ida útil efectiva de esta posibilidad?

100.000 grabaciones parecen muchas si no se están realizando grabaciones continuas en la misma, y tengo curiosidad sobre la experiencia de otros Arduineros.

Lo pregunto pensando en unidades como esta:

Muy económicas y de vida de 1.000.000 de ciclos, es decir, 10 veces más que la del Arduino

Gracias

TonyDiana:
Ya que la vida de la EEPROM es limitada en cuanto a escritura (pensando en otras cosas a futuro) ¿Alguien tiene noción o ha experimentado sobre la ida útil efectiva de esta posibilidad?

Hola, hace unos dias "queme" una 256 en segundos!! todo por no haber puesto "n=0;" en la programacion , en fin yo me entiendo y quiero dar a entender que hay que ser cuidadoso con las EEPROM.

Creo ademas que las funciones get y put (y la libreria EEPROM en general) no leen la 256 o por ejemplo la 32 que que llevan los modulos RTC, etc.

Saludos.

Gracias por el dato

Ya que la vida de la EEPROM es limitada en cuanto a escritura (pensando en otras cosas a futuro) ¿Alguien tiene noción o ha experimentado sobre la ida útil efectiva de esta posibilidad?

100.000 grabaciones parecen muchas si no se están realizando grabaciones continuas en la misma, y tengo curiosidad sobre la experiencia de otros Arduineros.3

Bueno ya que lo preguntas, hace un tiempo quise hacer una prueba e hice un código que escribía un numero luego en la EEPROM despues lo leía e imprimía por puerto serial, después de eso sumaba uno y se repetía el ciclo de escritura haciendo un log. y duro poco mas de 3 millones de escrituras, después comenzó a dar errores, así que en conclusión esas 100 000 escrituras solo es lo que te garantiza el fabricante, pero puede durar mucho mas

Gracias, creo que volveré a la ida original de usar la SD, pero me parece super interesante

Yo había leído de 1 millón pero ya ves que RIG llegó a 3 millones. Impresionante!!