Manejo de epoch con millis()

Tengo un funcion que por comunicacion serial pide una sola vez la variable epoch que son los segundos desde 1970 hasta ahora, luego con timeLib lo convierto para saber la hora, minutos, y seguundos, mi problema es que luego de hacer la peticion quiero poder que el arduino siga contando y sumando a epoch para no saturar el servidor NTP que es de donde la obtengo

void obtenerHora() {

  if (epoch == 0) {
    Serial1.print(2);
    if (Serial1.available() > 0) {
      String data = Serial1.readString();
      epoch = data.toInt();
    }
  } else {
    epoch += millis()/1000; // aca esta mi problema lo que pasa es que al hacer esto mi causa error y la hora minutos y segundos toman valores erroneos
  }

 // estas variables son globales estan definidas fuera de la funcion
  Hr   = hour(epoch) - 3;
  mins = minute(epoch);
  secs = second(epoch);

}

Su función es incorrecta, toma el valor de milis completo y lo divide por 1000. Entonces obtiene el tiempo desde el controlador reset, pero necesita el tiempo desde la respuesta del NTP.
Debe recordar el valor de milis en el momento en que obtiene el tempo del NTP y luego calcular la diferencia entre los milis actuales y el valor memorizado

void obtenerHora() {
  static uint32_t prev_millis =0;
  if (epoch == 0) {
    Serial1.print(2);
    if (Serial1.available() > 0) {
      String data = Serial1.readString();
      epoch = data.toInt();
      prev_millis = millis();
    }
  } else {
    epoch += (millis()- prev_millis)/1000; // aca esta mi problema lo que pasa es que al hacer esto mi causa error y la hora minutos y segundos toman valores erroneos
  }
1 Like

Gracias por tu aporte pero lastimosamente acabo de probarlo y no soluciona, los segunbdos aumentan de una forma exageradamente alta, y en consecuencia los minutos y la hora

¿No has probado crear un RTC virtual con RTClib que no solo sirve para manejar RTC "reales"?
Puedes cargar la hora en formato epoch y de lo demás se encarga la librería.

De todos modos recuerda que la precisión del cristal del arduino es "más o menos" así que cada tanto tendrías que volver a consultar el servidor para ajustar la hora.

Agrego porque me fui de tema...
La instrucción correcta debería ser

new_epoch = epoch + (millis()- prev_millis)/1000;

O sea, mantienes de base la hora epoch que ingresaste y le sumas los segundos transcurridos desde el ingreso pero en una nueva variable de trabajo.

1 Like

https://www.prometec.net/ntp/
Ya que no has puesto todo el código supongamos que este fuera el caso.
Aca le envian un paquete cada 1 seg y claramente el servidor puede con eso.
Podrias tener un RTC virtual como te dice @anon90500195 y ajustarlo cada X tiempo. Millis() no es la panacea pero si lo corriges cada 10 min seguramente estarás mas que bien.

1 Like

Te paso lo que yo uso. Si tienes alguna duda, avisa


#include <ESP8266WiFi.h>
#include <time.h>
#define SINC_NPT 30 // minutos entre llamadas. Uso 720 (12 horas)

const char* ssid = "";
const char* password = "";


const char* NTP_SERVER = "ch.pool.ntp.org";
const char* TZ_INFO    = "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00";  // barna: zonas (https://remotemonitoringsystems.ca/time-zone-abbreviations.php)

tm timeinfo;
time_t now;
unsigned long lastNTPtime;
unsigned long lastEntryTime;

void setup() {
  Serial.begin(115200);

  Serial.println("\n\nNTP Test\n");
  WiFi.begin(ssid, password);

  int counter = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(200);
    if (++counter > 100) ESP.restart();
    Serial.print ( "." );
  }
  Serial.println("\n\nWiFi conectada\n\n");

  configTime(0, 0, NTP_SERVER);
  // See https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv for Timezone codes for your region
  // madrid CET-1CEST,M3.5.0,M10.5.0/3
  setenv("TZ", TZ_INFO, 1);

  lastEntryTime = 0;
  getNTPtime();

 // primera vez da error de datos: rellamar 1 minuto despues
  lastNTPtime = 0;
  lastEntryTime = millis()-((SINC_NPT-1)*60000);
}


void loop() {

  getNTPtime();

  if(Serial.available()>0){
        do{
          int car=Serial.read();
          delay(10);
        }while(Serial.available()>0);
          showTime(timeinfo); 
        }
}

void getNTPtime() {
  
  if(millis() - lastEntryTime >= (60000 * SINC_NPT) || lastNTPtime==0){ // minutos
    unsigned long start=millis();  

    do {
      time(&now);
      localtime_r(&now, &timeinfo);
      delay(10);
    } while (((millis() - start) <= 1500) && (timeinfo.tm_year < (2020 - 1900))); //esperar 1500 milis hasta year correcto
 
    if (timeinfo.tm_year <= (2020 - 1900)) return;  // la llamada NTP no tuvo éxito

    lastNTPtime = now; // actualizar la ultima hora
    }
 else{
    now = lastNTPtime + (int)(millis() - lastEntryTime) / 1000; // hora entre llamadas
    }
}
      

void showTime(tm localTime){
    char time_output[30];
    getNTPtime();
    Serial.print("Ahora ");  Serial.println(now);

    strftime(time_output, 30, "%A  %d-%m-%y %T", localtime(&now));
    Serial.println(time_output);
    Serial.println();
    }

Saludos

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.