DataLogger ESP32, SD y RTC DS3231

Hola compañeros, estoy desarrollando un proyecto en el cual llevo tres semanas atascado sin poder terminarlo, he visto proyectos similares en este foro y en Youtube pero sus soluciones no sirven para mi proyecto. No sé si es cuestión de las librerías que estoy utilizando o si es que no lo estoy haciendo correctamente.

Mi proyecto consta de un ESP32, un RTC DS3231 y un módulo para tarjetas SD. Lo que necesito hacer es crear un archivo de texto en la micro SD y que en ese archivo se almacene la lectura del sensor junto con la hora y la fecha en la que se hizo la lectura.

El problema que tengo es que no consigo escribir en el archivo de texto la fecha y la hora en la que se hizo la lectura. Si alguien me puede ayudar le estaría realmente agradecido. Todavía estoy aprendiendo y ya no sé por dónde tirar, por lo que toda ayuda sería bienvenida... Muchas gracias de antemano.

#include "Arduino.h"
#include "uRTCLib.h"
#include "FS.h"
#include "SD.h"
#include <SPI.h>

#define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor de microsegundos a segundos */
#define TIME_TO_SLEEP 30

#define SD_CS 5
String datalog;
 
int Vresistor = 36; // SP pin which is the GPIO36 pin this is adc0
int Vrdata;

uRTCLib rtc;
File file;

#define SOFTWARE_VERSION "1.0"

#define DATE_FORMAT_LONG_MASK 0x01
#define DATE_FORMAT_AMERICAN 0x02
#define DATE_FORMAT_AMERICAN_LONG 0x03
#define DATE_FORMAT_EUROPEAN 0x04
#define DATE_FORMAT_EUROPEAN_LONG 0x05

void printRTC(uint8_t aDateFormatSpecifier = 0);
bool printRTCEveryPeriod(uint16_t aPeriodSeconds, uint8_t aDateFormatSpecifier = 0);

void printRTCDate(uint8_t aDateFormatSpecifier = 0);
void printRTCDateAmericanFormat(bool aPrintLongFormat);
void printRTCDateEuropeanFormat(bool aPrintLongFormat);
void printRTCDateISOFormat();

void printRTCTime(bool aPrintLongFormat = true, bool aDoRefresh = false);

void printRTCTemperature();
bool requestDateBySerialAndSet(void);

#if !defined(__AVR__) && ! defined(PROGMEM)
#define PROGMEM
#endif

//#define SPANISH_NAMES_FOR_DATE

#if defined(SPANISH_NAMES_FOR_DATE)
const char Monday[] PROGMEM= "Lunes";
const char Tuesday[] PROGMEM= "Martes";
const char Wednesday[] PROGMEM= "Miércoles";
const char Thursday[] PROGMEM= "Jueves";
const char Friday[] PROGMEM= "Viernes";
const char Saturday[] PROGMEM= "Sábado";
const char Sunday[] PROGMEM= "Domingo";

const char January[] PROGMEM= "Enero";
const char February[] PROGMEM= "Febrero";
const char March[] PROGMEM= "Marzo";
const char April[] PROGMEM= "Abril";
const char May[] PROGMEM= "Mayo";
const char June[] PROGMEM= "Junio";
const char July[] PROGMEM= "Julio";
const char August[] PROGMEM= "Agosto";
const char September[] PROGMEM= "Septiembre";
const char October[] PROGMEM= "Octubre";
const char November[] PROGMEM= "Noviembre";
const char December[] PROGMEM= "Diciembre";
#else
const char Monday[] PROGMEM= "Lunes";
const char Tuesday[] PROGMEM= "Martes";
const char Wednesday[] PROGMEM= "Miércoles";
const char Thursday[] PROGMEM= "Jueves";
const char Friday[] PROGMEM= "Viernes";
const char Saturday[] PROGMEM= "Sábado";
const char Sunday[] PROGMEM= "Domingo";

