Skip to Content

← NTP-Synced Hardware RTC on an ESP32 PLC for Timestamps

Textile monitoring (weaving)ESP32 PLCNTPResilience / OTA

NTP-Synced Hardware RTC on an ESP32 PLC for Timestamps — full example

Sync the hardware RTC of an ESP32 PLC over NTP with retries and periodic resync, so industrial datalogging timestamps stay correct through outages.

Complete, runnable program for the ESP32 PLC (rtc-ntp-synchronization.ino): wiring header, requirements and integration notes included.

Download the full project pack — freeThis example + the related ones + bill of materials

Read-only preview.

/*
 * COMPLETE EXAMPLE — Hardware RTC synchronized via NTP
 *
 * Hardware: ESP32 PLC (Industrial Shields, with integrated RTC chip and WiFi)
 * Based on: textile monitoring project, modul_RTC.h
 *
 * Network:
 *   Plant WiFi with internet access (pool.ntp.org) — without internet
 *   access, point to a local NTP server on the concentrator
 *
 * Architecture:
 *   1. At startup (with network) the time is requested via NTP with retries
 *   2. The time is written to the physical RTC chip -> it survives reboots
 *      and network outages: the datalogging timestamps are never garbage
 *   3. Periodic resynchronization (every 12 h) to correct drift
 *   4. The timestamp of the last successful synchronization is recorded,
 *      exposed as a diagnostic by the webserver and the MQTT commands
 *
 * Works together with other catalog examples:
 *   - sd-daily-file-datalogging.ino (file names /YYYY-MM-DD.json)
 *   - mqtt-events-sd-buffering.ino (messageID with real timestamp)
 *   - webserver-ota-firmware.ino (status page)
 */

#include 
#include           // integrated RTC of the PLC (Industrial Shields library)
#include 

const char *WIFI_SSID = "WIFI_SSID";
const char *WIFI_PASS = "WIFI_PASS";

const char *NTP_SERVER       = "pool.ntp.org";
const long  GMT_OFFSET_SEC   = 3600;     // CET
const int   DST_OFFSET_SEC   = 3600;     // daylight saving time
const uint32_t RESYNC_MS     = 12UL * 3600UL * 1000UL;   // every 12 h

uint32_t lastSyncOK = 0;                 // epoch of the last successful sync
uint32_t tResync = 0, tWifi = 0, tPrint = 0;

// ------------------------------------------------- NTP -> RTC synchronization
// Returns true if the RTC chip was updated
bool syncRTC() {
  if (WiFi.status() != WL_CONNECTED) return false;

  configTime(GMT_OFFSET_SEC, DST_OFFSET_SEC, NTP_SERVER);

  struct tm timeinfo;
  int attempts = 0;
  while (!getLocalTime(&timeinfo, 1000) && attempts < 10) {
    attempts++;
    Serial.println("NTP: retry " + String(attempts));
  }
  if (attempts >= 10) return false;      // no NTP: keep running on RTC time

  time_t now = mktime(&timeinfo);
  RTC.setTime((uint32_t)now);            // write to the physical chip
  RTC.write();

  lastSyncOK = (uint32_t)now;
  Serial.println("RTC synchronized: " + String((uint32_t)now));
  return true;
}

void checkWiFi() {                       // non-blocking, see the dedicated sheet
  if (WiFi.status() == WL_CONNECTED) return;
  if (millis() - tWifi < 10000) return;
  tWifi = millis();
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
}

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

  RTC.begin();                           // the chip time is already usable at boot

  checkWiFi();
  uint32_t t0 = millis();                // initial WiFi wait (max 15 s)
  while (WiFi.status() != WL_CONNECTED && millis() - t0 < 15000) delay(500);

  if (!syncRTC())
    Serial.println("No NTP at startup: using previous hardware RTC time");
}

void loop() {
  checkWiFi();

  // Periodic resynchronization to correct crystal drift
  if (millis() - tResync >= RESYNC_MS) {
    tResync = millis();
    syncRTC();
  }

  // Demo: print the real time every 10 s (the one the datalogger would use)
  if (millis() - tPrint >= 10000) {
    tPrint = millis();
    if (RTC.read()) {
      char buf[32];
      sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
              RTC.getYear(), RTC.getMonth(), RTC.getMonthDay(),
              RTC.getHour(), RTC.getMinute(), RTC.getSecond());
      Serial.print("RTC time: ");
      Serial.print(buf);
      Serial.println("  (last NTP sync: " + String(lastSyncOK) + ")");
    }
  }

  delay(50);
}
Download the full project pack — freeThis example + the related ones + bill of materials