gmag11 / ESPNtpClient

High accuracy NTP library for ESP32 and ESP8266
MIT License
118 stars 25 forks source link

Use with Time Library #26

Closed RobInSaratoga closed 2 years ago

RobInSaratoga commented 2 years ago

Hi, I am looking for help to implement this library along with the Arduino Time library.

I have clocks running the Time Library example for ESP8266, which have the NTP sync routines built-in - but I am seeking replace that with the higher accuracy offered by this library.

I have successfully run the examples from this library and have read the code, most of which I think I understand well enough.

My question is; using the Time Library structure, how do I call this library? (Sorry, I am not a coder so this may not be the proper terminology).

The Time library takes care of handling time on the Arduino; giving the user the ability to establish, set, adjust, and query the Arduino's time keeping. But I want to SET the clock using this (more accurate) library.

In essence, the Time library offers a variety of ways to sync the time of the Arduino to various sources (NTP, GPS, RTC, etc.). How do I tell it to use this library instead? I am unclear on how to do this.

Considering the basic example in this library; how would one implement the use of the Time Library?

Any help is greatly appreciated. Thank you.

Rob

RobInSaratoga commented 2 years ago

Here is the code I am working with. The "NTP.getTimeDateStringsUs" output is working and the time is correct. It's the following function that is not working and I believe it is because the Time library does not see the time as being "SET"; therefore the routine does not run.

`#include

include

include

include

define YOUR_WIFI_SSID "ssid"

define YOUR_WIFI_PASSWD "password"

define SHOW_TIME_PERIOD 1000

void setup() { Serial.begin (115200); Serial.println (); WiFi.begin (YOUR_WIFI_SSID, YOUR_WIFI_PASSWD); NTP.setTimeZone (TZ_America_Los_Angeles); NTP.begin (); }

time_t prevDisplay = 0;

void loop() { static int last = 0;

if ((millis () - last) >= SHOW_TIME_PERIOD) { last = millis (); Serial.println (NTP.getTimeDateStringUs ()); }

if (timeStatus() != timeNotSet) { if (now() != prevDisplay) { //update the display only if time has changed prevDisplay = now(); digitalClockDisplay(); } } }

void digitalClockDisplay() { // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); }

void printDigits(int digits) { // utility for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if (digits < 10) Serial.print('0'); Serial.print(digits); }

`

gmag11 commented 2 years ago

Hi. As far as I know Time Library has 1 second accuracy. It does not calculate neither consider milliseconds so no higher accuracy is possible. Anyway, what is not working in your code?

RobInSaratoga commented 2 years ago

Hi, Thank you for your reply. Sorry for my delay (just finished a holiday here in the US).

Yes, I understand the Time Library's limitations; this is why I want to use this library.

My question is more about implementation. I currently use the Time Library - with calls for displaying time in particular formats - using the time_t variable. What I would like to do - but I don't know if it is possible - is how to continue to use the Time Library with the ESTNtpClient is setting (and resetting) the time?

Does this library completely replace the Time Library (I don't think so according to the readme file)? If so, how do I use the variables (or what variable do I use) to display the time (to an LCD, for example)?

If it works with the Time Library, then how do I get the two to work together. In the example code I gave earlier evidently the Time Library does not see that the ESPNtpClient has set the system time - in other words, the "if (timeStatus() != timeNotSet)" returns a false flag. If I use the basic Time Library example code, how do I implement this library to gain higher precision in that example?

Thank you.

Rob

gmag11 commented 2 years ago

You may use this example code as a beggining:

#include <Arduino.h>

//#include "WifiConfig.h"

#include <ESPNtpClient.h>
#include <TimeLib.h>
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif

#ifndef WIFI_CONFIG_H
#define YOUR_WIFI_SSID "YOUR_WIFI_SSID"
#define YOUR_WIFI_PASSWD "YOUR_WIFI_PASSWD"
#endif // !WIFI_CONFIG_H

#define SHOW_TIME_PERIOD 1000

// time_t getTime () {
//     if (NTP.syncStatus () != unsyncd) {
//         Serial.println ("----------------- GETTIME ==> SYNCD -----------------");
//         time_t utcTime = time (NULL);
//         tm* currentTime = localtime (&utcTime);

//         time_t localNow = mktime (currentTime);
//         return localNow;
//     } else {
//         Serial.println ("----------------- GETTIME ==> NOT SYNCD -----------------");
//         return 0;
//     }
// }

void printDigits (int digits) {
  // utility function for digital clock display: prints preceding colon and leading 0
    Serial.print (":");
    if (digits < 10)
        Serial.print ('0');
    Serial.print (digits);
}

void digitalClockDisplay () {
  // digital clock display of the time
    Serial.print (hour ());
    printDigits (minute ());
    printDigits (second ());
    Serial.print (" ");
    Serial.print (day ());
    Serial.print (" ");
    Serial.print (month ());
    Serial.print (" ");
    Serial.print (year ());
    Serial.println ();
}

void ntpEventHandler (NTPEvent_t e) {
    //Serial.printf("NTP Event: %s\n", NTP.ntpEvent2str (e));
    if (e.event == timeSyncd || e.event == partlySync) {
        time_t utcTime = time (NULL);
        tm* currentTime = localtime (&utcTime);
        // Serial.printf ("Year: %d\n", currentTime->tm_year + 1900);
        // Serial.printf ("Month: %d\n", currentTime->tm_mon + 1);
        // Serial.printf ("Day: %d\n", currentTime->tm_mday);
        // Serial.printf ("Hour: %d\n", currentTime->tm_hour);
        // Serial.printf ("Minute: %d\n", currentTime->tm_min);
        // Serial.printf ("Second: %d\n", currentTime->tm_sec);

        setTime (currentTime->tm_hour, currentTime->tm_min, currentTime->tm_sec, currentTime->tm_mday, currentTime->tm_mon + 1, currentTime->tm_year + 1900);
    }
}

void setup() {
    Serial.begin (115200);
    Serial.println ();
    WiFi.begin (YOUR_WIFI_SSID, YOUR_WIFI_PASSWD);
    NTP.setTimeZone (TZ_Europe_Madrid);
    NTP.setMinSyncAccuracy (50000);
    NTP.begin ();
    //setSyncProvider (getTime); // You can use this instead of next line but timeLib will not sync until second try. If you use this, you need to uncomment getTime() fuctions in the code upwards.
    NTP.onNTPSyncEvent (ntpEventHandler);
}

void loop() {
    if (timeStatus () == timeSet) {
        digitalClockDisplay ();
    } else {
        Serial.println ("The time has not been set");
        Serial.println ();
        delay (4000);
    }
    delay (1000);
}
RobInSaratoga commented 2 years ago

Thank you for your response. I will give it a try. Kind regards.

RobInSaratoga commented 2 years ago

Hi,

I tried this code, as written, and I get seg fault. The code executes through the Setup and then prints "The time has not been set" from the main loop, once, and then it faults (it says Exception 9).

I tried the code from the basic example, and it works fine.

I am using a Wemos D1 mini (clone). I get the same issues on a NodeMCU (12E).

Any suggestions on what I might try to fix this?

Thanks in advance.