const char January[] PROGMEM= "Enero";
const char February[] PROGMEM= "Febrero";
const char March[] PROGMEM= "Marzo";
const char April[] PROGMEM= "Abril";
const char May[] PROGMEM= "Mayo";
const char June[] PROGMEM= "Junio";
const char July[] PROGMEM= "Julio";
const char August[] PROGMEM= "Agosto";
const char September[] PROGMEM= "Septiembre";
const char October[] PROGMEM= "Octubre";
const char November[] PROGMEM= "Noviembre";
const char December[] PROGMEM= "Diciembre";
#endif

const char* const sDayStrings[] PROGMEM = { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday };
#define DOW_MAX_STRING_SIZE 11 

const char* const sMonthStrings[] PROGMEM = { January, February, March, April, May, June, July, August, September, October, November, December };

#define MONTH_MAX_STRING_SIZE 10 


// FUNCIONES SISTEMA DE ARCHIVOS Y ALMACENAMIENTO DE DATOS EN LA SD

// Almacenar lecturas del sensor en la SD
void logSDCard() {
  // Almacenar Fecha y hora en la SD
  file.print(rtc.day());
  file.print("/");
  file.print(rtc.month());
  file.print("/");
  file.print(rtc.year());
  file.print("  ");
  file.print(rtc.hour());
  file.print(":");
  file.print(rtc.minute());
  file.print(":");
  file.print(rtc.second());
  file.print(" ");
  datalog =  "Sensor 1: " + String(Vrdata) + "\n";
  Serial.println(datalog);
  appendFile(SD, "/DataLogger.txt", datalog.c_str());
}
// Crear archivos en la SD
void writeFile(fs::FS &fs, const char * path, const char * message) {
  File file = fs.open(path, FILE_WRITE);
  if(!file) {
    return;
  }
  if(file.print(message)) {
    Serial.println("Archivo creado con éxito");
  } else {
    Serial.println("Error: No se pudo crear el archivo");
  }
  file.close();
}
// Append data to the SD card (DON'T MODIFY THIS FUNCTION)
void appendFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Guardando lectura del sensor en el archivo: %s\n", path);
  File file = fs.open(path, FILE_APPEND);
  if(!file) {
    Serial.println("ERROR: No se pudo guardar la lectura del sensor");
    return;
  }
  if(file.print(message)) {
    Serial.println("La lectura del sensor se guardó con éxito");
  } else {
    Serial.println("ERROR: No se pudo guardar la lectura del sensor");
  }
  file.close();
}
void ReadVresistor()
{
  Vrdata = analogRead(Vresistor);
  Serial.println(Vrdata);
}


// FUNCIONES RTC HORA Y FECHA FORMATEADAS

bool requestDateBySerialAndSet(void) {

  uint8_t tSecond, tMinute, tHour, tDayOfMonth, tMonth, tYear;
  char tInputBuffer[17];
  Serial.println();
  Serial.println(F("Introducir la hora en el formato: \"HH MM SS DD MM YY\""));
  Serial.setTimeout(30000);
  // read exactly 17 characters
  size_t tReadLength = Serial.readBytes(tInputBuffer, 17);
  if (tReadLength == 17 && tInputBuffer[14] == ' ') {
    #ifdef AVR
      sscanf_P(tInputBuffer, PSTR("%2hhu %2hhu %2hhu %2hhu %2hhu %2hhu"), &tHour, &tMinute, &tSecond, &tDayOfMonth, &tMonth, &tYear);
    #else
      sscanf(tInputBuffer, "%2hhu %2hhu %2hhu %2hhu %2hhu %2hhu", &tHour, &tMinute, &tSecond, &tDayOfMonth, &tMonth, &tYear);
    #endif
    // read newline etc.
    while (Serial.available()) {
      Serial.read();
    }
    Serial.setTimeout(1000);
    Serial.println();
    Serial.println(F("Introducir el día de la semana como un número entre 1 y 7 (Domingo-Sábado) - Timeout is 10 seconds"));
    Serial.readBytes(tInputBuffer, 7);
    if (tInputBuffer[0] > '0' && tInputBuffer[0] < '8') {
      rtc.set(tSecond, tMinute, tHour, tInputBuffer[0] - '0', tDayOfMonth, tMonth, tYear);
      Serial.print(F("Hora establecida a: "));
      printRTC();
      return true;
    }
  }
  Serial.println(F("El RTC no se ha modificado."));
  return false;
}

