DS1307 RTC return incorrect time

While debugging a sketch I noticed that a DS1307 return incorrect time:

To get the unix time I do:

uint32_t getUnixtime()
{
  DateTime now = rtc.now();
  return now.unixtime();
}

During debug I printed out the unix time and saw this in the output:

10:48:37.833 -> time=1612930271
...
10:48:39.833 -> time=2147471113
                       ^^^^^^^^^^^
...
10:48:39.953 -> time=1612930273

Anyone seen this before? Why do this happen? Bad RTC?

I use the RTClib from Adafruit.

It could also be a memory scribble, but you haven't posted all your code so it is difficult to see the wider picture.

OK.
I'll will examine the code (about 10000 lines) and see if this could be the case.

Make a small test sketch and do rtc.now() a few times per second. Make it automatic, so test if the value is too far off and print the wrong value. Then you know for sure that there is nothing wrong with that part. I'm already pretty sure that part is okay.

I have converted that number into a time and date, but there is nothing in common with the normal time and date. There is also no bitwise similarity. Then I checked my crystal ball and it tells me that countrypaul is right.

Uploaded this code to the controller (a MEGA2560):

#include <RTClib.h>

RTC_DS1307 rtc;

void setup() 
{
  Serial.begin(9600);
  Serial.println(F("\n\nInitializing"));

  if (!rtc.begin()) {
    Serial.println(F("RTC begin failed"));
    while (true) ;
  }

  if (!rtc.isrunning()) {
    Serial.println(F("RTC not running."));
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop() 
{
  static uint32_t last = 0L;
  
  DateTime    now = rtc.now();

  uint32_t utime = now.unixtime();
  if (0L != last) {
    uint32_t d = utime - last;
    if (10L < d) {
      Serial.print(F("Time error: "));
      Serial.print(last);
      Serial.print(F(" -> "));
      Serial.println(utime);

    }
  }
  last = utime;
}

The output was:

18:28:40.660 -> 
18:28:40.660 -> 
18:28:40.660 -> Initializing
18:28:43.220 -> Time error: 1612958014 -> 2130096454
18:28:43.220 -> Time error: 2130096454 -> 1612958014
18:28:50.820 -> Time error: 1612958022 -> 2130104785
18:28:50.860 -> Time error: 2130104785 -> 1612958022

Tried two different RTCs.

I am flabbergasted :o
That data is interesting, it is not completely random. However, it is not a fixed offset.
2130096454 (0x7EF6B146) - 1612958014 (0x6023C93E) = 517138440 (0x1ED2E808)
2130104785 (0x7EF6D1D1) - 1612958022 (0x6023C946) = 517146763 (0x1ED3088B)

Could you add a delay of at least 10ms at the end of the loop() ? To give the I2C bus and the DS1307 some idle time.

I checked open en closed Issues and Pull requests: GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC Arduino library.
Could this be the same problem ? DS3231 not correctly reading date · Issue #71 · adafruit/RTClib · GitHub.

Where did you buy that module ? Is it a DS1307 or a compatible chip or a counterfeit ?

I think this is a I2C bus problem. There are other units on the bus and when disconnecting this I did not detect any errors.

I then added more and more units using short cables. It seem to work now. I hope it will continue to do so :slight_smile:

Thanks for the replies.

BTW, the chip on the module say DS1307. It's a cheap one from Ali Express.

This was more weird than I thought.

It turned out that this problem occurred when I applied +5V on the "Heating wire" input (diagram below). And that even if the controller did nothing else than checking the RTC (read: did not send any signals to the PCF on this boards (total of 3 of them)).

So I will refactor the design on the boards trying to eliminate noise.

I'm glad you found the problem :smiley:

I wrote this: "How to make a reliable I2C bus", and even I did not recognize it as a I2C bus problem :confused:
Does that page help to make the I2C bus better ?

The library does not check if data was actually received: https://github.com/adafruit/RTClib/blob/master/RTClib.cpp#L864.

Koepel:
I'm glad you found the problem :smiley:

I wrote this: "How to make a reliable I2C bus", and even I did not recognize it as a I2C bus problem :confused:
Does that page help to make the I2C bus better ?

The library does not check if data was actually received: https://github.com/adafruit/RTClib/blob/master/RTClib.cpp#L864.

Thanks for the link. Useful page, but not much news for me here, since I already know most of it. But the "Measuring the total sink current" was new for me.

During debugging this problem I found out that the RTC has 3k3 pull-ups on the PCB. That is much lower pull-ups compared to what I have used in other designs.

The hardware and software has been running through night without the heating power connected. So far no errors has been detected.

I have modified the design. I have added opto-couplers instead of connecting the output pin from the relay to the PCF. But still the problem with incorrect time from the RTC occurs when the heating power is connected. But not as often as before.

I'm going crazy soon :wink: can't imagine what is going on. It must be related to the heating power but I cannot see any spikes there (I ran a FFT analyzes using a scope on the line). The heating power supply and the power supply for the controller and other components are equal.

New design:

What else is connected to the I2C bus ? Can you make a photo of the project ? There must be an Arduino and a DS1307 somewhere. How many pullup resistors are there ? Are there wires or cables between the devices on the I2C bus ? For example between the Arduino and the heating module. Is a SCL wire next to a SDA wire ? Can you give a link to those relays so I can check the coil current, and so on, and so on.

When the problem occurs when the heating is turned on, that does not mean that the problem is there. I would like to know everything, every I2C thing, every ground thing.

The current through the coils of the relays is going into the same GND as the GND of the I2C bus and that is put into a cable ? The I2C bus is a open-drain bus, therefor the signals are weak. The I2C bus is designed to be used on the same pcb board inside a television. As soon as you put a relay in the circuit without using a optocoupler for the relay coil, then you are pushing your luck.

A spike can be so high frequency, that a oscilloscope does not see it. A oscilloscope can also not "see" ground currents. You can assume there is much more going on then what you can see.

Adafruit has a I2C bus isolator: Adafruit ISO1540 Bidirectional I2C Isolator [STEMMA QT / Qwiic] : ID 4903 : $8.95 : Adafruit Industries, Unique & fun DIY electronics and kits.
To make that work, you may not connect the grounds of both circuits, the grounds should be seperated.

Beside this, the DS1307 library should test if data was received from the DS1307.

A lot is connected. Over time I have made small development board that can be connected together using I2C bus, which I use for this test. I have never seen such a problem like this before.

The mega2560 board contain the RTC on the I2C bus. It also have a SD card and a 8 digit 7-segment display.
On the I2C bus from the mega2560 board, there is a 5x4 keypad using MCP23017, two LCD2004 and a TCA9546 I2C MUX. The I2C mux has four channels. The three first is used to each of the test board (see previous posted diagram). Channel 4 is used for a 16 channel ADC converter using a MCP23017, a PCF8574 and a ADS1115.

I just added a "dual LC filter" (2x 1mH + 3x 1000uF) on the power supply connected to the "Heating power" input. It seems to work but have not tested it over time yet (doing so right now).

Also spoke with a former college, who work as an electrician. He suggested that the heating power supply generate a lot of noise. And I'm more or less sure that this is the case. However, since the two circuits now not longer have contact with each other I thought the problem should disappear. Seems like that was a wrong assumption.

The I2C bus is not meant for that. The I2C bus is not that kind of "bus". This is something for Serial or RS-485.

I think TCA9546 amplifies the signals. That means that the main I2C bus and every sub-I2C bus needs to have pullup resistors. You also have to check all the pullup resistors to be sure that it is not too much pullup.

I see a lot of flat-ribbon cables. Are there cables with SDA and SCL next to each other ? You should not do that, not even for 10cm.
When the flat ribbon cable is used for other signals, that might be a problem as well. With such a project, the flat-ribbon cable should have GND wire between the signals.

See page 60 of the I2C standard: https://www.nxp.com/docs/en/user-guide/UM10204.pdf. The SDA and SCL should not be next to each other.
The Sparkfun Qwiic bus: they did it wrong.
The DFRobot Gravity I2C bus: they did it wrong.
The Adafruit Stemma I2C bus: they did it wrong.
You see the problem ? They all got very excited by the word "bus" and they didn't think about the weak and wonky signal that I2C is.

Is everything on the I2C bus with 5V ?

Can you try that empty sketch (with only Wire.begin) and measure the shortcut current for every part of the I2C bus for both SDA and SCL. One before the mux and four after the mux, that is a total of 10 currents.
When they are <1mA, then the bus is too high impedance.
When they are >3mA, then it is not according to the I2C standard.

In the end, your project might not work. The I2C bus is not meant for that.

Koepel:
The I2C bus is not meant for that. The I2C bus is not that kind of "bus". This is something for Serial or RS-485.

Well, I and other have managed to use I2C over several meters. I did one test with over 20 meter cable (An uno controlling a 1604 LCD at the other end). Worked fine for days.

Koepel:
I think TCA9546 amplifies the signals. That means that the main I2C bus and every sub-I2C bus needs to have pullup resistors. You also have to check all the pullup resistors to be sure that it is not too much pullup.

The RTC has 3k3 pull-ups (controller side of the TCA) and each of the test boards has 4k7 pull-ups. and the ADC board has 5k6 pull-ups (both on each channel of the TCA). So pull-ups should be fine.

Koepel:
I see a lot of flat-ribbon cables. Are there cables with SDA and SCL next to each other ? You should not do that, not even for 10cm.
When the flat ribbon cable is used for other signals, that might be a problem as well. With such a project, the flat-ribbon cable should have GND wire between the signals.

SDA and SCL is not side by side. I have used longer flat ribbon cables before without any problems. The longest I have is about 50 cm.

Koepel:
See page 60 of the I2C standard: https://www.nxp.com/docs/en/user-guide/UM10204.pdf. The SDA and SCL should not be next to each other.
The Sparkfun Qwiic bus: they did it wrong.
The DFRobot Gravity I2C bus: they did it wrong.
The Adafruit Stemma I2C bus: they did it wrong.
You see the problem ? They all got very excited by the word "bus" and they didn't think about the weak and wonky signal that I2C is.

I know about that, yes :slight_smile:

Koepel:
Is everything on the I2C bus with 5V ?

Yes.

Koepel:
Can you try that empty sketch (with only Wire.begin) and measure the shortcut current for every part of the I2C bus for both SDA and SCL. One before the mux and four after the mux, that is a total of 10 currents.
When they are <1mA, then the bus is too high impedance.
When they are >3mA, then it is not according to the I2C standard.

In the end, your project might not work. The I2C bus is not meant for that.

That was a useful tip. I will do that.

Everything works fine until the heating power supply is connected.

I just replaced the PWM for the heating supply with a laboratory-style power supply (not a PWM based). It seems to be more stable. Only one "RTC time error".

So I think the problem is noise from the PWM.

The final project will use ring core transformers to power the heating wires.

thehardwareman:
Well, I and other have managed to use I2C over several meters. I did one test with over 20 meter cable (An uno controlling a 1604 LCD at the other end). Worked fine for days.

That is not good enough. Your project is not just a wire over 20 meters.

thehardwareman:
So I think the problem is noise from the PWM.

Trying to find how that influences the I2C bus can be hard. I think you still have to check the I2C bus and ground currents and make the I2C bus better, so it can deal with a little noise.
The PWM noise can go via a power adapter to the mains and via an other power adapter to the Arduino. Or wireless if you have a ground loop. Keeping the noise away with optocouplers is just a start.

When my I2C bus fails once a year, then I climb into the curtains screaming: "why?" :wink: If you have one error without the PWM, then it is a serious problem, and not just a PWM noise problem.

It is the heating power supply that generate noise. With a non-PWM power no errors has been detected.

Since the problem occurs only when the output of the second PWM is connected to the test boards (and not when disconnected but still turned on), the noise must come through the 5V output.

This reminds me about the problem that Rockheim had several years ago. The outside wall has programmable LEDs (more than 13000) and the power supplies used generated so much noise that it affected the communication system onboard aircraft's that was going to land on the airport nearby.

They have to turn the lights off and fix it.

Koepel:
I see a lot of flat-ribbon cables. Are there cables with SDA and SCL next to each other ? You should not do that, not even for 10cm.
When the flat ribbon cable is used for other signals, that might be a problem as well. With such a project, the flat-ribbon cable should have GND wire between the signals.

I have read about SDA and SCL should never be side by side on a flat ribbon cable. But guess what I found while searching for a good image of the connector I use... Look here and see how they have placed SDA and SCL next to each other!

BTW, what about the Vcc line and SDA/SCL? I cannot remember reading anything about that.

thehardwareman:
Look here

Ew! that's ugly.

When you have a GND, put it in between SDA and SCL. When you have a GND and VCC put them both between SDA and SCL. That is what the I2C document says on page 60.
They assume that VCC is decoupled, and behaves just like the GND for high frequencies.

When GND and VCC wires are next to each other, then they are inductive coupled. A current peak that goes to a device via the VCC wire should return in the GND wire. It must be exactly the same current peak in reverse. Then the VCC and GND wire do not spread a lot of noise because they are coupled in the cable.

That is why grounding is a craftsmanship on its own.

Yes, it was ugly.

Thanks for the info. :slight_smile: