DS1307 RTC breaks only when called from a thread? (ESP32 / Coding)

dev.deque
Posts: 4
Joined: Thu Jun 09, 2022 7:35 pm

DS1307 RTC breaks only when called from a thread? (ESP32 / Coding)

Postby dev.deque » Thu Jun 09, 2022 8:02 pm

Hello,
I have a LilyGo T-display with a DS1307 I2C RTC module connected. The module is working great given the example sketches. It works as expected in the setup() of my sketch. But as soon as I try to call the RTC from one of two threads, the date and time will be wrong. It'll go from a proper date and time like: "06/09/22 14:12:00." To either "165/165/2165 37:165" or close but invalid values like "06/03/2022 12:35:36." The RTC is remembering the right time between boots despite the wrong value later in the sketch.

How do I use all of this in one of the threads of the ESP32? It feels like some sort of scope problem.

Code: Select all

#include <Wire.h>
#include <RtcDS1307.h>
RtcDS1307<TwoWire> Rtc(Wire);
RtcDateTime now; // i've tried using this as global, or as a local variable, to the same result.

void setup() {
	Serial.begin(115200);
	while (!Serial) {
		delay(100);
	}
	Wire.begin(21, 22);
	Rtc.Begin();
        //.. clutter
        RtcDateTime now;
        now = Rtc.GetDateTime(); // the rtc module reports the right time/date in here 06/09/22 14:12:00. Many times if given a loop.
        xTaskCreate(loopOne, "loopOne", 2048, NULL, 1, NULL);
	xTaskCreate(loopTwo, "loopTwo", 2048, NULL, 1, NULL);
}

void loopOne(void *arg) {
	RtcDateTime now; // local
        while ( 1 ) {
                now = Rtc.GetDateTime(); //now would be 165/165/2165 37:165
                //.. clutter. long delays etc.
                // now = Rtc.GetDateTime(); //from global. same wrong value.
                delay(5);
        }
}
void loopTwo(void *arg) {
        // OR here...
        while ( 1 ) {
                RtcDateTime now = Rtc.GetDateTime(); // or like this. same wrong value.
                //.. clutter. long delays etc.
                delay(5);
        }
    }
}

void loop {
}
Thanks!

dev.deque
Posts: 4
Joined: Thu Jun 09, 2022 7:35 pm

Re: DS1307 RTC breaks only when called from a thread? (ESP32 / Coding)

Postby dev.deque » Fri Jun 10, 2022 5:44 am

I just wanted to thank you all. All of those has read this, taking their time in an effort to help others. I'm still around and it doesn't go unnoticed.

If you happen to have any ballpark suggestions - feel free! I'd be glad to test them out and report back.

ESP_Sprite
Posts: 9745
Joined: Thu Nov 26, 2015 4:08 am

Re: DS1307 RTC breaks only when called from a thread? (ESP32 / Coding)

Postby ESP_Sprite » Fri Jun 10, 2022 6:07 am

Looks like the 'Rtc' module is not re-entrant, as in, it messes up when two tasks use it at the same time. Suggest either not doing that, or using a FreeRTOS mutex to make sure only one task uses it at a time.

dev.deque
Posts: 4
Joined: Thu Jun 09, 2022 7:35 pm

Re: DS1307 RTC breaks only when called from a thread? (ESP32 / Coding)

Postby dev.deque » Fri Jun 10, 2022 5:03 pm

ESP_Sprite wrote:
Fri Jun 10, 2022 6:07 am
Looks like the 'Rtc' module is not re-entrant, as in, it messes up when two tasks use it at the same time. Suggest either not doing that, or using a FreeRTOS mutex to make sure only one task uses it at a time.
Thanks for the suggestions. I've never used mutex before. I couldn't I easily find how to implement that. I tried some tutorials but I kept getting compile errors. I don't know what libraries etc. I need for my board - if any. If you know of a solid example, please let me know?

So I tried limiting whom all is accessing the RTC and the code below is working. :D

Code: Select all

#include <Wire.h>
#include <RtcDS1307.h>

RtcDS1307<TwoWire> Rtc(Wire);

#define countof(a) (sizeof(a) / sizeof(a[0]))
void printDateTime(const RtcDateTime& dt) {
  char datestring[20];
  snprintf_P(datestring, countof(datestring), PSTR("%02u/%02u/%04u %02u:%02u:%02u"), dt.Month(),
      dt.Day(),dt.Year(),dt.Hour(),dt.Minute(),dt.Second() );
  Serial.println(datestring);
}

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    delay(100);
  }
  Wire.begin(21, 22);
  xTaskCreate(loopOne, "loopOne", 2048, NULL, 1, NULL);
  xTaskCreate(loopTwo, "loopTwo", 2048, NULL, 1, NULL);
}

void loopOne(void *arg) {
  Rtc.Begin();
  if (!Rtc.IsDateTimeValid()) {
    if (Rtc.LastError() != 0) {
      Serial.print("RTC communications error = ");
      Serial.println(Rtc.LastError());
    } else {
      Serial.println("RTC lost confidence in the DateTime!");
    }
  }
  if (!Rtc.GetIsRunning()) {
    Serial.println("RTC was not actively running, starting now");
    Rtc.SetIsRunning(true);
  }
  Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
  RtcDateTime now = Rtc.GetDateTime();
  printDateTime(now);
  
  while ( 1 ) {
    now = Rtc.GetDateTime();
    printDateTime(now);
    delay(5000);
  }
}

void loopTwo(void *arg) {
  while ( 1 ) {
    delay(1000);
  }
}

void loop() {
}
12:51:31.375 -> 06/10/2022 12:51:19
12:51:36.382 -> 06/10/2022 12:51:24
12:51:41.394 -> 06/10/2022 12:51:29
12:51:46.368 -> 06/10/2022 12:51:34
12:51:51.375 -> 06/10/2022 12:51:39
12:51:56.382 -> 06/10/2022 12:51:44
12:52:01.389 -> 06/10/2022 12:51:49
On a side note, do I need to call

Code: Select all

Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
everytime or just when I set the time of the RTC module. Doesn't hurt either way? I'm not sure.

Thank you!

ESP_Sprite
Posts: 9745
Joined: Thu Nov 26, 2015 4:08 am

Re: DS1307 RTC breaks only when called from a thread? (ESP32 / Coding)

Postby ESP_Sprite » Sat Jun 11, 2022 1:47 am

You probably only need to call it once. Or even never, if you don't use the resulting square wave signal.

dev.deque
Posts: 4
Joined: Thu Jun 09, 2022 7:35 pm

Re: DS1307 RTC breaks only when called from a thread? (ESP32 / Coding)

Postby dev.deque » Sat Jun 11, 2022 2:09 am

ESP_Sprite wrote:
Sat Jun 11, 2022 1:47 am
You probably only need to call it once. Or even never, if you don't use the resulting square wave signal.
I don't. Thanks for all your guidance! I'm going to assume this solved.

I actually ended up using one xTaskCreate() and the loop(). My project also has an SD card module. I got the RTC to play nicely as explained. But the SD card refused to play that way. Still no luck figuring out mutex. But ... both work in the loop(). So I just use the xTaskCreate() loop for input only and loop() for sensors UI stuff. I'm making a smart solar powered irrigation project. Feels good to finally be past those issues. I bought and tested new hardware because of this issue. I thought the RTC module was faulty...

Who is online

Users browsing this forum: No registered users and 108 guests