// NTP server to request time
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = -10800; //-3
const int daylightOffset_sec = -10800; //-3
I decided to print on the serial monitor the information coming directly from the NPT before being treated by the RTC DS1302, and lo and behold: it is correct, both the date and the time.
So why is the date wrong in the RTC DS1302 information ? (time is right)
#include <ThreeWire.h>
#include <WiFi.h>
#include <RtcDS1302.h>
#include "time.h"
const char* ssid = "XXXXXXX";
const char* password = "xxxxxxx";
int ano,mes,dia,hora,minuto,segundo;
const int RstPino = 25; //pino Reset (RTC DS1302)
const int DatPino = 26; //pino Data (RTC DS1302)
const int ClkPino = 27; //pino Clock (RTC DS1302)
ThreeWire myWire(26, 27, 25); //26 data, 27 clock e 25 reset do módulo RTC DS1302
RtcDS1302<ThreeWire> Rtc(myWire);
char daysOfTheWeek[7][12] = {"Domingo", "Segunda", "Terca", "Quarta", "Quinta", "Sexta", "Sabado"};
// NTP server to request time
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = -3600*3;
const int daylightOffset_sec = 0;
// Initialize WiFi
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
// Function that gets time from NTP Server and syncs RTC clock
unsigned long getTime() {
struct tm timeinfo;
getLocalTime(&timeinfo);
dia = timeinfo.tm_mday;
mes = timeinfo.tm_mon;
ano = timeinfo.tm_year;
hora = timeinfo.tm_hour;
minuto = timeinfo.tm_min;
segundo = timeinfo.tm_sec;
Rtc.SetDateTime(RtcDateTime(dia,mes,ano,hora,minuto,segundo));
//disconnect WiFi as it's no longer needed
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}
void setup() {
Serial.begin(115200);
Rtc.Begin();
RtcDateTime now = Rtc.GetDateTime();
delay(20);
// Compilar com a data e a hora do sistema:
// RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__); // Variável recebe data e hora da compilação
// Rtc.SetDateTime(compiled); //informações compiladas substituem as informações anteriores
//Wifi
initWiFi();
//Time Server
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
getTime();
}
void loop() {
RtcDateTime now = Rtc.GetDateTime();
Serial.print(daysOfTheWeek[now.DayOfWeek()]);
Serial.print(',');
Serial.print(now.Day() < 10 ? "0" : "");
Serial.print(now.Day(), DEC);
Serial.print('/');
Serial.print(now.Month() < 10 ? "0" : "");
Serial.print(now.Month(), DEC);
Serial.print('/');
Serial.print(now.Year(), DEC);
Serial.print(',');
Serial.print(now.Hour() < 10 ? "0" : "");
Serial.print(now.Hour(), DEC);
Serial.print(':');
Serial.print(now.Minute() < 10 ? "0" : "");
Serial.print(now.Minute(), DEC);
Serial.print(':');
Serial.print(now.Second() < 10 ? "0" : "");
Serial.println(now.Second(), DEC);
delay(1000);
}
Why would you use an external RTC at all?
When you have internet-time you have the actual time
additionally the ESP32 has an internal RTC itself
Here is a Demo-Code that combines
connecting to WiFi but only on first power up (can be simulated through uploading the code)
synchronising with NTP-Time
by the way the WiFi-routers from AVM can be used as a local NTP-server which reacts much quicker than some external
const char* ntpServer = "fritz.box";
setting up the internal RTC of the ESP32 and then goes into deepsleep-mode to demonstrate the RTC is running and is keeping time through the deepsleep
then on second and all consecutive boots don't synchronise again with NTP
but print RTC time
/*
Here is a Demo-Code that combines
connecting to WiFi but only on first power up (can be simulated through uploading the code)
synchronising with NTP-Time
by the way the WiFi-routers from AVM can be used as a local NTP-server which reacts much quicker than some external NTP-server
setting up the internal RTC of the ESP32 and then goes into deepsleep-mode to demonstrate the RTC is running and is keeping time through the deepsleep
then on second and all consecutive boots do't synchronise again with with but print RTC time
*/
#include <WiFi.h>
#include <ESP32Time.h>
#include <time.h> // time() ctime()
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 15 /* Time ESP32 will go to sleep (in seconds) */
RTC_DATA_ATTR int bootCount = 0;
ESP32Time rtc;
ESP32Time rtc1(-3600); // offset GMT-1
ESP32Time rtc2(7200); // offset GMT+2
const unsigned long WaitBeforeSleep = 10000;
unsigned long sleepTimer;
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 2;
const char *ssid = "Your-SSID";
const char *password = "your-password";
//const char *ssid = "";
//const char *password = "";
// a lot of home-wlan-routers can be used as a NTP-server too
const char* ntpServer = "fritz.box";
const long gmtOffset_sec = 0;
const int daylightOffset_sec = 7200;
time_t now; // this is the epoch
tm myTimeInfo; // the structure tm holds time information in a more convient way
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason); break;
}
}
void setRTC() {
time(&now); // read the current time
localtime_r(&now, &myTimeInfo); // update the structure tm with the current time
int year = myTimeInfo.tm_year + 1900;
int month = myTimeInfo.tm_mon + 1;
int day = myTimeInfo.tm_mday;
int hour = myTimeInfo.tm_hour;
int minute = myTimeInfo.tm_min;
int second = myTimeInfo.tm_sec;
rtc.setTime(second, minute, hour, day, month, year);
}
void printRTC_Times() {
Serial.println(rtc.getTime("RTC0: %A, %B %d %Y %H:%M:%S")); // (String) returns time with specified format
Serial.println(rtc1.getTime("RTC1: %A, %B %d %Y %H:%M:%S")); // (String) returns time with specified format
Serial.println(rtc2.getTime("RTC2: %A, %B %d %Y %H:%M:%S")); // (String) returns time with specified format
}
void showTime() {
time(&now); // read the current time
localtime_r(&now, &myTimeInfo); // update the structure tm with the current time
Serial.print("year:");
Serial.print(myTimeInfo.tm_year + 1900); // years since 1900
Serial.print("\tmonth:");
Serial.print(myTimeInfo.tm_mon + 1); // January = 0 (!)
Serial.print("\tday:");
Serial.print(myTimeInfo.tm_mday); // day of month
Serial.print("\thour:");
Serial.print(myTimeInfo.tm_hour); // hours since midnight 0-23
Serial.print("\tmin:");
Serial.print(myTimeInfo.tm_min); // minutes after the hour 0-59
Serial.print("\tsec:");
Serial.print(myTimeInfo.tm_sec); // seconds after the minute 0-61*
Serial.print("\twday");
Serial.print(myTimeInfo.tm_wday); // days since Sunday 0-6
if (myTimeInfo.tm_isdst == 1) // Daylight Saving Time flag
Serial.print("\tDST");
else
Serial.print("\tstandard");
Serial.println();
}
void connectToWifi() {
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
BlinkHeartBeatLED(OnBoard_LED, 333);
delay(332);
Serial.print(".");
}
Serial.print("\n connected.");
Serial.println(WiFi.localIP() );
}
void synchroniseWith_NTP_Time() {
Serial.print("configTime uses ntpServer ");
Serial.println(ntpServer);
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Serial.print("synchronising time");
while (myTimeInfo.tm_year + 1900 < 2000 ) {
time(&now); // read the current time
localtime_r(&now, &myTimeInfo);
BlinkHeartBeatLED(OnBoard_LED, 100);
delay(100);
Serial.print(".");
}
Serial.print("\n time synchronsized \n");
showTime();
}
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println(__FILE__);
Serial.print( F(" compiled ") );
Serial.print(__DATE__);
Serial.print( F(" ") );
Serial.println(__TIME__);
}
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
void setup() {
Serial.begin(115200);
Serial.println("\n Setup-Start \n");
PrintFileNameDateTime();
if (bootCount < 1) {
Serial.println("bootcount < 1 new power on");
connectToWifi();
synchroniseWith_NTP_Time();
}
else {
Serial.println("not powerup");
}
bootCount++;
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
Serial.print("Going to sleep in ");
Serial.print(WaitBeforeSleep / 1000);
Serial.println(" seconds");
sleepTimer = millis();
}
void loop() {
BlinkHeartBeatLED(OnBoard_LED, 100);
if ( TimePeriodIsOver(MyTestTimer, 1000) ) {
showTime();
printRTC_Times();
}
if ( TimePeriodIsOver(sleepTimer, WaitBeforeSleep) ) {
Serial.println("execute esp_deep_sleep_start()");
Serial.print("will be back in ");
Serial.print(TIME_TO_SLEEP);
Serial.println(" seconds");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
}
Which is optimised for lowest power in deepsleep-mode
The current goes down to 15 µA in deepsleep-mode which should give a pretty long battery-lifetime
A combination of detecting is there power coming from Vin with one IO-pin and if not going to deep-sleep reducing the current to 15µA and wake-up on IO-pin state-change
could do the thing
Though the wiring-effort is the aprox. same as adding a coin-cell external RTC
Fair enough. Sure, and if you were really clever, you could also incorporate calibration and temperature compensation in software (custom because I doubt the RTC API supports it directly). The processor does have a temp sensor, right? But it would be tricky to make that happen during sleep states.
I just had this problem the other day. I think your problem is that the NTP server gives you a Unix timestamp, which is the seconds since 1 January 1970.
However, the RTC libraries will normally calculate a timestamp, which is seconds since 1st January 2000. This is more efficient, as the 8-bit register for the year is between 00-99 on the RTC.