Modulo SD Card o EEprom??

Saludo cordial a todos los integrantes del foro.

Estoy intentando implementar un horómetro que cuando se des-energice el arduino guarde el dato de tiempo transcurrido y cuando se inicie lea ese dato y continúe con el conteo, por el momento lo intento con un modulo de SD CARD y la funcion millis, el dato se graba en la memoria, pero cuando desconecto y vuelvo a conectar, el dato al parecer se borra porque el conteo inicia desde cero. He estado revisando información para poder hacer lo mismo utilizando la EEPROM de arduino pero no quiero salirme de la idea que estoy desarrollando sin estar seguro que pueda funcionar de otra manera.

Agradezco cualquier opinión, corrección, sugerencia, o recomendación de documentación para poder llevar a buen termino mi idea.

Exitos para todos en sus proyectos.

Les comparto el codigo para su observación.

#include <Arduino.h>
#include <U8g2lib.h>
#include <SD.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

File myFile;
File archivo;

int horas;      
int minutos;    
int segundos;   
int inicio=0;   
unsigned long valor;
unsigned long valMillis;

char cadenaTiempo[16]; // Cadena para almacenar texto formateado


void setup(void) {
  Serial.begin(9600);
  delay(100);
  u8g2.begin();
    
}

void loop(void) {

  if (!SD.begin(10)) { //make sure sd card was found
    delay (2000);
    u8g2.firstPage();
  do{
    u8g2.setFont(u8g2_font_ncenB10_tr);
    
    u8g2.drawStr(9,44,"ERROR SD NO");
    u8g2.drawStr(18,59,"DETECTADA");    
    } 
    while ( u8g2.nextPage() );
    delay(1000);
  }

else{

  if(inicio==0){
      myFile = SD.open("prueba.txt", FILE_READ);
      Serial.println(myFile);
      valor = myFile.read();
      myFile.close();
      Serial.println(inicio);   
      }
      inicio=1;
      millis();
      valMillis = ((millis() / 1000)+(valor));   // Se obtienen los segundos
      segundos = valMillis % 60;      // se divide entre segundos por minuto y te quedas con el resto
      minutos = valMillis / 60;       // Se convierte a minutos
      minutos = minutos % 60;         // se divide entre minutos por hora y te quedas con el resto
      horas = (valMillis / 60) / 60;  // Se convierte en horas
      Serial.println(valor);
      Serial.println(myFile);
      
          
        
      sprintf(cadenaTiempo, "%04d:%02d:%02d", horas, minutos, segundos); // Componer cadena con la información del tiempo formateada
   
    
  SD.remove("prueba.txt");  
  archivo = SD.open("prueba.txt", FILE_WRITE);
  if (archivo) {    
    archivo.println(valMillis);
    archivo.print("Sec");
    archivo.close();
  } 
    
  u8g2.firstPage();
  do{
    u8g2.setFont(u8g2_font_ncenB10_tr);
    u8g2.drawStr(40,40,(cadenaTiempo));
    u8g2.drawStr(0,40,"T > ");
    
    
  } while ( u8g2.nextPage() );
  delay(1000);
    
  }
  
}

Hola

Comprueba que la lectura de:

valor = myFile.read();

Esté dando el valor correcto y no "0" porque lea texto en vez del valor guardado.

En este caso
valor=0 y milis() es aproximadadmente 0 porque ese acaba de iniciar, por lo que valMilis =0. Entonces se inicia a cero el contador.

Y otra cosilla, no entiendo mucho de SD pero si guarda el valor cada loop la SD puede "morir" prematuramente y desde luego eso no se te ocurra hacerlo en la EEPROM (duraría unas pocas horas).

Espero que sea el error.

Solo por curiosidad, el millis(); "huerfano" que hay después del inicio=1; ¿es por alguna razón?

Saludos

Lo mejor sería que uses EEPROM.put() y EEPROM.get() es mas rápido que la SD.
Dada la condición de corte de energía que no dices como la determinas, entonces usando

EEPROM.put(address, valMillis);

y lo lees en el setup con

EEPROM.get(address, valMillis);

Entonces dada la condición guardas con put y al energizar Arduino lees con get.

