NTPClient icon indicating copy to clipboard operation
NTPClient copied to clipboard

Wrong time data from NTPClient

Open afrixx opened this issue 5 years ago • 26 comments
trafficstars

Describe the problem

Normally, this library provides correct time data, with a maximum 2s deviation. But some days, let's say every 30 days, I get wrong time data from the library. Sometimes 5 minutes difference, sometimes 30 minutes. And although I have configured a refresh every 10 minutes, the time remains wrong for hours, sometimes only until a hard reset.

You could say it's a network problem, but I can access the webserver on the ESP all the time.

Additional context

I am using a Wemos D1 Mini board (ESP8266-based).

afrixx avatar Apr 30 '20 21:04 afrixx

It is an intricate problem. Can I have a look at your codes? You can include files in reply.

WhymustIhaveaname avatar May 01 '20 10:05 WhymustIhaveaname

Thanks @WhymustIhaveaname for having a look at my code. I included the 2 basic files (wortuhr.ino and timezoneHelper.ino, renamed to .txt). wortuhr.txt timeZoneHelper.txt

afrixx avatar May 01 '20 11:05 afrixx

Entschuldigung, I didn't find the reason for your problem, although clues indicate this is the problem of this library. However, I found that you are not the only one, in issue #6 is there a bunch of people suffer from the same problem as you.

May you find the bug.

WhymustIhaveaname avatar May 01 '20 14:05 WhymustIhaveaname

Thanks @WhymustIhaveaname for your support! I will go on debugging...

afrixx avatar May 01 '20 23:05 afrixx

You can try my fork. This fork, by default, prints many pieces of information about NTP via Serial, such as the time NTP package is sent and received, the times in the NTP response package. It also changes the return type of update from bool to byte, to record more information(1 on update and success, 0 on update but failed, 2 or 3 on not time to update). These may help you debug.

WhymustIhaveaname avatar May 02 '20 03:05 WhymustIhaveaname

Hi, I have a similar (identical?) problem... I am using always the EPOCH date (and have the offset myself through an online API). However now I see that that the time jumps regularly with one hour... By coincidence the NTP Update interval is one hour... I already did some code reading of the NTPClient, but does not find anything what could explain this... I now added some syslog debug information in case the NTP Update failed (so in case of timeout).

The principle of my implementation is explained below. So I am very interested in the possible results of your debugging. I will also share mine once available.

In the Startup:

    // Start NTP Server connection and wait until time is received
    timeClient.begin();

    // Wait until NTP time received
    uint16_t NTPStart = millis();
    do {
      NTPUpdateDone |= timeClient.update();
      yield();
    } while ( !NTPUpdateDone && (millis()-NTPStart < NTP_TIMEOUT) );
    CurrentDateTime = timeClient.getEpochTime();

And in the Loop:

  boolean NTPUpdate = timeClient.update();
  CurrentDateTime = timeClient.getEpochTime();

Filip

FilipDem avatar May 14 '20 14:05 FilipDem

I did a lot of more testing to find the deviation issue - but I was not successful.

For me I found another solution, which works fine and is much more easy: The ESP8266 core now contains its own time library: You are able to define multiple NTP Servers, it works in background and there is also a timezone calculation included. So I removed both NTPClient library and Timezone client by adding this functions: https://github.com/esp8266/Arduino/blob/9913e5210779d2f3c4197760d6813270dbba6232/cores/esp8266/time.c

There is a good example sketch to try out: https://github.com/esp8266/Arduino/blob/61cd8d83859524db0066a647de3de3f6a0039bb2/libraries/esp8266/examples/NTP-TZ-DST/NTP-TZ-DST.ino

The setting of the timezone is very simple:

  // set timezone to Berlin
  setenv("TZ", "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", 3);
  tzset();

There you get most important time zone strings: https://sites.google.com/a/usapiens.com/opnode/time-zones

So... if you're using the ESP, I can only recommend this internal ESP library.

afrixx avatar May 14 '20 17:05 afrixx

Thanks. Was easy to use and seems to work fine. Still to test on long run, but was easy and promising. Don't know why there are not a lot of references to this library when we google ESP8266 NTP...

(for people that stick to NTPClient) Yesterday I did bit of code reading again of the NTP client and the only reason I can expect for the time jumps is that the return from the NTP server has zeroes... So time is not updated while the "last_update" time is set as we received a successful answer. Did not debug this, but I am almost sure that this can be the only reason...

