Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make use of ESP32 internal RTC to setup Epoch time? #3641

Closed
ghost opened this issue Jan 16, 2020 · 20 comments
Closed

How to make use of ESP32 internal RTC to setup Epoch time? #3641

ghost opened this issue Jan 16, 2020 · 20 comments
Labels
Status: Stale Issue is stale stage (outdated/stuck)

Comments

@ghost
Copy link

ghost commented Jan 16, 2020

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?

@lbernstone
Copy link
Contributor

lbernstone commented Jan 16, 2020

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?

@chegewara
Copy link
Contributor

setTime(epoch)
epoch = now()

@everslick
Copy link
Contributor

maybe a misunderstanding? RTC != real time clock like DS3231 !!!

@chegewara
Copy link
Contributor

chegewara commented Jan 23, 2020

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
  }

@a-c-sreedhar-reddy
Copy link
Contributor

a-c-sreedhar-reddy commented Jan 23, 2020

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)

@ghost
Copy link
Author

ghost commented Jan 24, 2020

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".

@a-c-sreedhar-reddy
Copy link
Contributor

What I do is update for every 10 loops. I am not sure whats the correct way to fix this.

@lbernstone
Copy link
Contributor

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.

@chegewara
Copy link
Contributor

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.

@chegewara
Copy link
Contributor

@Gopal123456789 You asked how to use internal RTC, you got the answer. Now about accuracy:
https://www.esp32.com/viewtopic.php?t=3715#p17038

@stickbreaker
Copy link
Contributor

@Gopal123456789 The RTC need an external 32.768KHz crystal.
ESP32 Hardware doc
esp32 rtc circuit

Chuck.

@ghost
Copy link
Author

ghost commented Jan 28, 2020

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

@chegewara
Copy link
Contributor

chegewara commented Jan 28, 2020

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

@ghost
Copy link
Author

ghost commented Jan 30, 2020

Thank you chegewara.

@stale
Copy link

stale bot commented Mar 30, 2020

[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 stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Mar 30, 2020
@stale
Copy link

stale bot commented Apr 13, 2020

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.

@stale stale bot closed this as completed Apr 13, 2020
@mohsendianati
Copy link

@Gopal123456789 The RTC need an external 32.768KHz crystal.
ESP32 Hardware doc
esp32 rtc circuit

Chuck.

Using external xtal is not mandatory. It increases both accuracy and current consumption. It's possible to configure internal clock for RTC.

@gitcnd
Copy link

gitcnd commented Jul 17, 2022

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

@Gendiaaa
Copy link

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

@Gendiaaa
Copy link

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 *****

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Stale Issue is stale stage (outdated/stuck)
Projects
None yet
Development

No branches or pull requests

8 participants