Grabacion y recuperacion de valores desde la eprom

Hola, estoy investigando para poder almacenar varios valores en la eprom, los valores son parametros de configuracion del programa con el que estoy liado y era por preguntar si alguien tiene ya hecho algo asi para poder utilizarlo de ejemplo ?

Tienes explicado el funcionamiento en la referencia:
http://www.arduino.cc/en/Reference/EEPROM

Lo lamento, acabo de ver que pregunte exactamente lo mismo no hace mucho tiempo en otro post, lo he repetido aunque sigo con los mismos problemas…

Chiva te doy mas detalles a ver si me puedes orientar…

Mediante puerto serie con el pc envio al arduino comandos y algunos valores de configuracion que quiero almacenar en la epprom…

Por ejemplo tengo un parametro de configuracion que es PAUSA que puede tener un valor entre 0 y 9999 ms…

Por puerto serie le envio al arduino la instruccion

A0340X

y en el arduino tengo establecido que si recibo A los siguientes caracteres son el valor y X termina el valor

Como los valores de cada memoria de la epprom (por lo que tengo entendido ya que de programacion si tengo mas experiencia pero de electronica toy pez ) pueden ser de 0 a 255 lo que se me ha ocurrido es “cortar” el parametro en 4 partes…

String Cadena = "";
int Valores[4] = {0,0,0,0} 

int Recibido = Serial.read();

if (Recibido != 'X') {
        if (ncar < 4) {
          Cadena = Cadena + char(Recibido);
          Valores[ncar] = int(Cadena[ncar]);
          if ( (Valores[ncar] > 0) && (Valores[ncar] < 10) ) {
            Serial.print("VALOR CORRECTO");
          }
          ncar++;
        }
        else { 
          Serial.print("> VALOR DEMASIADO LARGO."); 
        };
      }

Y para guardar los valores a la epprom estoy utilizando :

  EEPROM.write(0,Cadena[0]);
  EEPROM.write(1,Cadena[1]);
  EEPROM.write(2,Cadena[2]);
  EEPROM.write(3,Cadena[3]);
  Serial.print("    GRABADO     ");
  delay(1000);

Mas o menos hasta ahi funciona la cosa, ahora tengo el problemilla de como rescatar esos datos para poder utilizarlos una vez que los tengo almacenados, para ello estoy utilizando el siguiente codigo:

String Cadena2 = "";
int Prueba2 = 0;

Cadena2.concat(EEPROM.read(0));
Cadena2.concat(EEPROM.read(1));
Cadena2.concat(EEPROM.read(2));
Cadena2.concat(EEPROM.read(3));
Prueba2 = atoi(Cadena2);

El problema que estoy encontrando con este codigo es en la linea:

Prueba2 = atoi(Cadena2);

Que no me deja compilar y me devuelve el error:

error: no se puede convertir ‘String’ a 'const char*" para el argumento ‘1’ para ‘int atoi(const char*)’

Solo hago buscar una funcion que me convierta de String a Integer pero por mas que busco solo encuentro ese “atoi()” y no consigo hacerlo funcionar

Seguramente me sobra la mitad del codigo pero como soy nuevo con este lenguaje estoy aprendiendo a base de prueba error,

¿ Chiva sabes decirme como hacer lo que yo quiero ?

Gracias por tu tiempo

Siento la respuesta tan seca de antes, pero iba bastante justo de tiempo.

Me temo que atoi no podrá pasar de String a entero, ya que creo que sólo pasa de char a entero, por lo que mejor hacerlo con char que seguro que funciona.

char valor[5];
int convertido;

for (int i=0;i<5;i++){
  valor[i] = EEPROM.read(i);
}
valor[5] = '\0';
convertido = atoi(valor);

Así debería funcionar

Un saludo

He probado pero no se porque me mete un 0 de más…

para salir del paso, como me di cuenta que los “valores” en la epprom creo que se guardan en ascii o al menos es lo que me estoy encontrando cree esta función patatera pero me da el apaño jeje :

  int AsciiToInt(String Valor) {
  
  if (Valor == "0") {
      return 0; }
  if (Valor == "1") {
      return 1; }      
  if (Valor == "2") {
      return 2; }      
  if (Valor == "3") {
      return 3; }      
  if (Valor == "4") {
      return 4; }
  if (Valor == "5") {
      return 5; }    
  if (Valor == "6") {
      return 6; }  
  if (Valor == "7") {
      return 7; }      
  if (Valor == "8") {
      return 8; }
  if (Valor == "9") {
      return 9; }
  }

