My second RTC module, another broken one [Solved]

Hello!

For a long time I want to make a common digital clock with Arduino-DS3231 RTC-TM1637. Personally, I did not find on the internet a program that runs in real time, I saw that the clock resets back to the moment when the program was compiled if the power drops. It's frustrating, I invested some money in a second RTC DS3231 module with a battery and a display, and in vain, the circuit still does not work properly.
The problem is that this program works halfway, the time is delayed by about 15 minutes compared to the actual real time, I really don't know how and why. It is frustrating.


#include "TM1637.h"
#define CLK 9//Pins for TM1637
#define DIO 8
TM1637 tm1637(CLK,DIO);

#include <Wire.h>
#include "RTClib.h"
// SDA->A4 SCL->A5
RTC_DS1307 RTC;
int hh, mm;

void setup()
{
tm1637.init();
tm1637.set(5);
//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
Wire.begin();
RTC.begin();
// Check if RTC is connected correctly:
/if (! RTC.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
/
// Check if the RTC lost power and if so, set the time:
/if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
//RTC.adjust(DateTime(DATE, TIME));
RTC.adjust(DateTime(2021, 5, 8, 3, 0, 0));
}
/
}//end "setup()"

void loop(){
DateTime now = RTC.now();
hh = now.hour(), DEC;
mm = now.minute(), DEC;

tm1637.point(POINT_ON);
if ((hh/10) == 0) tm1637.display(0,17);
else
tm1637.display(0,hh/10); // hour
tm1637.display(1,hh%10);
tm1637.display(2,mm/10); // minutes
tm1637.display(3,mm%10);
delay(500);
tm1637.point(POINT_OFF);
if ((hh/10) == 0) tm1637.display(0,17);
else
tm1637.display(0,hh/10); // hour
tm1637.display(1,hh%10);
tm1637.display(2,mm/10); // minutes
tm1637.display(3,mm%10);
delay(500);
}// end loop()

 

I don't think it helps to have a fixed reset of the clock in your code. It has to be a one time thing.

I'd write something that sets the clock when triggered from serial and then replace it with the code that just does the display once the time is set adequately.

This line is to be used only once.
After the initial run of the code, comment the line and re-upload the code.
For changes of the time you will have to come up with somithing less crude.

I tried to upload like this:
if (! RTC.isrunning ()) {
Serial.println ("RTC is NOT running!");
RTC.adjust (DateTime (2021, 5, 8, 15, 47, 0));
}
Then with the commented line:
if (! RTC.isrunning ()) {
Serial.println ("RTC is NOT running!");
//RTC.adjust(DateTime(2021, 5, 8, 15, 47, 0));
}
The clock is 10 minutes late now, but it keeps its time if I stop powering up the Arduino.

So you have to be fast, or adjust the PC time.

For the adjustment you will have to program something.

I suspect that your issue is that when you send the new version with the commented out setting, the Arduino resets and runs the old code before being overwritten.

I tried to upload like this:

void setup ()

{

tm1637.init ();

tm1637.set (5);

// BRIGHT_TYPICAL = 2, BRIGHT_DARKEST = 0, BRIGHTEST = 7;

Wire.begin ();

RTC.begin ();

RTC.adjust (DateTime (__ DATE__, TIME)); // tricky

} // end "setup ()"

Then with the commented line:

void setup ()

{

tm1637.init ();

tm1637.set (5);

// BRIGHT_TYPICAL = 2, BRIGHT_DARKEST = 0, BRIGHTEST = 7;

Wire.begin ();

RTC.begin ();

// RTC.adjust (DateTime (__ DATE__, TIME)); // tricky

} // end "setup ()"

The clock is about 4 seconds late now, but it keeps its time if I don't power up the Arduino anymore.

If you want to use any sort of profanity I fully recommend facebook.
That sort of wording is more likely to get you banned here.

Nothing to do with your problem, but the module you use has a lame battery charging circuit which should be disabled

DS3231 diode resistor

should google you the skinny on this matter.

a7

Did I do something wrong ?

Hi, @cristian10001

To add code please click this link;

Also pressing CTRL -T will auto format your code, putting indents to make your code easier to read.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

I understand. Thanks.

Why?

@cristian10001: I have a couple of the modules you are using (with the DS3231M chip), and for what I know they run a bit slow so within a week they are a couple (5-10) of seconds behind. By modifying the aging register on them, my modules have been keeping the time for some weeks now.

Obviously, I have no idea about that register.

Try this
RTC_DS3231 rtc;

The OP has some success with a perfectly fine RTC_DS3231 object named RTC.

RTC_DS1307 RTC;

changing the name of the object will have zero effect on anything.

Unless you just meant try pretending it's a DS1307 edit: No, IC that is what you are getting at:

    RTC_DS1307 rtc;

which seems more likely.

Neither would this have any (good) effect I can know.

The last report:

seems to imply the problem is solved.

BTW the out-of-the-box accuracy of the DS3231 should mean quite good time-keeping without messing with the aging register. I don't know why @Danois90 isn't enjoying that. I haven't checked the modules I have for accuracy, though, and they were suspiciously very way too cheap inexpensive, perhaps they've used some kind of factory reject DS3231s. Or counterfeits.

a7

I kept trying to change that object from RTC to rtc or vice versa. Now I will see if it decreases with the accuracy of time, as > Danois90 says.

@alto777: I'm not enjoying that my (cheap knock-off) modules are not very accurate. I do, however, enjoy the fact that the aging register can be used to calibrate the modules to an accuracy that is much better than the default.

The following code works for getting/setting the aging register of a DS3231M module. I cannot guarantee that this will work with other modules. The RTC module and Wire objects must be initialized and the code does not include any error checking/handling.

#define DS3231_AGING_OFFSET 0x10

int8_t ds3231_get_aging_offset()
{
  //Returns the aging offset, defaults to 0
  Wire.beginTransmission(DS3231_ADDRESS);
  Wire.write(DS3231_AGING_OFFSET);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_ADDRESS, 1);
  return Wire.read() & 0xFF;
}

void ds3231_set_aging_offset(int8_t offset, bool force_conversion = true)
{
  //offset = a value from -127 .. 127
  //force_conversion = force the clock to use the value immediately
  //Negative values will speed up the module.
  //A change of +/- 1 will adjust the time base by 0.12ppm
  Wire.beginTransmission(DS3231_ADDRESS);
  Wire.write(DS3231_AGING_OFFSET);
  Wire.write(offset);
  Wire.endTransmission();
  if (force_conversion)
  {
    Wire.beginTransmission(DS3231_ADDRESS);
    Wire.write(DS3231_CONTROL);
    Wire.endTransmission();
    Wire.requestFrom(DS3231_ADDRESS, 1);
    uint8_t ctrl = Wire.read() | (1 << 5);
    Wire.beginTransmission(DS3231_ADDRESS);
    Wire.write(DS3231_CONTROL);
    Wire.write(ctrl);
    Wire.endTransmission();
  }
}

P.S: The setting code should only be performed when the time of the clock is adjusted due to a battery replacement or alike.

Good to know.

THX. I didn't last long enough perusing the data sheet to convince myself of this…

but typing just now… do you mean the aging offset is held in battery backed memory, or something that would survive total removal of power?

a7