Problem with DS3231 RTC module

Hello,

I would like to find answer here. I have problems with my DS3231 RTC. I run a code which shows a clock and display it in the LCD (16,2). But I have a problem with time. When I start a code with Arduino and clock is running after some time I see that I'm loosing seconds. In 30 minutes I lost 10 seconds (approximately). I just synchronize it manually with my PC time within seconds and starting to run, but after some time I see that my RTC clock is late comparing with computer clock. I read articles that it's possible to calibrate this device. But I am not sure if it's true and maybe there is any other way to know why ? Or is it module problem ?

Split from another topic

DO NOT hijack topics. If you have a question about your project start your own topic

Have used many DS3231s in the past, have never had a problem like this.

Most modules are well within a minute after several months of operation.

Try a new RTC.


Always:

Show us a good schematic of your circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components. Posting images:
https://forum.arduino.cc/index.php?topic=519037.0

Use CTRL T to format your code.
Attach your ‘complete’ sketch between code tags
[code]Paste your sketch here[/code]

Hello,

Sorry for posting into not correct topic of the forum.
My schematic is very basic one to have working DS3231 and LCD which you can find in the internet. Everything is working like I want. This code is used from example and a little bit modified for my purpose.

I'd like to share my code below:
Also, I've attached code in TXT file to make it more easier to to check it.

#include <LiquidCrystal.h>
#include <Wire.h>
#include "ds3231.h"


LiquidCrystal lcd(12, 11, 4, 5, 6, 7); // LCD pajungimo kontaktai


#define BUFF_MAX 128


uint8_t time[8]; // nustatomi 8 bitai laikui
char recv[BUFF_MAX]; // buferis priima max
unsigned int recv_size = 0;
unsigned long prev, interval = 1000;


//void parse_cmd(char *cmd, int cmdsize);


void setup()
{
Serial.begin(9600);
Wire.begin();
DS3231_init(DS3231_CONTROL_INTCN);
memset(recv, 0, BUFF_MAX);
Serial.println("GET time");
lcd.begin(16, 2); // LCD paleidimas
lcd.clear (); // LCD išvalymas


//Serial.println("Setting time");
//parse_cmd("T000515419112020",16); // Nustatoma esama data pirmo paleidimu
}


void loop()
{
char in;
char buff[BUFF_MAX];
unsigned long now = millis();
struct ts t;


// show time once in a while
if ((now - prev > interval) && (Serial.available() <= 0)) {
 DS3231_get(&t); //Gaunam laiką
 //parse_cmd("C",1);


 lcd.clear();
 lcd.setCursor(0, 0); // Pirmos ekrano eilutės kursoriaus vieta
 lcd.print("Data:");
 lcd.print(t.year); // Išveda į ekraną metus


 printMonth(t.mon); // Išveda i ekraną mėnesį


 lcd.print(t.mday); // Išveda į ekraną dienas


 lcd.setCursor(0, 1); //Antra ekrano eilutė
 lcd.print("Laikas:");
 lcd.print(t.hour);
 lcd.print(":");
 if (t.min < 10)
 {
   lcd.print("0");
 }
 lcd.print(t.min);
 lcd.print(":");
 if (t.sec < 10)
 {
   lcd.print("0");
 }
 lcd.print(t.sec);


 //lcd.print(' ');
 //lcd.print(tempF);
 //lcd.print((char)223);
 //lcd.print("C ");
 prev = now;
}




if (Serial.available() > 0) {
 in = Serial.read();


 if ((in == 10 || in == 13) && (recv_size > 0)) {
   parse_cmd(recv, recv_size);
   recv_size = 0;
   recv[0] = 0;
 } else if (in < 48 || in > 122) {
   ;       // ignore ~[0-9A-Za-z]
 } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
   // drop
   recv_size = 0;
   recv[0] = 0;
 } else if (recv_size < BUFF_MAX - 2) {
   recv[recv_size] = in;
   recv[recv_size + 1] = 0;
   recv_size += 1;
 }


}
}