F

FilipDem avatar May 15 '20 07:05 FilipDem

My update interval is set to 10 minutes, and the error manifests as 10 minutes behind. The error is highly dependent on the connection. Some ESP32s I have running in other locations, never experience this error. One always shows the error within an hour or two of operation.

I'm going to try a hopefully temporary workaround that will keep trying until the time received is greater than the previous update.

mitchsf avatar Jun 20 '20 11:06 mitchsf

I can also confirm this issue; and the wrong time depends clearly on the update interval or multiples of it. I think FilipDem is correct with his assumption about "last_update"

morres83 avatar Jul 09 '20 05:07 morres83

I stopped using the NTPClient seen I had too much of these problems (don't think there is a lot of activity to solve the concerns). I switched to the solution of afrixx (see above - default time library). Is easy to integrate and works very well! Can only recommend this (sorry to say this in the NTPClient topic).

FilipDem avatar Jul 09 '20 13:07 FilipDem

I seem to have this under control now. Around line 126 of NTPClient.cpp, NTPClient::update(), there is a "return true" statement on an earlier release, and "return false" on the current release. That's why it was returning corrupted packets. I'm not going to research the cause, maybe it's something I changed inadvertently, or maybe a bug fix. It does make sense that the last good packet received was off by the update interval.

mitchsf avatar Jul 09 '20 14:07 mitchsf

I think the problem lies in the forceUpdate function. The client receives "0", _lastUpdate will be set even though the reception was not correct. Once you read the time by getEpochTime(), you get the wrong offset.

I fixed it in another fork of a similar library, which I use. It combines a check for 0, return codes for update() and a check if the new time is OFFSET later than the current one. You might take a look if you want (ntpUpdate()-function). I think it fixes the issue (as far as I can tell today). https://github.com/morres83/NTP/blob/master/NTP.cpp

morres83 avatar Jul 09 '20 14:07 morres83

I stopped using the NTPClient seen I had too much of these problems (don't think there is a lot of activity to solve the concerns). I switched to the solution of afrixx (see above - default time library). Is easy to integrate and works very well! Can only recommend this (sorry to say this in the NTPClient topic).

Congratulations to you finally find a better solution. I agree with you that this package is buggy and user-unfriendly.

WhymustIhaveaname avatar Jul 10 '20 13:07 WhymustIhaveaname

Unfortunately also my Bugfix doesn't solve the problem completely, as I found 1 day later.

Clearly, there is a bug. But I wouldn't call this library user-friendly. But the Arduino core solution and the example sketch clearly is. That's why you cannot find any hint on Google about it.

morres83 avatar Jul 12 '20 05:07 morres83

The latest release is working fine for me, at least so far. I added an additional method to get milliseconds. The library referred to by afrixx looks great, but I use the ESP32 and I don't see a version for it.

mitchsf avatar Jul 12 '20 14:07 mitchsf

The latest release is working fine for me, at least so far. I added an additional method to get milliseconds. The library referred to by afrixx looks great, but I use the ESP32 and I don't see a version for it.

For ESP32 the integrated time library works fine, too: https://randomnerdtutorials.com/esp32-date-time-ntp-client-server-arduino/

afrixx avatar Jul 12 '20 16:07 afrixx

Thanks. I think that Timezone is still required to automatically shift to DST, but that's easy enough to add.

mitchsf avatar Jul 13 '20 14:07 mitchsf

I just noticed this issue recently and found that the version I had did not have the following code near the beginning of forceUpdate(). It does appear in version 3.2:

  // flush any existing packets
  while(this->_udp->parsePacket() != 0) {
    this->_udp->flush();

What I believe was happening in my case is that after an unsuccessful forceUpdate(), the NTP packet actually came in after the timeout period. When called the next time, the udp->parsePacket() immediately returns the packet from the previous iteration. With a debug statement, I found that the timeout count is then always 1 after a delayed NTP response. Ten milliseconds is not long enough for a distant server to respond. The flush ensures that the previous packet is cleared so you get the latest update.

hedgemybets avatar Feb 01 '21 02:02 hedgemybets

I just noticed this issue recently and found that the version I had did not have the following code near the beginning of forceUpdate(). It does appear in version 3.2:

// flush any existing packets
while(this->_udp->parsePacket() != 0) {
this->_udp->flush();

I think this is exactly what fixed the problem.

mitchsf avatar Feb 01 '21 17:02 mitchsf

Just jumping on this train, I also noticed that my clock showed the wrong time after a while, with the offset of the ntp-update interval. Same library version (3.2.0, I suppose, as it has not been updated for a while). So I also modified my sketch to use the integrated time library, which made things even simpler. I only added a secondary loop to run the ntp-update every 10 minutes, based on the "blink without delay" example.

DrTron avatar Mar 09 '21 01:03 DrTron

Just piling on to say that I have the same issue. My "fix" is pretty simple. I seem to be getting small numbers for my epoch time

the last few times it happened I got "6" but its hard to know if thats coincidence or not. I'll edit my sketch to use the integrated library mentioned above later, but i'll leave my serial monitor open and see if I always get 6 which might mean something?

I'm using ntp just to keep an RTC Module in sync, so I decided the easiest course of action is to ignore bad results my RTC will keep good enough time for my project

void updateTime(){
  Serial.println("UpdatingTime");
    timeClient.update();
    long realTime=timeClient.getEpochTime();
    //sometimes ntp was telling the the time was a very small number if that happens we just ignore it and keep the rtc the same
    if (realTime > 1000000){
        rtc.adjust(DateTime(realTime));

    }
  Serial.println(realTime);

}

robertknutzen avatar Jul 09 '21 08:07 robertknutzen

same problem here. Off by one hour (updateperiod was set to 5min but updates where done only by forceupdate by an external trigger about once every hour) Fixed itself after about a day. Happend twice this month with continously running setup. server was europe.pool.ntp.org.

0815Creeper avatar Oct 30 '21 16:10 0815Creeper

same problem here. ‍‍‍‍‍.update(); run in every loop and there is some minutes behind ! and time goes wrong after a while /

alirezaimi avatar Jan 23 '22 13:01 alirezaimi

An old thread, and not sure if this is related to the same problem. Using NTPClient on Arduino Portenta. My code, and the example code, had an offset in the NTP time by the amount equal to the update interval.

In the example case, the update interval was 10sec, and the time being returned was 10 sec behind.

In my code, I use a 60 second interval (Portenta 32kHz clock issues), and the time returned was always 60 sec behind.

What I did was issue a

timeClient.update();

a second time in the loop

for(;;) {

     timeClient.update();

    if (timeClient.updated()) {

      SerDebugln("********UPDATED********");

    } else {

      SerDebugln("******NOT UPDATED******");

      rtos::ThisThread::sleep_for(mbed::chrono::milliseconds_u32(1000L));

      continue;

    }

    timeClient.update();    // reread in case buffer issues

It now seems to return the correct time, and I am able to set the arduino clock to within a couple of seconds of the clock on my PC.

salasidis avatar Aug 12 '22 23:08 salasidis

Never mind on my last posting. It worked for a short time, and then started to be behind by one minute again.

I got rid of the code, and I am using the sendNTPpacket software that is also generally available. That one works, however, because of the forced delay for 1 second after sending the packet to parse the packet, the synced clock is 1 second behind. I compensate by just adding 1 second to the clock time that is retrieved.

salasidis avatar Aug 14 '22 20:08 salasidis

"4. End-User agrees that he or she will not: (a) Change default settings to make more frequent request of the Services, if using an ntp daemon (“NTP Protocol”); (b) Request time from the Services more than once every thirty (30) minutes (ideally at even longer intervals), if using SNTP. (c) Set the time more often than is necessary for the purposes of the device; if the device can keep reasonably accurate time for several days, End-User will not set the time every hour. Additionally, if the device only uses whole seconds, End-User will not optimize the device for millisecond accuracy. (d) Set up a regular time sync interval such as “top of the hour”, “top of the minute”, or “at minute or second X”." https://www.ntppool.org/tos.html

Calling timeClient.update() in every hour solved my issue.

pisunio avatar Oct 13 '22 17:10 pisunio

I think, I have fixed this. So I have made the telegram bot on ESP8265 that shows whether I have light at home or not. If there are no light it goes into light sleep. After external interrupt (light goes on) in wakes up and getting ntp time (almost every time wrong). I've tried a lot of cases and now seems that this one is working. Pasted it after waking up and connecting to wi-fi:

    while ( timeClient.update() == false){
      Serial.print("_ ");
      timeClient.update();
      delay(500); 
    }

It takes from 10 to 50 seconds to get real time. At least it works correctly now

dDenVil avatar Jan 04 '23 14:01 dDenVil