leer datos por puerto serie almacenados en EEPROM - validación de String

Hola, muchas gracias por tomarse el tiempo en atender a la presente, Resumen de lo deseado:
Necesito hacer un reloj con Arduino, en el cual ingresare 6 rangos de horarios, cada rango de horario tiene 6 variables:
Hon = Hora de inicio de ciclo
Mon = Minuto de inicio de ciclo
Hoff = Hora de apagado de ciclo
Moff = Minuto de apagado de ciclo
Ton = PEriodo durante el ciclo en el que se activan 2 relays conectados a los pines 4 y 5
Toff = Periodo durante el cuclo en el que se apagan los 2 relays mencionados.
Se desea ingresar los valores usando Softwareserial (2,3), el puerto serie de Arduino lo dejo libre para ver el comportamiento del sketch durante las ejecuciones.
Para aislar el problema realice lo siguiente, Al ingresar por BT (Bluetooh) solo 1 caracter desde A hasta F (Ciclo 1 hasta 6 respectivamente), el Sketch se ejecuta a la perfeccion.
Pero cuando ingreso las variables mencionadas (Hon,Mon, Hoff, etc…) mediante un String separado por comas y con un comando finalización por ejemlplo:
Rango inicia 11h00 hasta 14h00 Ton= 14seg y Toff = 2 min el String sería de la siguiente manera:
String enviado por BT 11,00,14,00,14,2, este String lo valido matematicamente, que sean ENTEROS, y depues lo almaceno en una dirección de EEPROM, para posteriormente leerlos y almacenarlos en un String de ejecución llamado VECTOR_RELAY, en este caso, todo funciona bien, PEEEROOO!!! despues de intentar ingresar varias veces un rango en la misma posición el SKETCH se inhibe!!
Que realice? Investigue y he liberado la memoria del Arduino UNO lo mas que puedo, actualmente mi sktch esta a un 63% y la memoria está a un 55%, de lo cual no esta nada mal… Adicional he investigado el metodo de ingresar cadenas por String, y cuando prueba la técnica SOLITA sin nada mas de código funciona a la perfección, por tanto no creo que sea la forma de leer el String… sin embargo… SOSPECHO que la info guardada en la EEPROM a veces… y eso es lo que no se como validar, la información se almacena con DATOS BASURA, que al leerlos y guardarlos en el VECTOR_RELAY causa que el sketch colapse porque no estaría leyendo NUMEROS, sino cualquier información que se pudiera haber almacenado… Adjunto mi código que uso en el simulador PROTEUS.
COmo dato adicional, para simularlo en PROTEUS, al puerto serial 2,3 del bluetooh, lo uso para visualizar el comportamiento de las variables durante su ejecución, y el puerto natural de arduino (0,1), lo uso como metodo de INGRESO, de esta manera simulo que por un lado ingreso información y por otro lado veo el comportamiento.
Funcion de lectura de String:

String convertirHora(byte orden)
{
  int count =0;
  char caracter ="";
  reiniciar_vector(ciclo_actual01);
  delay(30); //caracter != '\n')
  while(count<6) 
    {
      if (Serial.available())  //caracteres especiales > o < 1,2,3,4,5,6 11,22,33,44,55,66'\n'
      {
      caracter = Serial.read();
      if(caracter != ',' && caracter != '\n') 
      {
        if(caracter>='0' && caracter <='9')
         {ciclo_actual01[orden][count]+=caracter;}
        }
      else{
        if(ciclo_actual01[orden][count].length()==1)
          if(ciclo_actual01[orden][count].toInt()>=0 && ciclo_actual01[orden][count].toInt() <=9){ciclo_actual01[orden][count] ='0'+ciclo_actual01[orden][count];}
          else {
            if(ciclo_actual01[orden][count].toInt()>=10 && ciclo_actual01[orden][count].toInt() <=60)ciclo_actual01[orden][count]=ciclo_actual01[orden][count];
            }       
        count++;}  
      }
    }
  for (int h=0;h<6;h++)
  {
   blue.print(F("Valor almacenado: "));
   blue.println(ciclo_actual01[0][h]);
   }
}

Función de captación de la variable para inciar proceso de lectura de String:

