We talked about ESP’s built-in RTC for time stamping and storing data locally in this thread: Messdaten vor dem Schreiben in die InfluxDB im Flashspeicher des nodes puffern
I’d like to develop some example code for the RTC part of this scenario, the goal is:
- set the RTC time via internet connection to a NTP server
- in case a timezone / UTC offset / summer time is configured how can this values survive deep sleep phase?
Starting with this example it is easy to set the local RTC via configTime()
with a time gathered from a NTP server. Local time can be put out via getLocalTime(&timeinfo)
In case you want to use timezones and daylight saving time in your (local) time stamps (btw we would not recommend this better make the magic on the server output) have a look at this tutorial
… and use configTzTime()
instead of configTime()
Now we can add deep sleep timer wake-up along this example
All seems to be ok at the first run after setting up the RTC but after the first deep sleep we see that the configured timezone has no effect. Seems that RTC recognize time after deep sleep, but forget the timezone values. See:
Einziges was fehlt ist die Einstellung der Zeitzone. Die Zeitzone muss nach dem wakeup neu eingestellt werden.
So we have to do this via
setenv("TZ",timeZone,1); // set timezone
tzset();
The final code looks like that and works:
// libs
#include <WiFi.h>
#include "time.h"
// deep sleep
#define TIME_TO_SLEEP 10 // sleep delay (in seconds)
#define uS_TO_S_FACTOR 1000000 // factor to convert ms to s
// Wifi credentials
const char* ssid = "[your-ssid]";
const char* password = "[your-pw]";
// time server and time settings
//const char* ntpServer = "pool.ntp.org"; // NTP pool international
const char* ntpServer = "de.pool.ntp.org"; // NTP pool DE
// define timezone see https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html and https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
//const char* timeZone = "CET-1CEST,M3.5.0,M10.5.0/3"; // Central European Time (CET) / Europe/Berlin
const char* timeZone = "UTC0"; // UTC
struct tm timeinfo; // time struct
// functions
void getNtpTime(){
//connect to WiFi
Serial.printf("connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" connected");
// init, get NTP time, set RTC
configTzTime(timeZone, ntpServer);
// debug
Serial.print("get NTP time, RTC set to: ");
printLocalTime();
Serial.println();
//disconnect WiFi as it's no longer needed
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
void setTimezone(){
Serial.print("set timezone to ");
Serial.println(timeZone);
setenv("TZ",timeZone,1); // set timezone
tzset();
}
void printLocalTime(){
if(!getLocalTime(&timeinfo)){
Serial.println("failed to obtain time");
return;
}
// print time human readable
// Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
Serial.println(&timeinfo, "%Y-%m-%d %H:%M:%S");
// print epoch time
time_t epoch_ts = mktime(&timeinfo); // get epoch time from struct
Serial.println("epoch time is " + String(epoch_ts));
}
void setup(){
Serial.begin(115200);
Serial.println();
// check if RTC is set
if (!getLocalTime(&timeinfo)) {
Serial.println("RTC is not set");
// set time via NTP
getNtpTime();
}
// after deep sleep and without getNtpTime() / configTzTime() we have to set the timezone manually again see https://esp32-server.de/ntp/
setTimezone();
}
void loop(){
Serial.print("current time: ");
printLocalTime();
// delay(5 * 1000);
Serial.println("deep sleep for " + String(TIME_TO_SLEEP) + " s");
Serial.flush();
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_deep_sleep_start();
}
additional Ressources
- documentation
struct tm
https://cplusplus.com/reference/ctime/tm/ - ESP32 Arduino time operations
https://iotespresso.com/esp32-arduino-time-operations/ - ESP32 System Time System Time - ESP32 - — ESP-IDF Programming Guide latest documentation
- timezone definitions TZ Variable (The GNU C Library) and posix_tz_db/zones.csv at master · nayarsystems/posix_tz_db · GitHub