Closed ghost closed 4 years ago
The default timer system uses both the RTC and the APB timers to track the internal time. It is possible to force the system to use only the RTC for time keeping (config). This requires recompiling the libraries, but I am not even sure arduino would function if you did so. Why don't you explain what you would like to achieve by doing so? Perhaps just this?
setTime(epoch)
epoch = now()
maybe a misunderstanding? RTC != real time clock like DS3231 !!!
This is code i am using to get time from NTP and set local time (internal RTC) and DS1307:
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
// get NTP time every time connect to wifi, not necessary but wont hurts
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
struct tm timeinfo;
if (getLocalTime(&timeinfo)) {
timeAdjusted = true;
setTime(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec,
timeinfo.tm_mday, timeinfo.tm_mon+1,timeinfo.tm_year - 100); // <--- set internal RTC
RTC.set(now()); // <--- read internal RTC (epoch) with now() and set DS1307
}
Hi @chegewara. can you try this
if (getLocalTime(&timeinfo)) {
timeAdjusted = true;
time_t now;
time(&now);
RTC.set(now); // <--- read internal RTC (epoch) with now() and set DS1307
}
Got it from https://github.com/espressif/arduino-esp32/issues/935#issuecomment-353094810
I have seen in the library, the now() function actually runs millis() to increment count. Using the time.h library and now() function, I kept my ESP 32 over night after once getting EPOCH from NTP server. After getting the EPOCH once I turned the wifi off and in the morning after about 12 hrs, I found that the time has actually elapsed by 30 minutes. So what I can see now is there is no such internal RTC which works like an external RTC(like DS3231 !!!) generally which runs on battery, as said by "everslick".
What I do is update for every 10 loops. I am not sure whats the correct way to fix this.
As I mentioned, the time keeping is based on the APB clock. This, in turn, is based on an external oscillator. I think the ones used by espressif are probably +-1%, which is 864 seconds over a day. If you want accuracy, use a purpose built ASIC. The device was built around network connectivity, and it is simple to sync your time over the network.
Hi @chegewara. can you try this
if (getLocalTime(&timeinfo)) { timeAdjusted = true; time_t now; time(&now); RTC.set(now); // <--- read internal RTC (epoch) with now() and set DS1307 }
Got it from #935 (comment)
I dont have issues with my code, it works exactly as intended. It was exaampple to show how to use internal RTC with now() to get epoch and how to set internal RTC with NTP call.
@Gopal123456789 You asked how to use internal RTC, you got the answer. Now about accuracy: https://www.esp32.com/viewtopic.php?t=3715#p17038
@Gopal123456789 The RTC need an external 32.768KHz crystal. ESP32 Hardware doc
Chuck.
Thank you all of you for your help. @chegewara, Can you please tell me which library do you use for the example code you have given, for the below lines? Or give a link to the library?
setTime(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, timeinfo.tm_mday, timeinfo.tm_mon+1,timeinfo.tm_year - 100); // <--- set internal RTC
RTC.set(now()); // <--- read internal RTC (epoch) with now() and set DS1307
https://github.com/PaulStoffregen/Time https://github.com/PaulStoffregen/DS1307RTC.git
PS in Time library is Time.h header file, which is causing conflict on esp32, i had to rename it
Thank you chegewara.
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.
@Gopal123456789 The RTC need an external 32.768KHz crystal. ESP32 Hardware doc
Chuck.
Using external xtal is not mandatory. It increases both accuracy and current consumption. It's possible to configure internal clock for RTC.
My code that works:-
/* Constructor for the RTC on the logging shield. */
DFRobot_DS1307 DS1307;
char daynames[]="SUN\0MON\0TUE\0WED\0THU\0FRI\0SAT\0";
// Set the ESP32 time from the RTC.
bool StartRTC() { // See http://www.rinkydinkelectronics.com/resource/DS1307/DS1307.pdf
if( !(DS1307.begin()) ){
Serial.println(F("Communication with DS1307 RTC device failed"));
return 1;
}
struct dsTimeStruct {
uint16_t tm_sec; /* seconds, range 0 to 59 */
uint16_t tm_min; /* minutes, range 0 to 59 */
uint16_t tm_hour; /* hours, range 0 to 23 */
uint16_t tm_wday; /* day of the week, range 0 to 6 */
uint16_t tm_mday; /* day of the month, range 1 to 31 */
uint16_t tm_mon; /* month, range 1 to 12 (not 0 to 11!) */
uint16_t tm_year; /* The number of years since 1900 */
uint16_t tm_yday; /* day in the year, range 0 to 365 */
uint16_t tm_isdst; /* daylight saving time */
} dstm ={0};
DS1307.getTime((uint16_t *)&dstm); //dstm.tm_mon--; // The month on the DS1307 is 1-12.
Serial.printf("DS1307 time: %s %4d/%02d/%02d %02d:%02d:%02d UTC\r\n", // DS1307 time: SUN 2022/07/17 13:06:10 UTC
&daynames[dstm.tm_wday*4], //Weekday &daynames[(getTimeBuff[3])*4], //Weekday [3]
dstm.tm_year, // Year [6]
dstm.tm_mon, // Month [5]
dstm.tm_mday, // Day [4]
dstm.tm_hour, // Hours dstm.dsRaw[2]
dstm.tm_min, // Mins dstm.dsRaw[1]
dstm.tm_sec // seconds dstm.dsRaw[0]
);
time_t seconds;
time(&seconds); // Put the time into seconds
struct tm *esptm;
esptm=gmtime(&seconds);
Serial.printf("ESP32 internal time: %s",asctime(esptm)); // ESP32 internal time: Thu Jan 1 00:00:00 1970
//DS1307 format is not same as linux ( they put the tm_wday in the middle, and don't have yday and isdst).
struct tm newdstm; newdstm.tm_sec =dstm.tm_sec; newdstm.tm_min =dstm.tm_min; newdstm.tm_hour=dstm.tm_hour;
newdstm.tm_wday=dstm.tm_wday; newdstm.tm_mday=dstm.tm_mday; newdstm.tm_mon =dstm.tm_mon-1; newdstm.tm_year=dstm.tm_year-1900;
// Serial.printf("newdstm time: %s",asctime(&newdstm)); // newdstm time: Mon Jul 17 13:09:32 2022
struct timeval dstv = { .tv_sec = mktime(&newdstm), .tv_usec = 0}; // &dstm.tm_ds
settimeofday(&dstv, NULL);
time(&seconds); // Put the updated-above time into seconds
esptm=gmtime(&seconds); // Convert epoc-based to D/M/Y...
Serial.printf("new ESP32 internal time: %s",asctime(esptm)); // new ESP32 internal time: Sun Jul 17 13:14:29 2022
return 0;
} // StartRTC
My code that works:-
/* Constructor for the RTC on the logging shield. */ DFRobot_DS1307 DS1307; char daynames[]="SUN\0MON\0TUE\0WED\0THU\0FRI\0SAT\0"; // Set the ESP32 time from the RTC. bool StartRTC() { // See http://www.rinkydinkelectronics.com/resource/DS1307/DS1307.pdf if( !(DS1307.begin()) ){ Serial.println(F("Communication with DS1307 RTC device failed")); return 1; } struct dsTimeStruct { uint16_t tm_sec; /* seconds, range 0 to 59 */ uint16_t tm_min; /* minutes, range 0 to 59 */ uint16_t tm_hour; /* hours, range 0 to 23 */ uint16_t tm_wday; /* day of the week, range 0 to 6 */ uint16_t tm_mday; /* day of the month, range 1 to 31 */ uint16_t tm_mon; /* month, range 1 to 12 (not 0 to 11!) */ uint16_t tm_year; /* The number of years since 1900 */ uint16_t tm_yday; /* day in the year, range 0 to 365 */ uint16_t tm_isdst; /* daylight saving time */ } dstm ={0}; DS1307.getTime((uint16_t *)&dstm); //dstm.tm_mon--; // The month on the DS1307 is 1-12. Serial.printf("DS1307 time: %s %4d/%02d/%02d %02d:%02d:%02d UTC\r\n", // DS1307 time: SUN 2022/07/17 13:06:10 UTC &daynames[dstm.tm_wday*4], //Weekday &daynames[(getTimeBuff[3])*4], //Weekday [3] dstm.tm_year, // Year [6] dstm.tm_mon, // Month [5] dstm.tm_mday, // Day [4] dstm.tm_hour, // Hours dstm.dsRaw[2] dstm.tm_min, // Mins dstm.dsRaw[1] dstm.tm_sec // seconds dstm.dsRaw[0] ); time_t seconds; time(&seconds); // Put the time into seconds struct tm *esptm; esptm=gmtime(&seconds); Serial.printf("ESP32 internal time: %s",asctime(esptm)); // ESP32 internal time: Thu Jan 1 00:00:00 1970 //DS1307 format is not same as linux ( they put the tm_wday in the middle, and don't have yday and isdst). struct tm newdstm; newdstm.tm_sec =dstm.tm_sec; newdstm.tm_min =dstm.tm_min; newdstm.tm_hour=dstm.tm_hour; newdstm.tm_wday=dstm.tm_wday; newdstm.tm_mday=dstm.tm_mday; newdstm.tm_mon =dstm.tm_mon-1; newdstm.tm_year=dstm.tm_year-1900; // Serial.printf("newdstm time: %s",asctime(&newdstm)); // newdstm time: Mon Jul 17 13:09:32 2022 struct timeval dstv = { .tv_sec = mktime(&newdstm), .tv_usec = 0}; // &dstm.tm_ds settimeofday(&dstv, NULL); time(&seconds); // Put the updated-above time into seconds esptm=gmtime(&seconds); // Convert epoc-based to D/M/Y... Serial.printf("new ESP32 internal time: %s",asctime(esptm)); // new ESP32 internal time: Sun Jul 17 13:14:29 2022 return 0; } // StartRTC
is this can be done with DS3231 could you please help to do the same but with ds3231 which the one available here
My code that works:-
/* Constructor for the RTC on the logging shield. */ DFRobot_DS1307 DS1307; char daynames[]="SUN\0MON\0TUE\0WED\0THU\0FRI\0SAT\0"; // Set the ESP32 time from the RTC. bool StartRTC() { // See http://www.rinkydinkelectronics.com/resource/DS1307/DS1307.pdf if( !(DS1307.begin()) ){ Serial.println(F("Communication with DS1307 RTC device failed")); return 1; } struct dsTimeStruct { uint16_t tm_sec; /* seconds, range 0 to 59 */ uint16_t tm_min; /* minutes, range 0 to 59 */ uint16_t tm_hour; /* hours, range 0 to 23 */ uint16_t tm_wday; /* day of the week, range 0 to 6 */ uint16_t tm_mday; /* day of the month, range 1 to 31 */ uint16_t tm_mon; /* month, range 1 to 12 (not 0 to 11!) */ uint16_t tm_year; /* The number of years since 1900 */ uint16_t tm_yday; /* day in the year, range 0 to 365 */ uint16_t tm_isdst; /* daylight saving time */ } dstm ={0}; DS1307.getTime((uint16_t *)&dstm); //dstm.tm_mon--; // The month on the DS1307 is 1-12. Serial.printf("DS1307 time: %s %4d/%02d/%02d %02d:%02d:%02d UTC\r\n", // DS1307 time: SUN 2022/07/17 13:06:10 UTC &daynames[dstm.tm_wday*4], //Weekday &daynames[(getTimeBuff[3])*4], //Weekday [3] dstm.tm_year, // Year [6] dstm.tm_mon, // Month [5] dstm.tm_mday, // Day [4] dstm.tm_hour, // Hours dstm.dsRaw[2] dstm.tm_min, // Mins dstm.dsRaw[1] dstm.tm_sec // seconds dstm.dsRaw[0] ); time_t seconds; time(&seconds); // Put the time into seconds struct tm *esptm; esptm=gmtime(&seconds); Serial.printf("ESP32 internal time: %s",asctime(esptm)); // ESP32 internal time: Thu Jan 1 00:00:00 1970 //DS1307 format is not same as linux ( they put the tm_wday in the middle, and don't have yday and isdst). struct tm newdstm; newdstm.tm_sec =dstm.tm_sec; newdstm.tm_min =dstm.tm_min; newdstm.tm_hour=dstm.tm_hour; newdstm.tm_wday=dstm.tm_wday; newdstm.tm_mday=dstm.tm_mday; newdstm.tm_mon =dstm.tm_mon-1; newdstm.tm_year=dstm.tm_year-1900; // Serial.printf("newdstm time: %s",asctime(&newdstm)); // newdstm time: Mon Jul 17 13:09:32 2022 struct timeval dstv = { .tv_sec = mktime(&newdstm), .tv_usec = 0}; // &dstm.tm_ds settimeofday(&dstv, NULL); time(&seconds); // Put the updated-above time into seconds esptm=gmtime(&seconds); // Convert epoc-based to D/M/Y... Serial.printf("new ESP32 internal time: %s",asctime(esptm)); // new ESP32 internal time: Sun Jul 17 13:14:29 2022 return 0; } // StartRTC
your code is not working as it should be for me DS1307 time: MON 2000/01/01 00:53:42 UTC ESP32 internal time: Thu Jan 1 00:00:01 1970 new ESP32 internal time: Sat Jan 1 00:53:42 2000 Arduino IoT Cloud - configuration info
As mentioned in the datasheet of ESP32, I was trying to make use of the internal RTC. But not able to find any example or APIs related to it. Is there any way to access the RTC?