Network Time Protocol On The ESP32

Network Time Protocol (NTP) is one of the best ways to keep networked computers synchronized to the same time. It’s simple, lightweight, and not only allows computers to maintain a time standard together, but it also allows some computer manufacturers to save some money on hardware costs. The Raspberry Pi is perhaps the most well-known example of a low-cost computer without the extra expense of a real-time clock (RTC). While the Pi sets up NTP essentially automatically, other microcontrollers like the ESP32 don’t, but it is possible to configure them to use this time standard with some work.

For this project the MicroPython implementation for the ESP32 is required. MicroPython is a way of running Python code on microcontrollers or other embedded systems without all of the overhead that Python would normally require. Luckily enough, the NTP libraries are built right in so once MicroPython is running on the ESP32 it’s nearly as easy as calling the library. Of course you will have to make sure there is an internet connection, and then grab the time, sync it to the machine, and then set the timezone.

For a bonus exercise, the project’s creator [Bhavesh] suggests attempting to configure Daylight Savings Time, although this can be a surprisingly difficult problem to solve. In the meantime, there are a few other ways of installing a clock on a microcontroller like this one. An RTC module is an obvious choice, but you can also get incredibly accurate time by using a GPS module as well.

29 thoughts on “Network Time Protocol On The ESP32

  1. I have an ESP-32 SSNTP implementation as part of Generic Main for esp-idf, at . This sets the time and you can set the timezone in a non-volatile parameter, then the time zone and DST are handled via the Olson time library and database, as it is on big computers. See also ../commands for the “date” and “param” command. This supports C and C++, and could probably be persuaded to support Rust, Python, etc. with some effort. It also implements STUN, PCP, Dynamic DNS, REST, Dynamic DNS, a select-based event loop, and a job (really coroutine) runner. It’s dual-licensed AGPL3 and commercial. Still pretty young, but I think you might find it worth perusing.

    It’s the basis of the $14 remote ham radio transceiver controller I’m making. See the parent directory at

    Also, please see, which we have created to support the development of Open Source software and hardware for Amateur Radio.

  2. If your IOT project needs to understand date and time, this information is already from any web server (it’s included in the headers of every GET request). The beauty of this is that – where you have edge devices uploading data to a central server your devices have a central, consistent time source.

    1. I’ve worked in enough shops to know there are always some servers that do not have the correct time. If the information is worth capturing it is worth some extra lines of code the time to get the correct time stamp.

      1. Interesting. I’ve always made sure that the server times are synchronised and correct in the first place.

        Having accurate, synchronised clocks is important for a number of other matters (e.g. Kerberos, security event logging, etc.) and all modern operating systems (Linux, Windows, etc.) have tfacilities available to fix this.

        You must have worked in some real borderline shops in the past.

  3. Having worked on NTP problems in IOT devices, I just wanna say: I hate it. Chrony might be better, but I haven’t used chrony enough to say if it fixes my core complaint with NTP: it’s a pain to debug problems. In my case the root cause was poor network configuration on a customer site, but in a global deployment of devices that problem will happen a lot.

    1. You have to have your network configured correctly to properly handle just about any UDP based communications, not just NTP. Especially you need to have your broadcast addresses set correctly or you may be spraying packets all over the place, clogging up all manner of things. Been there done that. Tell your customers to get their act in gear. No, this does not happen a lot in companies that have even mild competence in networking, when they have problems like this they get detected and fixed asap.

    2. SNTP is, like it says, a lot Simpler than NTP but much less accurate. It’s for IoT devices that just need the time set and won’t need high-resolution time. Debugging these things is unfortunately best done with Wireshark. All of the extra stuff we might have put in for visibility in an implementation for a larger computer is absent from IoT applications simply because size is a premium.

    1. None of the microcontrollers I’ve seen have high accuracy RTC. If you really care about accurate RTC then you should have it in a separate package because those can be much more accurate, The best ones have the crystal in the package with the RTC so they can detect the temp of the crystal and compensate.

  4. Why does everyone try and reengineer this. Its completely built into free rtos. One lone configuration.

    configTime(0, 0, “”);

    Pretty much posix compatible os. Almost all the eap32 ntp libraries are reinventing what already built in.

  5. If you’re going to use micro Python might as well not even use NTP. Going to be so much latency in python your time will never be accurate. I’ve built a GPS to NTP server on an ESP32. All in C code and there’s still enough jitter in C running on an ESP32 with all it’s background wifi handling to make a distant NTP server over the internet still more accurate. I can only imagine how bad it would be with python

    1. Depends on your goal. Making an alarm clock? More than good enough, as long as it isn’t more than 30s off it’ll work just fine. Precision instrumentation synchronization? No way.

  6. You don’t need the bloat and speed-hit of MicroPython to get NTP time with the ESP32 because its already included in the ESP32 C/C++ toolchain. If you are interested, here’s more…

    I want to say this first: Please do not abuse the public NTP Pool Project servers. Read the NTP Pool Project’s use recommendations and Terms of Service (ToS) at [1] below.

    The ESP32’s C/C++ ESP-IDF toolchain (and therefore the Arduino IDE ESP32 Core as well) has a built-in NTP client (or is it SNTP) with auto DST and UTC offset capability. See [2] for a tutorial on how to use the built-in NTP client. Normally I recommend you add a battery-backed Maxim Integrated DS3231S Extremely Accurate I²C-Integrated VC-TCXO referenced hardware RTC [3] to be periodically disciplined via the NTP client. That way you only have to hit the public NTP server pool very infrequently to maintain the time.

    However, if you can’t or don’t want to use an external hardware RTC, the ESP32 has a built-in RTC of its own. The ESP32s built-in RTC is by default configured to use the best internal timing options, but it is nothing in comparison to the excellent stability and accuracy of the DS3231S hardware RTC. But in a pinch the ESP32s internal RTC is there for you, see [4] for an easy to use example of how to set and read the ESP32’s internal RTC in C/C++. So you get NTP time and set the internal RTC with it then just read from the internal RTC instead of always using the public NTP pool. The accuracy and stability of the ESP32s default internal RTC can vary quite a bit, even between modules but it might be good enough for you. So test it and decide if it will work in your project.

    If you buy a DS3231 RTC module online, be very careful. Almost all the DS3231 modules from China either have the inferior DS3231M chip instead of the more stable and accurate DS3231S part (the DS3231M does not have a VC-TCXO reference like the DS3231S), or the parts are incorrectly labeled DS3231S but are really either DS3231M parts, or mostly functionally compatible but seriously inferior DS1307 chips, or outright fakes. I have a half-dozen or so Chinese DS3231M modules bought on Amazon. All of them are out-of-spec unstable and/or inaccurate compared to the datasheet.

    Also most of the Chinese DS3231 modules have a backup battery trickle charge circuit that consists of a 200R series resistor (YMMV) and a 1N4148 steering diode. See [5] for a Chinese DS3231 module example on Amazon complete with schematic. That DS3231 module will only work properly if you power the module from 3.3V (not 5.0V) and use a rechargeable LR2032 coin cell, not a non-rechargeable CR2032 cell. Instead I recommend you just remove the trickle charge series current limit resistor or the series diode and use a non-rechargeable CR2032 coin cell for backup. A good quality non-rechargeable CR2032 coin cell will last for years.

    Or you could simply avoid the risk with buying a generic Chinese DS3231 module and spend more money to buy a module that’s known good. For example I know personally that Adafruit’s DS3231 Feather compatible module [6][7] works properly. My Adafruit Feather compatible modules have genuine DS3231S (not M) chips on them. [Note, I am not affiliated with Adafruit.] Wherever you buy your DS3231 module make sure you get a schematic and it has a real DS3231S chip on it, not a DS3231M or worse-yet a fake.

    Building a DS3231S RTC module is simple (look at the Adafruit module’s schematic). But the problem is DS3231S chips are essentially unobtainium due to the chip shortage. Mouser is showing a Q1 2023 restock date [8], Digi-Key has zero stock [9] and does not even list a lead-time. Adafruit has some DS3231 modules in stock, but that will likely dry up some day. Be careful where you buy DS3231S chips, I believe there are fakes in the wild.

    * References:

    1. The NTP Pool Project Terms of Service

    2. ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)

    3. Maxim Integrated DS3231 Extremely Accurate I²C-Integrated TCXO/Crystal Based RTC

    4. fbiego/ESP32Time Library (for ESP32 internal RTC)

    5. HiLetgo 5pcs DS3231 AT24C32 Clock Module Real Time Clock Module IIC RTC Module for Arduino Without Battery 4.4 out of 5 stars 183 ratings $18.49 [With Schematic]

    6. DS3231 Precision RTC FeatherWing – RTC Add-on For Feather Boards, Product ID: 3028, $13.95 ea.

    7. Adafruit DS3231 Precision RTC Breakout – Tutorial & Schematic

    8. DS3231S @ Mouser

    9. DS3231S @ Digi-Key

    1. Daylight saving is not necessarily hard for any given country, it’s hard for all countries. Even your little mnemonic there (which you’ve named ‘formula’, cute) doesn’t include all the information necessary.

  7. I am playing around with NTP and IOT network time in my home for the simple reason that I dream of the day that all of my clocks set themselves and I no longer need to care about them…
    It is the big reason that I have ordered some RTC’s from Micro Crystal and some devboards from Sparkfun to build some desk clocks as well.

    Shoving an ESP32 into my microwave or stove to be able to “push buttons” and set the time after a power outage or every few months is my tiny slice of spectacular….

  8. Since I come from the *nix world, I think of NTP as both the time-sharing protocol and the clock-discipline PLL aka clock conditioning.

    A free-running clock, who’s time is occasionally set by the protocol, is confusingly called NTP too. That’s what the three inexpensive aliexpress “WiFi” clocks I’m auditioning for radio-station use seem to be doing. It makes a lot of sense for the battery-operated analog wall clock to omit clock conditioning since it demands frequent WiFi use. I suspect they’re all ESP32 or its cousin.

    Since the $20[sic] GL-MT200N-v2 “mango” has full NTP (since it runs OpenWRT, hence it also handles time zones), I was hopeful one of the USB-powered WiFi clocks might also have a clock disciplining, but it doesn’t appear to be the case (and it doesn’t seem trivial to put a nice big display on the mango).

    FYI none of the clocks handled the US time-zone change and only one of the three is careful to switch the seconds digits precisely at the start of the second rather than some time in between. One clock hard-wires its NTP server. Two don’t allow adjusting the synchronization interval at all. Interestingly xclock(1) on *nix switches the seconds digits at the right time, while my desktop toolbar clock does not.

    Realistically a free-running quartz clock set twice a day with sloppily-timed seconds updates is probably good enough for coordinating nothing-fancy radio production, but my inner geek wants more.

    Clock-conditioning NTP for ESP32 seems like a good thing for applications with the power to feed it.

    de N0KCL

  9. It’s wrong about leap years.
    1. divisble by 4 is a leap Year
    2. by 100 is not
    3. by 400 it is

    The millenia issues was (partly) due to programmer’s knowing 1 and 2 but NOT knowing 3. Let’s not repeat that mistake, please. Although, I give it’s a long time to the next “opportunity”. On the other hand, that was the excuse in the 80’s too. The flaw in the article will be wrong in 78 years “only”.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.