/*
 * @return true if update/refresh happened
 */
bool printRTCEveryPeriod(uint16_t aPeriodSeconds, uint8_t aDateFormatSpecifier) {
  static long sLastMillisOfRTCRead;
  if (millis() - sLastMillisOfRTCRead >= (1000 * aPeriodSeconds)) {
    sLastMillisOfRTCRead = millis();
    rtc.refresh();
    printRTC(aDateFormatSpecifier);
    return true;
  }
  return false;
}

void printRTC(uint8_t aDateFormatSpecifier) {
  rtc.refresh();
  printRTCDate(aDateFormatSpecifier);
  Serial.print(' ');
  printRTCTime((aDateFormatSpecifier & DATE_FORMAT_LONG_MASK), false);
  Serial.println();
}

void printRTCDateAmericanFormat(bool aPrintLongFormat) {
#if defined(__AVR__)
  char tDateString[(2 * DOW_MAX_STRING_SIZE) + 1 + (2 * MONTH_MAX_STRING_SIZE) + 1 + 12];
#else
  char tDateString[DOW_MAX_STRING_SIZE + MONTH_MAX_STRING_SIZE + 12];
#endif

  if (aPrintLongFormat) {
#if defined(__AVR__)
    // fist copy day of week
    strcpy_P(&tDateString[sizeof(tDateString) - (DOW_MAX_STRING_SIZE + MONTH_MAX_STRING_SIZE) - 3],
        (PGM_P) pgm_read_word(&sDayStrings[rtc.dayOfWeek() - 1]));
    strcpy_P(&tDateString[sizeof(tDateString) - (MONTH_MAX_STRING_SIZE) - 2],
        (PGM_P) pgm_read_word(&sMonthStrings[rtc.month() - 1]));
    sprintf_P(tDateString, PSTR("%s, %s %2hhu, 20%2hhu"),
        &tDateString[sizeof(tDateString) - (DOW_MAX_STRING_SIZE + MONTH_MAX_STRING_SIZE) - 3],
        &tDateString[sizeof(tDateString) - (MONTH_MAX_STRING_SIZE) - 2], rtc.day(), rtc.year());
#else
    sprintf(tDateString, "%s, %s %2u, 20%2u", sDayStrings[rtc.dayOfWeek() - 1],
        sMonthStrings[rtc.month() - 1], rtc.day(), rtc.year());
#endif
  } else {
    sprintf_P(tDateString, PSTR("%02u/%02u/20%2u"), rtc.month(), rtc.day(), rtc.year());
  }
  Serial.print(tDateString);
}