void loop() {
  if (Serial.available())  //Si el puerto serie (Bluetooth) está disponible
  {
    valor = Serial.read(); //Lee el dato entrante via Bluetooth
  }
  //CICLO 01 ESTA ES LA FUNCION QUE HACE QUE EL SKETCH COLAPSE
    if (valor == 'A'){ convertirHora(0);
    ciclo=0;eeAddress=0; EEPROM.update(301,1); while (!EEPROM.isReady()) {delay(1);}
    blue.println(F("Valor A ingresado"));
    } 
  //CICLO 02 - CUANDO INGRESO LOS VALORES MANUALMENTE DESDE EL SKETCH, COMO EN ESTE EJEMPLO, EL SKETCH
  // tRABAJA SIN NINGUN PROBLEMA
    if (valor == 'B'){ 
      reiniciar_vector(ciclo_actual01);
      ciclo_actual01[0][0]= "12";
      ciclo_actual01[0][1]= "30";
      ciclo_actual01[0][2]= "12";
      ciclo_actual01[0][3]= "45";
      ciclo_actual01[0][4]= "12";
      ciclo_actual01[0][5]= "01";
      ciclo=0;eeAddress=0; EEPROM.update(301,1); while (!EEPROM.isReady()) {delay(1);}} 
  //CICLO 03
  //CICLO 04
  //CICLO 05 ... ETC AQUI VAN OTROS PROCESOS QUE POR EL MOMENTO CONSIDERO INNECESARIOS PARA EXPRESAR MI PROBLEMA.
}

y Finalmente el proceso de validación y lectura de EEPROM que realizo:

if(grabar)
{ 
//aqui van funciones para validar que los datos numericos estan correctos,si todo esta bien pasa a lo siguiemte:
blue.println(F("Valores de Ciclo Correcto - Proceso de Grabacion")); 
for(int k1=0;k1 <6 ;k1++)
 {
if(ciclo_actual01[ciclo][k1] != vector_relay[ciclo][k1])
{
EEPROM.updateInt(eeAddress,ciclo_actual01[ciclo][k1].toInt()); //poner PUr Update de la nueva libreria de EEPROM
while (!EEPROM.isReady()) {delay(1);}  
}
eeAddress += sizeof(int);
}
EEPROM.update(300,1);// posicion para validar que existió una grabación START
while (!EEPROM.isReady()) {delay(1);}
if(ciclo==0) eeAddress = 0;
if(ciclo==1) eeAddress = 12;
if(ciclo==2) eeAddress = 24;
if(ciclo==3) eeAddress = 36;
if(ciclo==4) eeAddress = 48;
if(ciclo==5) eeAddress = 60;
for(int k1=0; k1<6; k1++)
{
  if(ciclo_actual01[ciclo][k1].toInt() != EEPROM.readInt(eeAddress)){error++;}
  eeAddress += sizeof(int);
  }
  if(error!=0){ blue.println(F("Grabacion Incorrecta"));
  }
  else 
  {
   error=0;
   blue.println(F("Grabacion Ok"));
   //hacer sonar un buzzer
   eeAddress =0;
   for (int h=0;h<6;h++)
   {
   blue.print(F("Valor almacenado EN GRABAR: "));
   blue.println(ciclo_actual01[0][h]);
   blue.print(F("Valor almacenado EN EEPROM GRABAR: "));
   blue.println(EEPROM.readInt(eeAddress));
   eeAddress += sizeof(int);
   }
   }
}

He decidido eliminar los adjuntos, porque he visto que se descargan pero no comentan nada al respecto.

Bueno, he investigado un poco mas y veo que la solución fue poner un fin de carrera y problema solucionado, aunque tambien veo que por algun tema que desconozco en ciertas ocasiones el Arduino no trabaja como corresponde a pesar que ingreso los mismo rangos de hora y a veces el RTC no sincroniza con la hora actualizada de la PC en donde lo descargo, son 2 temas que según las normas deberán ir en otro post. A mi criterio creo que el programa esta algo recargado y no logra procesar todo. Si alguien tiene idea .. se aceptan comentarios