void parse_cmd(char *cmd, int cmdsize)
{
uint8_t i;
uint8_t reg_val;
char buff[BUFF_MAX];
struct ts t;


//snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
//Serial.print(buff);


// TssmmhhWDDMMYYYY aka set time
if (cmd[0] == 84 && cmdsize == 16) {
 //T355720619112011
 t.sec = inp2toi(cmd, 1);
 t.min = inp2toi(cmd, 3);
 t.hour = inp2toi(cmd, 5);
 t.wday = inp2toi(cmd, 7);
 t.mday = inp2toi(cmd, 8);
 t.mon = inp2toi(cmd, 10);
 t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
 DS3231_set(t);
 Serial.println("OK");
} else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
 DS3231_get_a1(&buff[0], 59);
 Serial.println(buff);
} else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
 DS3231_get_a2(&buff[0], 59);
 Serial.println(buff);
} else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
 Serial.print("aging reg is ");
 Serial.println(DS3231_get_aging(), DEC);
} else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
 DS3231_set_creg(DS3231_CONTROL_INTCN | DS3231_CONTROL_A1IE);
 //ASSMMHHDD
 for (i = 0; i < 4; i++) {
   time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
 }
 byte flags[5] = { 0, 0, 0, 0, 0 };
 DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
 DS3231_get_a1(&buff[0], 59);
 Serial.println(buff);
} else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
 DS3231_set_creg(DS3231_CONTROL_INTCN | DS3231_CONTROL_A2IE);
 //BMMHHDD
 for (i = 0; i < 4; i++) {
   time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
 }
 byte flags[5] = { 0, 0, 0, 0 };
 DS3231_set_a2(time[0], time[1], time[2], flags);
 DS3231_get_a2(&buff[0], 59);
 Serial.println(buff);
} else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
 Serial.print("temperature reg is ");
 Serial.println(DS3231_get_treg(), DEC);
} else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
 reg_val = DS3231_get_sreg();
 reg_val &= B11111100;
 DS3231_set_sreg(reg_val);
} else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
 reg_val = DS3231_get_addr(0x5);
 Serial.print("orig ");
 Serial.print(reg_val, DEC);
 Serial.print("month is ");
 Serial.println(bcdtodec(reg_val & 0x1F), DEC);
} else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
 DS3231_set_aging(0);
} else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
 Serial.print("status reg is ");
 Serial.println(DS3231_get_sreg(), DEC);
} else {
 Serial.print("unknown command prefix ");
 Serial.println(cmd[0]);
 Serial.println(cmd[0], DEC);
}
}


void printMonth(int month)
{
switch (month)
{
 case 1: lcd.print("-01-"); break;
 case 2: lcd.print("-02-"); break;
 case 3: lcd.print("-03-"); break;
 case 4: lcd.print("-04-"); break;
 case 5: lcd.print("-05-"); break;
 case 6: lcd.print("-06-"); break;
 case 7: lcd.print("-07-"); break;
 case 8: lcd.print("-08-"); break;
 case 9: lcd.print("-09-"); break;
 case 10: lcd.print("-10-"); break;
 case 11: lcd.print("-11-"); break;
 case 12: lcd.print("-12-"); break;
 default: lcd.print(" Klaida "); break;
}
}

Code.txt (5.55 KB)

Please follow the advice on posting a programming question given in Read this before posting a programming question

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

Hello,

I modify my previous post, please, help to check and help to solve a problem if it's possible.

Hi,

Anyone can help on this ?

I personally have not had any problem at all with the 3231 running over extended periods. Are you able to try with another module? I've not studied your code in detail but nothing leaps out at me.

Hello,

Do we have any better module than DS3231 ?

The DS3231 is generally highly regarded and is certainly more accurate than you are experiencing. Apart from that problem, what characteristics would, in your opinion, would be better

I'm worry about one thing in my code. I'm thinking that it can be delay while we are showing time every one second. I trying to say that maybe I have some delay... every time during loop. And this 1000 ms interval is getting not equal to 1 second.... I am not sure If you can understand me. That's why after some time my DS3231 clock seconds are not equal to clock with computer.

unsigned long prev, interval = 1000;

Why not read the current second each time through loop() and printing only when the second changes ? It seems perverse to do timing using millis() when you have an RTC

Could you please let me know your logic in the code ? How to do it ?

rapolasl:
Could you please let me know your logic in the code ? How to do it ?

Here it is in pseudo code

start of loop
  read the time from the RTC
  if currentSecond not equal to previousSecond
    display the current time
    previousSecond = currentSecond
  end if
end of loop

Over to you to turn it into real code