void printRTCDateEuropeanFormat(bool aPrintLongFormat) {
#if defined(__AVR__)
  char tDateString[(2 * DOW_MAX_STRING_SIZE) + 1 + (2 * MONTH_MAX_STRING_SIZE) + 1 + 12];
#else
  char tDateString[DOW_MAX_STRING_SIZE + MONTH_MAX_STRING_SIZE + 12];
#endif

  if (aPrintLongFormat) {
#if defined(__AVR__)
    // fist copy day of week
    strcpy_P(&tDateString[sizeof(tDateString) - (DOW_MAX_STRING_SIZE + MONTH_MAX_STRING_SIZE) - 3],
        (PGM_P) pgm_read_word(&sDayStrings[rtc.dayOfWeek() - 1]));
    strcpy_P(&tDateString[sizeof(tDateString) - (MONTH_MAX_STRING_SIZE) - 2],
        (PGM_P) pgm_read_word(&sMonthStrings[rtc.month() - 1]));
    sprintf_P(tDateString, PSTR("%s, %2hhu. %s 20%2hhu"),
        &tDateString[sizeof(tDateString) - (DOW_MAX_STRING_SIZE + MONTH_MAX_STRING_SIZE) - 3], rtc.day(),
        &tDateString[sizeof(tDateString) - (MONTH_MAX_STRING_SIZE) - 2], rtc.year());
#else
    sprintf(tDateString, "%s, %2u/%s/20%2u", sDayStrings[rtc.dayOfWeek() - 1], rtc.day(),
        sMonthStrings[rtc.month() - 1], rtc.year());
#endif
  } else {
    sprintf_P(tDateString, PSTR("%02u/%02u/20%2u"), rtc.day(), rtc.month(), rtc.year());
  }
  Serial.print(tDateString);
  
}

void printRTCDateISOFormat() {
  char tDateString[11];
#if defined(__AVR__)
  sprintf_P(tDateString, PSTR("%02hhu/%02hhu/20%2hhu"), rtc.day(), rtc.month(), rtc.year());
#else
  sprintf(tDateString, "%02u/%02u/20%2u", rtc.day(), rtc.month(), rtc.year());
#endif
  Serial.print(tDateString);
}

void printRTCDate(uint8_t aDateFormatSpecifier) {

  if (aDateFormatSpecifier & DATE_FORMAT_AMERICAN) {
    printRTCDateAmericanFormat((aDateFormatSpecifier & DATE_FORMAT_LONG_MASK));
  } else if (aDateFormatSpecifier & DATE_FORMAT_EUROPEAN) {
    printRTCDateEuropeanFormat((aDateFormatSpecifier & DATE_FORMAT_LONG_MASK));
  } else {
// Formato ISO
    printRTCDateISOFormat();
  }
}

void printRTCTemperature() {
  Serial.print(rtc.temp() / 100);
  Serial.print('.');
  Serial.print(rtc.temp() - ((rtc.temp() / 100) * 100));
}

void printRTCTime(bool aPrintLongFormat, bool aDoRefresh) {
  if (aDoRefresh) {
    rtc.refresh();
  }
  char tTimeString[9]; 
#if defined(__AVR__)
  if (aPrintLongFormat) {
    sprintf_P(tTimeString, PSTR("%02hhu:%02hhu:%02hhu"), rtc.hour(), rtc.minute(), rtc.second());
  } else {
    sprintf_P(tTimeString, PSTR("%02u:%02u"), rtc.hour(), rtc.minute());
  }
#else
  if (aPrintLongFormat) {
    sprintf(tTimeString, "%02u:%02u:%02u", rtc.hour(), rtc.minute(), rtc.second());
  } else {
    sprintf(tTimeString, "%02u:%02u", rtc.hour(), rtc.minute());
  }
#endif
  Serial.print(tTimeString);
}