HOla, tengo un proceso de grabar datos en la EEPROM usando Arduino UNO, los valores los adquiero por un String separados por “comas”, desde el puerto bluetooh (2,3).
Este String, lo convierto posteriormente en Int, para despues extraer el LOWBYTE, ya que los valores almacenados son menores a 255.
En el primer intento de grabar EEPROM lo hace con exito, pero en el segundo intento el Array donde almaceno los datos del String convertidos a Int, los cuales los convertire despues a Bytes, no se guarda bien, comienza a dar valores errados.
Que he hecho? COnsulto con la funcion FREEMEM(), a ver cuanta memoria tengo, y supero los 1000, por tal creo que estpy bien.
VIsualizo en cada parte del proceso los datos ingresados y procesados por puerto serial usando la macro F().
He dejado de usar la libreria EEPROMex por la libreria original EEPROM.h. La verdad no se porque sucede esto, y porfavor si tienen alguna idea AYUDENME…!!! si no logro que funcione, tomaré un uC mas poderozo que el de Arduino UNO, pues solo al trabajar con este tema de EEPROM o conversion de datos me da problemas.
Aqui les dejo el codigo (he dejado solo la parte principal)
Hasta le puse un WatchDog para resetear en caso de inhibición, pero considero que el codigo es bien ligero para que se esté inhibiendo.
El codigo esta diseñado para simularlo en PROTEUS, el puerto BLUETOOH lo uso para ver lo que pasa durante la ejecución y el puerto serial lo uso para introducir manualmente los valores separados por “COMA”
Como fin de carrera del String uso la letra Z mayuscula. En total se ingresan 6 valores de maximos 2 digitos cada uno separado por COMAS.

