Notifications
Clear all

Getting started with ESP32 - SimpleTime


Tigs62
(@tigs62)
Active Member
Joined: 3 months ago
Posts: 12
Topic starter  

As this is only my second post, and only my first question, I hope you are gentle with me in case my mental faculties have drifted farther than I would like.

I have read the "Getting Started with ESP32" from start to end.   It is very good by the way.  I was specifically interested in how to get the correct time using time.h
https://dronebotworkshop.com/esp32-intro/#Simple_Time
It references the SimpleTime sketch that comes with the ESP32 library in the Arduino IDE.

 

The whole point of connecting to an ntp source is to get the correct time and updating the ESP32 internal Real Time Clock.  This is understand.

In the void setup() part of the SimpleTime sketch the code:

  1. connects to your WiFi
  2. gets the time from an ntp pool server
  3. then disconnects from the WiFi
    (to save power apparently)

What I don't understand is why these three bits of code all exist in the void setup() section of the code?
If I understand it correctly, being placed in the void setup() means that this code will only be called ONCE.

So, although the Real Time Clock has been updated, (once), it will not be updated ever again, because the code doesn't seem to be called from within the void loop().  The short bit of code in the void loop() is accessing the LocalTime which is stored in the ESP32 internal Real Time Clock.

As I want to implement the NTP functionality to make sure that my ESP32 projects have got the correct time, (3 of them are actually CLOCKS!), will I need to modify this code so that it updates the internal RTC say, once a day?

I was thinking that I would probably try to put those three bits of code in a subroutine called something like void GetTime() then call it from within the void loop() once a day using a Timer function.
( I am still learning about those too, so stand by for the next question soon )

Looking forward to some replies.
Thanks, in advance.

You are never too old to learn.
You are never too old to teach.


Quote
Topic Tags
DroneBot Workshop
(@dronebot-workshop)
Workshop Guru Admin
Joined: 2 years ago
Posts: 1004
 

@tigs62 

Welcome to the forum, and I'll try and be "gentle" with you LOL!

😊

You are correct in that the time is only updated in the Setup function, and thus only happens once, that is by design.  In most situations this would be sufficient, as the RTC keeps fairly accurate time once set.

And your idea for creating a GetTime function is a perfect way to accomplish what you want to do.

A good example of putting this into use is from the Bald Engineer (this makes the 2nd time this week I've sent someone to that awesome website), he has exactly the function you are looking for and a great example of putting it into practice.

Posted by: @tigs62

I am still learning about those too, so stand by for the next question soon )

 

We'll be waiting!

😎

Bill

 

"Never trust a computer you can’t throw out a window." — Steve Wozniak


Tigs62 liked
ReplyQuote
LydaRA
(@lydara)
Trusted Member
Joined: 4 months ago
Posts: 95
 

Some common time standards allow for drift of plus or minus three minutes--that's six minutes of variance between them! 

We had a private school that, being a good neighbor in the middle of a residential part of the city, wanted to shut down their obnoxiously loud bell system.  They thought they would simply go to Walmart and buy cheap "atomic" clocks.  Then I pointed out that teachers in one building might dismiss students "early," while teachers two buildings away might hold students "late."  Students might be given detentions, "late turn in" grade deductions, etc unfairly.  It would all just depend upon you & your clock's perspective!

So we deployed a "site synchronized" clock system.  It used a GPS time reference, then distributed this over a campus area with a low-power "atomic clock" beacon of our own.  Clocks sync'd every hour.  We even made the computers & phones on campus reference the GPS time. 

So, how precise do you _need_ your clocks to be?


Tigs62 liked
ReplyQuote
Tigs62
(@tigs62)
Active Member
Joined: 3 months ago
Posts: 12
Topic starter  

@dronebot-workshop

Hi Bill,

Thanks for the reply.  Unfortunately there is still an issue as far as I can see.

I followed the link that you gave me and looked at the code.
His code is almost identical to yours.  In fact, whenever anyone seems to want to discuss connecting to an NTP server, the same sketch seems to get used again and again.

A quick way to see if it is the same code, is to look for this comment:

disconnect WiFi as it's no longer needed

If I see this same comment, it gives me pause, every single time.

If the WiFi is activated, and the DISCONNECTED in the void setup, then there is no way that the code can be connecting to the NTP server anywhere else in the code, like in the void loop(), because the WiFi module is turned OFF.  (see my point). 😤 