void setup() {
  Serial.begin(115200);
    // Inicializar SD card
  SD.begin(SD_CS);  
  
  while (!Serial);
  Serial.println(F("START " __FILE__ "\r\nVersion " SOFTWARE_VERSION " from " __DATE__));

  #ifdef ARDUINO_ARCH_ESP8266
    URTCLIB_WIRE.begin(21, 22); // D3 and D4 on ESP8266
  #else
    URTCLIB_WIRE.begin();
  #endif

  rtc.set_rtc_address(0x68);
  rtc.set_model(URTCLIB_MODEL_DS3231);

  // Establecer fecha y hora en el RTC -> RTCLib::set(byte segundos, byte minutos, byte horas, byte díaDeLaSemana, byte díaDelMes, byte mes, byte año)
  // Compilar 1 vez para establecer fecha en el RTC, comentar la línea del "rtc.set" y recompilar
  
   //rtc.set(0, 22, 12, 3, 11, 8, 21);     // 11/08/2021  12:22:00

  if (rtc.lostPower() || rtc.year() < 19) {
    if (requestDateBySerialAndSet()) {
      rtc.lostPowerClear();
    }
  }

   // Montar SD y crear sistema de archivos
   
   if(!SD.begin(SD_CS)) {
    Serial.println("No se pudo montar la SD");
    return;
  }
  uint8_t cardType = SD.cardType();
  if(cardType == CARD_NONE) {
    Serial.println("No se encuentra ninguna SD");
    return;
  }
  Serial.println("Inicializando la SD...");
  if (!SD.begin(SD_CS)) {
    Serial.println("ERROR - Inicialización de la SD fallida!");
    return;    // init failed
  }
  File file = SD.open("/DataLogger.txt");
  if(!file) {
    Serial.println("El archivo no existe...");
    Serial.println("Creando archivo...");
    writeFile(SD, "/DataLogger.txt", "Neodomo DataLogger SD \r\n");
  }
  else {
    Serial.println("El archivo ya existe");
  }
  file.close();

  printRTC(DATE_FORMAT_EUROPEAN_LONG);
  delay(300);
  
  ReadVresistor();
  logSDCard();
  
   esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
   esp_deep_sleep_start();  // sleep
}

void loop() {

}

Hola, recién me estreno por el foro pero por el código creo entender que lo has podido coger de algún ejemplo de internet y le has hecho algún leve cambio.
Mi consejo es que sigas paso a paso este tutorial aunque esté en inglés tienes imágenes y código:

Verás que limpio es el código.
tutorial ESP32 + SD

Todas las constantes que usas para cambiar los nombres al español no lo entiendo, el DS3231 tiene su librería y es muy simple cambiar los valores numéricos a texto en español usando los índices de un array.
DS3231

1 Like

Hola @cuantron lo primero muchas gracias por la respuesta. Sí, el código que tengo es sacado de internet, he probado unos cuantos códigos que hay publicados y siempre me dan problemas o con las librerías de la SD o con las del RTC, este es el que mejor me funciona...
Con respecto al tutorial que compartiste está muy bien pero por desgracia no me sirve, se me olvidó mencionar que el datalogger no va a disponer de una conexión a internet para obtener la hora desde un servidor NTP, por eso me está dando tantos problemas poder escribir un timestamp en un archivo de texto.

Por partes. Olvida los ejemplos con todo completo. ¿Has hecho un testeo de la SD desde el ESP32?
Fíjate en el epígrafe " Testing MicroSD Card Functions" que hay en el enlace que puse.
Una vez compruebes que crea, lea y borra archivos en tu SD podrás continuar.
Hay que ir descartando problemas.

Como te dice @cuantrom, separa las cosas y deja de buscar algo que te resuelva todo.
Lo que ocurre es que buscas la solución fácil y generalmente no existe.
Si aprendes a grabar en una SD y como se hace y luego, leer el RTC e ir pasando los datos verás que es muy simple o bueno te llevará un poco pero haz sketchs pequeños que te sirvan, y den respuestas.
El código que encontraste ya te da una muy buena aproximación a lo que necesitas.
Pero hace todo en el setup y no en el loop de modo que es un ejemplo para entender como funciona el ESP loggeando.
Tiene un sensor que tal vez sea un NTC o un simple divisor de tensión en el GPIO36
Comparto que usar una librería con el RTC es mas fácil de entender que esto pero bueno son basicamente lo mismo.
El procedimiento logSDCard() almacena fecha y hora
A mi me gusta usar sprintf
con sprintf lo usarías asi.
debes crear un buffer de datos, algo con tamaño para almacenar todo.