void loop() {
wdt_reset();

byte longCad2=0;
byte error=0;
byte val=0; 
String k="";

 if (Serial.available())  
 {
   valor = Serial.read(); 
 }
 //CICLO 01
   if (valor == 'A'){
     ciclo=0;
     convertirHora(ciclo);
   } 
 //CICLO 02
   if (valor == 'B'){ 
     ciclo=1;
     convertirHora(ciclo); 
     } 
 //CICLO 03
   if (valor == 'C'){ 
     ciclo=2;
     convertirHora(ciclo);
  //   EEPROM.update(303,1);delay(tiempo);}
    }
 //CICLO 04.. y asi continua hasta el ciclo 06, pero por tema de espacio y no ser latoso borrare...
  
  if (valor >= 'A' && valor <= 'F'){grabar = true; valor=""; error =0;}
 
 //Opción para ENCERAR todas las variables 
 if (valor == 'k'){ formateoMem();delay(500); blue.println(F("Formateo realizado - reinicie el Equipo"));
 valor="";
 grabar=false;

 estadorelay=true;
 //ton=false;
 ciclo=10;
 error=0;}
 //Opción para leer ciclos almacenados
 if (valor == 'S'){
   valor="";
 for(int d=1;d<=6;d++)
 { eeAddress=Posicion(d-1);
 if(EEPROM.read(300+d)==1) 
   {
   blue.print(F("Ciclo "));          blue.print(d);                                blue.println(F(":"));
   blue.print(F("Inicio= "));        blue.print(EEPROM.read(eeAddress));       blue.print(F("h"));      blue.println(EEPROM.read(eeAddress+1));
   blue.print(F("Fin= "));           blue.print(EEPROM.read(eeAddress+2));     blue.print(F("h"));      blue.println(EEPROM.read(eeAddress+3));
   blue.print(F("Ton= "));           blue.print(EEPROM.read(eeAddress+4));     blue.println(F(" Seg"));
   blue.print(F("Toff= "));          blue.print(EEPROM.read(eeAddress+5));    blue.println(F(" Min")); blue.println(F(""));
   }
   else {blue.print(F("Ciclo "));blue.print(d);blue.println(F(" No Existe"));}
 delay(100);
 }
 }
/*-----------------------3RO--------------------*/

if(grabar)
{ 
 Serial.print ( F("Free mem: ") );
 Serial.println ( freeMemory () );
 grabar=false;
 estadorelay=true;
 digitalWrite(led_1,LOW);
 digitalWrite(led_2,LOW);

 if (true){//1

   if(longCad == 12){ 

     if (true){//2

       eeAddress = Posicion(ciclo);
      
       // Para visualizar lo ingresado en String por puerto Serial y convertido toInt()
       for(int k1=0;k1 <6 ;k1++){
           blue.print(F("BT - en Int() ciclo_actual01[ "));
           blue.print(ciclo);blue.print(F(" ][ ")); blue.print(k1);blue.print(F(" ]= "));
           delay(tiempo);
           blue.println(ciclo_actual01[ciclo][k1].toInt());delay(tiempo);
       }
       
       //se extrae el LOWBYTE y se lo almacena en EEPROM
       byte temp =0;
       for(int k1=0;k1 <6 ;k1++){
           blue.print(F("Update Epprom ciclo_actual01[ "));
           blue.print(ciclo);blue.print(F(" ][ ")); blue.print(k1);blue.print(F(" ]= "));
           delay(100);
           temp = lowByte(ciclo_actual01[ciclo][k1].toInt());
           delay(100);
           blue.println(temp);
           EEPROM.update(eeAddress,temp);
           delay(100); 
           eeAddress += sizeof(byte);
           }

       for(int k1=0; k1<10; k1++){
           blue.write(205);
           }
       blue.println(F("")); 
        
       eeAddress = Posicion(ciclo);
      // Se visualiza lo almacenado en EEPROM
       for(int k1=0; k1<6; k1++){
           if(lowByte(ciclo_actual01[ciclo][k1].toInt()) != EEPROM.read(eeAddress)){error++;}
           blue.print(F("Valor almacenado en EEPROM "));
           blue.print(eeAddress);blue.print(F(" = ")); blue.println(EEPROM.read(eeAddress));
           eeAddress += sizeof(byte);
           }
       
       for(int k1=0; k1<10; k1++){
           blue.write(205);
           }
       blue.println(F("")); 

       //Se visualiza lo almacenado en EEPROM convertido en String, hago esto para validar que la información este          //correcta
       eeAddress = Posicion(ciclo);
       k="";
       for(int k1=0; k1<6; k1++){ 
           k=EEPROM.read(eeAddress); delay(10);
           if(k.length()==1) longCad2++;
           else longCad2 = longCad2 + 2; 
           blue.print(F("Valor leido en EEPROM como STring en posicion "));
           blue.print(eeAddress);blue.print(F(" = ")); blue.println(k);
           eeAddress += sizeof(byte);
           }
       
       for(int k1=0; k1<10; k1++){
           blue.write(205);
           }
       blue.println(F(""));

       k="";
       
       //visualizo los parametros de validacion de error
       blue.print(F("longEEPROM = "));
       blue.println(longEEPROM);
       blue.print(F("longCad2 = "));
       blue.println(longCad2);
       blue.print(F("Error = "));
       blue.println(error);
       if(error!=0 || longEEPROM != longCad2){ 
          error=10; 
          blue.println(F("Grabacion Incorrecta"));
          }
       else{//correcto
          error=0;
          EEPROM.update(300,1);delay(tiempo);
          EEPROM.update(301+ciclo,1);delay(tiempo);
          buzzer_relay(true);
         }//end else correcto
     }//end if 2 /*-----------------------4TO------------------------*/
 
   }// end if longCad
   
 
}//  end If 1
/*-----------------------5TO----------------------------*/
} // end if grabar
}// end loop
static int freeMemory ( void )
{
  int free_memory;
  
  if((int)__brkval == 0)
  free_memory = ((int)&free_memory) - ((int)&__bss_end);
  else
  free_memory = ((int)&free_memory) - ((int)__brkval);
  
  return free_memory;
}
String convertirHora(byte orden)
{
 byte count=0;
 char caracter ="";
 byte contar=0;
 String dato="";
 longEEPROM =0;
 longCad=0;
 
 delay(30); //caracter != '\n')
 
 while(count<=5) // Se coloca 5 porque son 5 "," las que separan los valores de las variables.
   { 
     if (Serial.available())  //caracteres especiales > o < 
     { 
       caracter = Serial.read();
       if(caracter != ',' && caracter != 'Z' && contar<2) 
       { if(caracter>='0' && caracter <='9')
         { dato+=caracter;
           contar++;
         }
       }
       else
       {   if(dato.toInt()>=0 && dato.toInt() <=9)
           { longEEPROM++;
             if(dato.length()==1)
             { dato ='0'+dato;
               longCad=longCad+dato.length(); 
             }
             else longCad=longCad+2;
           }
           else 
           { longEEPROM=longEEPROM+2;
             longCad=longCad+dato.length();
           }
        ciclo_actual01[orden][count]=dato;
        count++;
        contar=0;
        dato="";
       }  
     }
   }
}
byte Posicion(byte turno)
{
switch (turno)
{case 0: return 0;
 case 1: return 6;
 case 2: return 12;
 case 3: return 18;
 case 4: return 24;
 case 5: return 30;
 break;
}}