The code at Last Minute Engineers, like almost every other webpage that I have looked at, uses the NTP server in the void setup() to configure the ESP32 RTC module, then after that, all calls for the latest time are done using something like the following bit of code:

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H%S");
}

However.... and this is the key bit, getLocalTime is NOT calling the time from the NTP server (as a few websites say that it does).  getLocalTime is making a call to the ESP32 internal Real Time Clock module.

The Real Time Clock may drift one way or another ad-infinitum until you turn the WiFi back on and update the RTC module using the code that is in the void setup()

THIS is the bit of code that is actually getting the time from the NTP server and updating the Real Time Clock:

configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

I am hoping that I am not going mad and that someone can see this too.
I am beginning to feel like Tom Hanks in castaway (WILSON, WILSON....I'm sorry!)
I hope you guys will take a closer look at this and tell me whether I am going insane or whether this bit of code needs to be explained better to lots of people.

In answer to the new reply from LydaRA, the problem that I am struggling with is that these clocks I am building are inside the Factory where I work as the IT Manager.  We have a LOT of CNC Milling machines and CNC Lathes as well as two large air compressors, all of which belch out huge amounts of heat.  In winter this is very welcome, in summer it is a huge issue for the workers.  It is also a huge issue for my early designs of ESP32 clocks.  As they get hotter and hotter the internal RTC starts to drift all over the place.

If I can update the time from an NTP source about once an hour, it will probably be OK.
We actually have a company NTP device in our air-conditioned server room, so I don't even need to reach the internet, just my internal network.  Another function that I want my clocks to perform is to measure the temperature every 5 minutes and send it to ThingsSpeak.

I have found a great project to do just this, in a really simple project on this website: https://randomnerdtutorials.com/esp32-thingspeak-publish-arduino/

Regards
Chris

You are never too old to learn.
You are never too old to teach.


ReplyQuote
codecage
(@codecage)
Member Admin
Joined: 2 years ago
Posts: 1079
 

@tigs62

Even though the wifi is disconnnected in setup, couldn't you just reconnect and ask the NTP server once an hour, using the RTC of the ESP32 as your "time keeper" of when to reconnect.  It shouldn't be too far off after just an hour.  In other words, every hour, connect, update time from the NTP server, disconnect.

But if you are retrieving the temperature every 5 minutes, aren't you going to need the wifi to report that upstream anyway, so why disconnect and reconnect all the time?

SteveG


MadMisha and Tigs62 liked
ReplyQuote
DaveE
(@davee)
Estimable Member
Joined: 4 months ago
Posts: 137
 

Hi @tigs62,

  Bill has indeed pointed you to good website for explaining about NTP, etc.

And please accept my apologies if I am pointing out the 'obvious', but from personal experience, I know how difficult it can be to spot the 'obvious'.

The example on that website is simple, which is good for the purposes of the demonstration, but that simplicity assumed that the processor could be dedicated to spending most of its time spinning its registers in the delay(ms) function. However, in most cases, the processor will have other things to do. Furthermore, calling NTP every second is a massive overkill, which if it was repeated across all processors across the world that use NTP, could overrun the servers.

Thus it is probable you need a slightly more sophisticated approach to decide when to call the NTP server.

There are probably thousands of examples around of how to approach this, if you look hard enough, but I hope the following is a useful start. The 'full blown' approach might include installing a real-time system to replace the basic setup() and loop() style of the Arduino. But the setup() and loop() style is sufficient in many cases.

First, decide how frequently your local clock needs updating - this is a function of the expected accuracy of the actual clock compared to the accuracy needed for your project. Maybe once per 24 hours might be a starting point.

Now you need a way of calling your NTP update function, once per 24 hours (or whatever period you choose), which uses minimal processor time so that the processor can concentrate on its 'day job'.

Assuming your Arduino top level code looks like:

void setup() { // Usual start up code here (including defining variables etc. for the NTP task)}
void loop {  check_if_its_time_to call_NTP_and call_if_necessary ();
  do_the_main_tasks_once ();}

Thus you need the code for the function check_if_its_time_to call_NTP_and call_if_necessary (); which will check to quickly if it has called the NTP within the 24 hours, do the NTP call if it hasn't, and then return to loop();, so that it can go through the do_the_main_tasks_once (); again.

The basis of how of a method to check if 24 hours has passed is provided in an Arduino sketch https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay . Obviously, the example is looking for 1 second, not 24 hours, but the basics are there. Note that the milliseconds timer will 'reset' after about 50 days, so if your system 'up' time between resets is likely to exceed 50 days, you will need to include appropriate allowance.

Depending upon the amount of time it takes for do_the_main_tasks_once (); function to run, you may decide to let it execute 'n' times, before doing the NTP check.

Another possible 'gotcha' to be aware of is, whilst the processor is running check_if_its_time_to call_NTP_and call_if_necessary (); , it is not running the main processor tasks. Most of the time, it will not call the NTP server, and hence return quickly to the main tasks. However, when it does call the NTP server, it will be occupied for longer, and the amount of time is likely to vary with the nuisances of the Internet. If any of your main tasks are time-critical, this could cause them to fail --- but with the call only happening once per 24 hours, it might be a long time before a problem shows up.

To get a rough idea of how long the NTP call will take, you could modify the code in the website Bill referenced, to call the NTP server 20 (say) times in a loop, without the delay(1000); , and preferably saving the times in the loop to an array, then printing the array outside of the loop.

I hope this useful and you are successful with your real-time programming project! Dave

 


ReplyQuote
Tigs62
(@tigs62)
Active Member
Joined: 3 months ago
Posts: 12
Topic starter  

@davee

Ooh, lots to read, thank you.

I think that I am going to have to take a stab at my own code and see where it gets me.  Hopefully it will work as expected, but if not, I may need to come back for some more help.
I followed some code from another site which uses the milli function to turn on and off an LED rather than using the .

But when I tried to adapt the same code to call a subroutine ( void ), it failed miserably.
But that is a different question and a different problem.

Initially I will try just calling the ntp server once an hour and check how far off the RTC is.
Like I mentioned to LydaRA, when I tested these clocks at home, the RTC didn't drift very much.
When I take the clocks to the "blazing inferno" that is the factory, things seem to "drift" quite a lot.

However, at least now I can see the difference in updating the RTC from the NTP server and just getting the time from the RTC.

Thanks for all the input guys.  More experimentation is clearly required.

Regards
Chris

You are never too old to learn.
You are never too old to teach.


ReplyQuote
DaveE
(@davee)
Estimable Member
Joined: 4 months ago
Posts: 137
 

Hi @tigs62,

  Sorry, I have just seen new conversations have been added whilst I was typing. Also, apologies if I have in anyway misunderstood your query.

I guess most of the example code relates to situations in which the system is likely to be powered down at the end of the day, so a decent real-time clock would still be reasonably accurate over 12 hours. To some extent, your solution may depend upon:

  1. How much error can you tolerate?
  2. What rate do the local clocks drift?
  3. Special precautions you need to take when the local is updated to avoid your 'data' being 'corrupted' by 'missing' or 'reliving' seconds.

I used 24 hours in my previous discussiom but maybe 30 minutes or 1 hour is more appropriate to your situation.

I only looked at the website mentioned, so didn't spot their repetitive calls were to the local clock - obviously the call should be to the NTP server at least once in a while to resynchronise the local clock with 'NTP time', and that call can only happen if the WiFi is active, so the appropriate parts/all of the WiFi code in the example setup() needs to be called everytime the NTP server is consulted. Clearly the code needs a little 'rearranging' compared to the example, but am I missing a fundamental problem?

Also, the example code has obvious 'human readable' error reporting, like "Failed to obtain time", whilst, except at power up, you would probably want the system to continue on local time for now, whilst warning it might need attention when someone is available.

I haven't looked at ThingsSpeak, but I presume the outline I gave for calling the NTP server could be duplicated to measure and report the temperature every 5 minutes as well.

Does that answer your queries or I am missing something?

Best wishes, Dave


Tigs62 liked
ReplyQuote
DaveE
(@davee)
Estimable Member
Joined: 4 months ago
Posts: 137
 

Hi Chris (@tigs62),

  Once again our messages have crossed in the Ether. Hopefully, you will be more successful on your next code bashing session. It was probably an 'obvious' problem ... which can be a real * to spot.

If you get stuck, first create a copy of your project, so you don't lose your work.

Then, on the copy, progressively slice out bits to try to contain the bug to a small program segment. If, neccessary, post it, along with error messages, etc. and hope someone else can spot it.

Good luck and please share any useful findings. Dave


Tigs62 and LydaRA liked
ReplyQuote