// como global.
char buffer[50]; // puse 50 bytes pero no tengo idea. Cuenta cuantos bytes se usan mas 1 para dar el fin al buffer.
// esto reemplaza todos tus file.print()
sprintf(buffer, "%02d%02d%02d %02d:%02d:%02d Sensor 1 %f\n", rtc.year(), rtc.month(), rtc.hour(), rtc.minute(), rtc.second(), Vrdata);
file.print(buffer);

Y listo.
Lo que tienes esta bien pero el ultimo paso solo muestra datalog en el puerto Serie, no lo almacena enla FS. Pense que usabas una SD pero este ejemplo usa la FS o sea el FileSystem del ESP. No son lo mismo pero la aproximación sirve.

1 Like

He revisado todo con calma y he hecho paso a paso el tutorial que compartiste del DS3231 y ya conseguí que me escriba en la SD la fecha, la hora y la lectura del sensor utilizando las librerías.

Con la solución que me dio @Surbyte de crear un buffer conseguí simplificarlo más. En resumen ahora tengo un sketch que tiene 300 líneas menos de código y es muchísimo más fácil de leer y mantener.

Ahora el problema que tengo es que si el ESP32 pierde la alimentación, el tiempo no pasa para el RTC, por si no me explico bien, supongamos que tengo el ESP32 enchufado al USB del PC y apago el PC el día 22/08/21 a las 22:00, cuando lo encienda al día siguiente a las 09:00 por ejemplo, la primera lectura que me haga pondrá la fecha y hora en la que se apagó, es decir que para el RTC no habrá pasado el tiempo.

¿Cuál sería la forma correcta para hacer eso? porque si cada vez que se me queda sin batería tengo que resubir el sketch me es inviable, ya que el ESP32 va a estar alimentado por una batería externa.

Lo único que se me ocurre es pedirle al usuario que introduzca él mismo los datos desde un formulario, pero no sé si hay alguna otra forma de hacerlo sin que dicho usuario intervenga.

#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>


#define uS_TO_S_FACTOR 1000000ULL    /* Factor de conversión de microsegundos a segundos */
#define TIME_TO_SLEEP 30

const int SD_CS = 5;
const int sensor = 36;   // El pin SP es el GPIO36 equivale a adc0. 

int lecturaSensor;

char buffer[50];

String daysOfTheWeek[7] = { "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" };
String monthsNames[12] = { "Enero", "Febrero", "Marzo", "Abril", "Mayo",  "Junio", "Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre" };

RTC_DS3231 rtc;
File logFile;


void setup() {
   Serial.begin(9600);
   
   if (!SD.begin(SD_CS)) {
      Serial.println("Error al iniciar");
      return;
   }
   
   delay(300);
    
   if (!rtc.begin()) {
      Serial.println("No se puede conectar al RTC");
      while (1);
   }
 
 
   // Si se ha perdido la corriente, fijar fecha y hora
   if (rtc.lostPower()) {
   
      // Fijar a fecha y hora de compilacion
      //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
      
      // Fijar a fecha y hora específica. 22 de Agosto de 2021 a las 04:15:00
      //rtc.adjust(DateTime(2021, 8, 22, 4, 43, 0));
   }

   // Abrir archivo y guardar la lectura del sensor
   logFile = SD.open("/datalog.txt", FILE_APPEND);

   if (logFile) {
      int lecturaSensor = analogRead(sensor);
      DateTime now = rtc.now();
      logSDCard(now, lecturaSensor);
      logFile.close();
   }
   
   else {
      Serial.println(F("Error al abrir el archivo"));
   }
   
   delay(1000);

   esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
   esp_deep_sleep_start();
}



void loop() {
   
}

void readSensor()
{
  lecturaSensor = analogRead(sensor);
}