Para poner en contexto tu pregunta he unido los temas a pesar que al anterior le pusiste solucionado pero como vemos no lo está.
Así que mejor entender todo.
Yo comencé a ver tu programa pero al usar algo fuera de lo común como es la librería EEPROMEnhanced no recuerdo si así se llama me detuve y no pude avanzar al ritmo habitual.

Por favor, colaca todo el código no solo el loop, de lo contrario cómo esperas que probemos lo que ocurre?

Moderador:
Has hecho muy mal en eliminar los adjuntos porque tu crees que todo el mundo tiene tiempo para responderte a la brevedad y no es el caso.
Debes ser paciencte porque no sabes cuando te van a responder.
Si tienes temor a que alguien USE tu código entonces maneja tu consulta de otra forma pero de ningún modo alteres el hilo principal porque ahora por ejemplo no podemos ver que librerías usabas y queda mi comentario fuera de lugar porque EEPROMEnhanced.h no existe, ya lo he verificado.

HOla, la verdad intenté cerrar y dejar por finalizado el Blog anterior, pues crei que haciendo click en NEW POST se creaba uno nuevo, pero en fin, parece que se creo post como continuación del otro.
Tal caso adjunto el codigo con las siguientes correcciones:
WATCHDOG habilitado.
FUncion para medir memoria libre.
Validacion en BYTE de la informacion almacenada en EEPROM.
La versión que realize corre perfectamente en PROTEUS, pero al cargar en la placa al visualizar por puerto Serial me muestra “???”
Intento hacer acciones, pero parece que no responde.
Las librerias que uso es la EEPROM.h, la que usaba antes era la EEPROMex.h y ya la deje porque ocupaba mucho espacio.
QUedo atento a sus comentarios para ver que estoy realizando mal.
REsumen, le puse una función de Reset por software, para que cada vez que se ingrese un dato, despues de validar la información haga un RESET, esto ayuda a que la cantidad de memoria disponible no disminuya… NO SE SI ESO ES CORRECTO, porque parece que es como hacer trampa… ya que no dejo que el equipo trabaje normalmente… Saludos

RELOJ_V6_NANO.ino (26.4 KB)

Ya corregi el tema del "???????????????????????????????????" pero asumo que al momento que se publique este post saldrá como puros EMOJIS, el simbolo que sale en fila es el de INTERROGACIÖN, y al parecer era un error mio al seleccionar los baudios incorrectos UPS!!!

Finalmente, poco a poco he ido corrigiendo los errores, pero me quedo con el mal sabor de haber tenido la necesidad de usar la función de RESET por software, sin esa función el programa simplemente no funcionaba, se ejecutaba pero en el momento de ingresar información en la EEPROM por 2da o 3ra vez colapsaba.

Porfa si saben algo al respecto acepto IDEAS o Sugerencias....

A mi criterio no debe usarse la función RESET pues es para un tema de Emergencia similar al WatchDog... pero considero que es como Hacer trampa con la codificación para forzarlo a que funcione.

Porque no subes su archivo Proteus zipeado por supuesto.

Hola, claro, adjunto el archivo proteus, y tambien pongo una imagen, como no puedo simular la entrada por celular, lo simulo por medio del puerto serial 0,1 propio del arduino, y como terminal de visualización para tener mas claro lo que leo uso el puerto serie del bluetooh. Cabe indicar que el trabajo ya lo termine, basicamente investigue todas las incognitas que se me presentaron. Aunque aun no tengo una respuesta del tema por que reiniciar para liberar memoria, no creo que sea realmente necesario o dependerá del tipo de programa usado?

PRO_RELOJ_ARDUINO_PROTEUS.zip (62.2 KB)