Pero la condición debe ser sólida y ejecturarse solo una vez sino vas a corromper la EEPROM en esa zona. Asi que asegúrate que eso ocurre solo cuando corresponda.

Hi,
Pregunta: Que usas para determinar que el micro perdio el voltaje y como sabes que debes de escribir las lectura en la SD. Si desconectas el power como vaz a escribir la infomacion en la SD y como el micro va escribir la informacon sino tiene voltaje. Cual es la situacion de que desconectes el voltaje.

Hola

Por lo que intuyo en el code, graba la hora cada vez que la lee, por lo tanto no tiene que detectar la caida del voltaje.

Esto lógicamente tiene 2 problemas, uno que la corriente se quite justo cuando está guardando, por lo que los datos se corromperan y luego no se podrán leer. Y el otro es que con los miles de escrituras si lo hace en EEPROM le durará unas horas antes de que "queme" la EEPROM, y en a la SD acortará su vida útil.

Para lo que necesita tiene que hacer como las placas madre de la impresoras 3D, una lectura de pin para detectar el voltaje de la alimentación y en el momento que se pierda actue una batería de respaldo que aguante los suficiente para hacer un guardado seguro.

Un saludo

Hi,
Para el caso tuyo entonces necesitas usar interrupt pues tiene que salvar la informacion el la memoria.No se cual es tu preocupacion de que la memoria se dane ya que tu sabras cuando remplazarla. Ahora si usa el eeprom del micro entoncces tienes que remplazar el micro yo me iria por la SD. Veo que no usas interrupt esto en tu aplicacion es requerido por el tiempo que tienes para guadar la informacion en la memoria. Si quires tratar adjunto un esquematico que puedes usa para que te de tiempo a escribir la informacion en la memoria. El circuito es simple es de anadirle un diodo de la fuente de entrada y alimentas el micro con el catodo del diodo. Le anade un condesador bastante grande para que retenga el voltaje. Puedes empaezar con uno de 1000ufd y prueba para entonces subirle el valor. El proposito del diodo es que cuando se cae el voltaje el diodo evita que el condesador se descargue con la caarga de entrada .Tienes que conectar el voltaje de entrada antes del diodo a un interrupt. Cuando ocurre la perdida del voltaje esto genera el interrupt y el voltaje almacenado en el condensador permite darle el tiempo para escribir la data en la memoria. Esto es solmentente una sugerencia. El tiempo de escribir va a depender de la capacidad de condesador.

@pepepotero

Y el otro es que con los miles de escrituras si lo hace en EEPROM le durará unas horas antes de que "queme" la EEPROM, y en a la SD acortará su vida útil.

Esto es algo que de ningún modo se debe hacer.
Hay que tener un circuito detector de falta de energía y solo en ese único caso y que sea 1 solo caso, se graba.
Cuando se vuelve a energizar se leen los datos de la EEPROM.
No hay posiblidad de dañar la EEPROM si haces las cosas bien.

Por eso yo escribí antes:

Lo mejor sería que uses EEPROM.put() y EEPROM.get() es mas rápido que la SD.
Dada la condición de corte de energía que no dices como la determinas, entonces usando

tauro0221:
Hi,
Pregunta: Que usas para determinar que el micro perdio el voltaje y como sabes que debes de escribir las lectura en la SD. Si desconectas el power como vaz a escribir la infomacion en la SD y como el micro va escribir la informacon sino tiene voltaje. Cual es la situacion de que desconectes el voltaje.

La idea es que el micro guarde el conteo de horas de operación de un dispositivo de corriente alterna, yo implemente una fuente de 220AC a 5DC para alimentar el arduino, en cuanto apaguen el dispositivo AC tambien se apaga el arduino. El micro esta guardando constamente el ultimo dato de ValMillis, en las pruebas hechas yo confirmo que cuando se apaga el arduino y procedo a leer la SD en el PC el dato si queda, pero cuando se energiza nuevamente el inicia desde cero.

Este es tu setup

void setup(void) {
  Serial.begin(9600);
  delay(100);
  u8g2.begin();
    
}

Donde le dices a tu setup que recupere el valor de Valmillis? En ningún sitio.
Ahi esta tu fallo.