// Función para guardar los datos en la SD
void logSDCard(DateTime rtc, int lecturaSensor)
{
   sprintf(buffer, "Fecha: %02d/%02d/%02d  Hora: %02d:%02d:%02d   Sensor: %f\n", rtc.day(), rtc.month(), rtc.year(), rtc.hour(), rtc.minute(), rtc.second(), lecturaSensor);
   logFile.print(buffer);
   Serial.println();
   Serial.println(buffer);
}


Si el RTC tiene colocada su batería no debería "perder" la hora.

Prueba las cosas. El supuesto que dices no debería ocurrir, cómo comenta @gatul detrás del RTC tienes una batería "de botón" de 3V y hasta donde he visto siempre la trae por defecto. Mientras esa batería no se agote tu RTC mantendrá la hora.
No es tan extraño de entender, ocurre lo mismo con las pilas de las placas base en los PC. De hecho suele ser la misma: "Pila Botón 3V CR2032 de Lithium"

1 Like
  1. Quita el comentario a la línea:
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

Cuando subes tu sketch, a partir de que fecha el RTC está contando y se mantendrá gracias a la batería que incorpora.
Las constantes date y time son la fecha y hora que tienes en el sistema de tu PC o el dispositivo que uses.
Una vez tu proyecto esté completo esa línea aunque resetees el Arduino no cambiará el valor (Seguirá contando el tiempo desde esta fecha) a menos que se detecte que el RTC ya no tiene batería.

  1. Pon una pequeña pausa en el setup, un delay corto antes de la lectura de la SD igual que tienes otro antes del RTC (Esto suele ayudar con algunos errores en las lecturas al iniciar)

[Edito]
Por cierto para la SD recomiendo la librería:
#include "SdFat.h"
#include "sdios.h"

1 Like

Perdón que haga una corrección.

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

ajusta el RTC a la fecha y hora en que se compiló el sketch, que son las que guardan DATE y TIME

Más allá de eso, al tener esa línea (y la siguiente que pone fecha y hora fijas) comentada y quedar sin alimentación y sin pila, el RTC tendría que reiniciarse (creo que 00:00:00 01/01/2000, ahora no lo recuerdo) pero nunca retendrá una hora "vieja".

Dejo una secuencia de imágenes para que se vea que incluso quitando el RTC, al volver a montarlo, todo sigue como debe. Obviamente tiene la pila de backup instalada y en perfecto estado. :wink:

Saludos

1 Like

En cuanto tenga hecha esta versión le dedicaré un tiempo a ver esas librerías y cómo funcionan.

@cuantron, @gatul perdonad, ya sé lo que me pasaba. La función para establecer la fecha la tengo dentro de un condicional if que sucede cuando se pierde la alimentación, lo que pasaba es que yo compilaba pero no desconectaba la alimentación por eso era al día siguiente en el momento de volver a encender el ordenador cuando la condición del if entraba.

En resumen hay que compilar, desconectar la alimentación y conectar la alimentación. Haciéndolo de esta forma el problema está resuelto.

El problema que me falta por solucionar es un error en la lectura del sensor, pero me gustaría dedicarle uno o dos días a ver si puedo detectar y solucionar el problema por mí mismo sin ayuda, por eso no voy a dar el tema como solucionado.

En uno o dos días me pasaré por aquí. Hasta entonces muchísimas gracias a los tres. gatul, Surbyte y cuantron, gracias por vuestros consejos, toda la ayuda y sobre todo por vuestro tiempo, sois unos cracks...

Bueno aunque te diste cuenta, es justamente rtc.lostPower() la que hacer lo que no quieres que haga.
Ese lostPower se suele usar para (que no te genere esto un dolor de cabeza) ajustar el reloj del sistema. Cómo??? Bueno el RTC lleva la hora pero al despertar el arduino le transfiere la hora al reloj del sistema, una rutina que lleva la hora basado en millis(), de ese modo no pregunta a cada momento al RTC. Cual es la ventaja? justamente tiempo. Y la desventaja? Que debes chequear dicho reloj del sistema cada X minutos para que no se corra demasiado.
Son estrategias.