(Creo que con un switch quedaria más clara pero no recuerdo si admite un string como valor a comparar…)

y utilizando este metodo para rescatar los datos de la epprom partiendo que tengo almecenado “0080” :

  int LeerValorDuracion() {
    int valorrt = 0;
    valorrt = AsciiToInt(EEPROM.read(3));
    valorrt = valorrt + ( AsciiToInt(EEPROM.read(2)) * 10);
    valorrt = valorrt + ( AsciiToInt(EEPROM.read(1)) * 100);
    valorrt = valorrt + ( AsciiToInt(EEPROM.read(0)) * 1000);*/
    
    return valorrt;

Me devuelve el dato correcto 80

Pero modificando la función a como me indicas…

  int LeerValorDuracion() {
    int valorrt = 0;
    char valor[5];
    for (int i=0;i<5;i++){
      valor[i] = EEPROM.read(i);
    }
    valor[5]='\0';
    valorrt = atoi(valor);
    return valorrt;

Me devuelve digamos que un 0 de mas porque me dice 800…

La verdad es que no comprendo donde esta el fallo, ese for no lo tengo muy estudiado aun…

Y la línea

valor[5]='\0';

si te digo la verdad ni idea de para que es… :-/

Fallo mio, hace un tiempo que no programo y se nota ;D

int LeerValorDuracion() {
    int valorrt = 0;
    char valor[5];
    for (int i=0;i<4;i++){
      valor[i] = EEPROM.read(i);
    }
    valor[5]='\0';
    valorrt = atoi(valor);
    return valorrt;

El valor[5]?=’\0’ le mete un indicador para saber donde acaba la cadena. Esto debe estar al final de cualquier array/vector pero por defecto ya se pone así que deberías poder borrar esa línea.

El for va sacando los valores de las posiciones 0,1,2 y 3 de la EEPROM y las mete en las posiciones 0,1,2 y 3 del vector de carácteres. Si

Por cierto, pasar de Ascii a entero es muy sencillo:

int AsciiToInt(String Valor){
  return Valor-30;
}

Si miras una tabla ASCII verás que el 0 corresponde al 30 ascii, el 1 al 31, por lo que si le restas 30 obtendrás el número tal cual.

Da gusto que pregunte gente como tú, con las cosas claras, sin rodeos, mostrando el código, explicando que funciona y dónde está probablemente el problema, una maravilla.

Un saludo

Gracias chiva aunque voy a dar un poco mas el coñazo jeje…

si intento compilar la función:

int AsciiToInt(String Valor) {
    
    return Valor - 30;

Me dice

error: no match para ‘operador-’ en ‘Valor - 30’

me imagino que será por que no le gusta que sea una String, he probado a cambiarlo a tipo char pero entonces me devuelve un nuemero raro… ¿ 20008 ? cuando el valor que hay almacenado es “0010”

Y ya para rematar de cosas raras es esto…

tengo establecida una variable llamada PrimerArranque declarada como true tipo bolean, en el void loop nada mas empezar tengo este codigo:

if (PrimerArranque){
    LCD_Presentacion(); // PANTALLA DE BIENVENIDA
    LCD_Valores(); // MUESTRO LOS VALORES ALMACENADOS
    LCD_Presentacion(); // VUELVO A MOSTRAR LA PANTALLA DE BIENVENIDA
    LCD_Clear(); // BORRO LA PANTALLA
    PrimerArranque = false; // DESACTIVO EL PRIMER ARRANQUE
    if (PrimerArranque) {
       LineaSR("PRIMER ARRANQUE"); } // LINEAS DE DEPURACION
    else { LineaSR("POS NO");}
    delay(500);
  };

Esque tengo puesta una pantalla LCD serie y por ahi voy depurando el programa…

Lo extraño es que LCD_Valores muestra en la pantalla los parametros de configuracion que rescato de la EEPROM, por alguna extraña razón que no llego a entender si utilizo la función que me has indicado para extraer los valores de la EEPROM:

  int LeerValorDuracion() {
    int valorrt = 0;
    char valor[5];
    for (int i=0;i<4;i++){
      valor[i] = EEPROM.read(i);
    }
    valor[5] = '\0';
    valorrt = atoi(valor);
    return valorrt;
    
  };

En vez de esta otra:

    int valorrt = 0;
    valorrt = AsciiToInt(EEPROM.read(3));
    valorrt = valorrt + ( AsciiToInt(EEPROM.read(2)) * 10);
    valorrt = valorrt + ( AsciiToInt(EEPROM.read(1)) * 100);
    valorrt = valorrt + ( AsciiToInt(EEPROM.read(0)) * 1000);
    return valorrt;
  };

La aplicación en el void loop nunca pasa de la linea:

    LCD_Valores(); // MUESTRO LOS VALORES ALMACENADOS

y este es el codigo de LCD_Valores():

  void LCD_Valores(){
    LCD_Clear(); // LIMPIO PANTALLA
    LineaSR("    VALORES     "); // MUESTRO LINEA
    LCD_Posicion(17); // CAMBIO POSICION
    LineaSR("----------------"); // MUESTRO LINEA
    delay(2000);
    LCD_Clear();
    LineaSR("  TIEMPO CORTE  ");
    LCD_Posicion(17);
    LineaSR("  DE SUBIDA     ");
    LCD_Posicion(29);
    LineaSR(LeerValorDuracion() );
    delay(3000);
    LCD_Clear();
    LineaSR("RETRASO ");
    LCD_Posicion(17);
    LineaSR("  DE SUBIDA     ");
    LCD_Posicion(29);
    LineaSR(LeerValorRetraso());
    delay(3000);

La funcion se ejecuta, llega hasta el delay(3000), ejecuta el delay y despues en vez de seguir por la linea en la que vuelvo a mostrar la pantalla de bienvenida dentro de ese if de si es el primer arranque, coge y no se si el arduino se reinicia o se reinicia el void loop pero vuelve a iniciarse el void loop en vez de continuar por donde debia… ¿ sera cosa de la 021 ? ¿ tendre un poltergai en mi arduino ? que cosas mas raras…

:o

Solucionado lo del reset dejando la funcion de lectura de los valores asi:

 int LeerValorDuracion() {
    int valorrt = 0;
    char valor[4];
    for (int i=0;i<4;i++){
      valor[i] = EEPROM.read(i);
    }
    valorrt = atoi(valor);
    return valorrt;

quitando la linea de valor[5] = ‘\0’ ya deja de reiniciarse pero por probar despues he bajado el tamaño del char a 4 y funciona bien tambien coge los 4 digitos del valor. :smiley:

el de pasar de ascii a int es el que no he arreglado aun :-?

Si hoy me parece que me he levantado con el pie izquierdo, por que vamos, no doy ni una.
Nunca me acuerdo de que String es un objeto y sobre lo de restar 30, cambia el 30 por ‘0’ con comillas incluidas (es 30, pero en hexadecimal, en decimal sería 48) y ahora debería funcionar correctamente la conversión.

Prueba este código a ver si te funciona, ya que no hace llamadas a ninguna función rara:

  int LeerValorDuracion() {
    int valorrt = 0;
    for (int i=0;i<4;i++){
      valorrt *= 10;
      valorrt += EEPROM.read(i)-'0';
    }
    return valorrt;
  }

Un saludo

Esa va perfecta tal y como indicas ahí, Muchas gracias :D

La tendré que estudiar con detenimiento que algunas cosas no las comprendo, mañana ya con menos sueño y más tiempo la estudio tranquilamente jeje.

Y esta otra, crees que tendrá solución ?

  int AsciiToInt(String Valor) {
    
    return Valor - '0';

Si intento compilar me dice

error: no match para 'operator-' en 'Valor -'0''

Con la lectura de los valores anteriores ya me apaño pero es por tenerla en la librería que proximamente me quiero crear con todas las funciones que voy recopilando... ::)

Prueba a ver con esto:

int AsciiToInt(char Valor) {
   return Valor - '0';
}

Si no te funciona así ya le tendría que echar un vistazillo más a fondo, pero en un par de días, ya que ando un poco mal de tiempo.

Un saludo

Buenas.

Joystick, he visto que lo que estás haciendo es guardar un número en la eeprom en formato ascii, pero es mejor que lo guardes en hexadecimal ya que en hexadecimal un int de arduino ocupa 2 bytes mientras que el mismo número en ascii te ocuparía 4 bytes, es decir, el doble. Si quieres guardar el número en hexadecimal, lo único que tienes que hacer es convertir primero la cadena a int y después partes el número con un desplazamiento de bits y una máscara y ya está a funcionar XD.