RTC time stays the same

Hi all

I have a RTC problem. I seams that everything was working fine for a week. Now the RTC stopped keeping time and the time stays the same.

I would like to know what may cause it.

I will go and replace the DS1307 when I go to the farm. The problem does not happen on my test bed so it is difficult to diagnose because the farm is 100Km away.
Is there known hardware problems with the DS1307 or can it be a software problem.
What can I do to solve this?

Any suggestions would be appreciated

Thank you

Regards

Luan

Now the RTC stopped keeping time and the time stays the same.

I would like to know what may cause it.

In my mind, the most like cause is a dead battery.

HI

I tested the battery it is still at 3V and it is only a few months old.

I am using RTClib.h or is DS1307RTC.h any different?

Thank you

PS the time does not reset but just stops working and stays the same.

There are no known issues with the DS1307. If there were, it probably wouldn't be so popular.

Please post your code and a schematic of how you've attached the DS1307.

Is it at (or near) the same point where time stops being advanced?

Luan: I have a RTC problem. I seams that everything was working fine for a week. Now the RTC stopped keeping time and the time stays the same.

The same as what? It always shows 12:42 pm on Sunday 4th October? Or it works for a while and then stops? Or it is different every time you boot it, but then doesn't change?

Let's assume you are using the RTClib library. Inside that is:

DateTime RTC_DS1307::now() {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0);    
  Wire.endTransmission();
  
  Wire.requestFrom(DS1307_ADDRESS, 7);
  uint8_t ss = bcd2bin(Wire.receive() & 0x7F);
  uint8_t mm = bcd2bin(Wire.receive());
  uint8_t hh = bcd2bin(Wire.receive());
  Wire.receive();
  uint8_t d = bcd2bin(Wire.receive());
  uint8_t m = bcd2bin(Wire.receive());
  uint16_t y = bcd2bin(Wire.receive()) + 2000;
  
  return DateTime (y, m, d, hh, mm, ss);
}

I note with some interest that after doing Wire.requestFrom it doesn't check it actually got 7 bytes. So if there is an I2C problem, you may be getting garbage.

Thank you for your help so far.

The RTC sch is attached, note the 7V is actually 5V from the Arduino I use 5V from a regulator for the other component.

Some of the results are attached and the time stays the same even after reset.

Here is some of the code:

//_______________setDateDs1307 Begin_________________
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers, Probably need to put in checks for valid numbers.

void setDateDs1307()                
{
  second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  
  minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  dayOfWeek = (byte) (Serial.read() - 48);
  dayOfMonth = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x00);
  Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
  Wire.send(decToBcd(minute));
  Wire.send(decToBcd(hour));      // If you want 12 hour am/pm you need to set
  // bit 6 (also need to change readDateDs1307)
  Wire.send(decToBcd(dayOfWeek));
  Wire.send(decToBcd(dayOfMonth));
  Wire.send(decToBcd(month));
  Wire.send(decToBcd(year));
  Wire.endTransmission();
}
//_______________setDateDs1307 End_________________


//_______________getDateDs1307 Begin_________________
// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x00);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  second     = bcdToDec(Wire.receive() & 0x7f);
  minute     = bcdToDec(Wire.receive());
  hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  dayOfWeek  = bcdToDec(Wire.receive());
  dayOfMonth = bcdToDec(Wire.receive());
  month      = bcdToDec(Wire.receive());
  year       = bcdToDec(Wire.receive());

  strDate.begin();
  strDate.print("20");
  strDate.print(year, DEC); 
  strDate.print("/");
  strDate.print(month, DEC);
  strDate.print("/");
  strDate.print(dayOfMonth, DEC);
  strDate.print(" ");
  strDate.print(hour, DEC);
  strDate.print(":");
  strDate.print(minute, DEC);
  strDate.print(":");
  strDate.print(second, DEC);
  
  //Serial.print("strDate ");
  //Serial.println(strDate);
  //Serial.println();
  
  //Added extra string for SD 2011/09/26
  strDateForSD.begin();  
  strDateForSD.print(second, DEC);
  strDateForSD.print("\n");
  strDateForSD.print(minute, DEC);
  strDateForSD.print("\n");
  strDateForSD.print(hour, DEC);
  strDateForSD.print("\n");
  strDateForSD.print(dayOfWeek, DEC);
  strDateForSD.print("\n");
  strDateForSD.print(dayOfMonth, DEC);
  strDateForSD.print("\n");
  strDateForSD.print(month, DEC);
  strDateForSD.print("\n");
  strDateForSD.print(year, DEC);
  strDateForSD.print("\n");
  strDateForSD.print("\n");
  strDateForSD.print(strDate);
  strDateForSD.print("\n");
  strDateForSD.print("EOF");
 
}
//_______________getDateDs1307 End_________________


//_______________RTC_config Begin___________________
void RTC_config()
{

  if (Serial.available()) 
  {      // Look for char in serial que and process if found
    command = Serial.read();
    if (command == 84) 
    {      //If command = "T" Set Date
      setDateDs1307();
      getDateDs1307();
      Serial.println(" ");
      futureTDC = ( now.unixtime() );  //Reset TDC if time chenged //2011/05/17
    }
    else if (command == 81) 
    {      //If command = "Q" RTC1307 Memory Functions
      delay(100);     
      if (Serial.available()) 
      {
        command = Serial.read(); 
        if (command == 49) 
        {      //If command = "1" RTC1307 Initialize Memory - All Data will be set to 255 (0xff).  Therefore 255 or 0 will be an invalid value

          Wire.beginTransmission(DS1307_I2C_ADDRESS); // 255 will be the init value and 0 will be considered an error that occurs when the RTC is in Battery mode.
          Wire.send(0x08); // Set the register pointer to be just past the date/time registers.
          for (int i = 1; i <= 27; i++) 
          {
            Wire.send(0xff);
            delay(100);
          }   
          Wire.endTransmission();
          getDateDs1307();
          Serial.println(": RTC1307 Initialized Memory");
        }
        else if (command == 50)  //If command = "2" RTC1307 Memory Dump
        {      
          getDateDs1307();
          Serial.println(": RTC 1307 Dump Begin");
          Wire.beginTransmission(DS1307_I2C_ADDRESS);
          Wire.send(0x00);
          Wire.endTransmission();
          Wire.requestFrom(DS1307_I2C_ADDRESS, 64);
          for (int i = 1; i <= 64; i++) 
          {
            testRTC = Wire.receive();
            Serial.print(i);
            Serial.print(":");
            Serial.println(testRTC, DEC);
          }
          Serial.println(" RTC1307 Dump end");
        }           
      }  
    }

    else if (command == 83)  //If command = "S" RTC1307 SQW/OUT Functions by Luan Celliers on 2011/01/11
    {      
      delay(100);     
      if (Serial.available()) 
      {
        command = Serial.read();         

        if (command == 48) //If command = "0" RTC1307 Set SQW/OUT pin to OFF , by Luan Celliers on 2011/01/11 .
        {      
          Serial.println(": Set SQW/OUT pin");
          Wire.beginTransmission(DS1307_I2C_ADDRESS);
          Wire.send(0x07);
          Wire.send(0x00);    //OUT 0 0 SQWE 0 0 RS1 RS0
          Wire.endTransmission();
          Serial.println(" : Set SQW/OUT pin end");
        }

        else if (command == 49)  //If command = "1" RTC1307 Set SQW/OUT pin to 1Hz, by Luan Celliers on 2011/01/11 .
        {      
          Serial.println(": Set SQW/OUT pin");
          Wire.beginTransmission(DS1307_I2C_ADDRESS);
          Wire.send(0x07);
          Wire.send(0x90);    //OUT 0 0 SQWE 0 0 RS1 RS0
          Wire.endTransmission();
          Serial.println(" : Set SQW/OUT pin end");
        }
      }  
    }     
    Serial.print("Command: ");
    Serial.println(command);     // Echo command CHAR in ascii that was sent
  }
  command = 0;                 // reset command 

}
//_______________RTC_config End________________________


//_______________Trim Begin________________________
// A way to trim leading and trailing whitespace from C-style "string."
//
//  davekw7x
//
void trim(char *charry)
{
  int i, j;

  /* First find trailing whitespace and eliminate it from the "string" */
  for (i = strlen(charry)-1; i >= 0; i--) {
    if (!isspace(charry[i])) {
      break;
    }
    /* This was whitespace.  Make this the end of the "string */
    charry[i] = '\0';
  }

  /* Next, start at the beginning and skip leading whitespace */
  for (i = 0; charry[i] != '\0'; i++) {
    if (!isspace(charry[i])) {
      break;
    }
  }

  /* Now, copy from present position to the end of the "string." */
  for (j = 0; charry[i] != '\0'; i++, j++) {
    charry[j] = charry[i];
  }
  /* Finally, put the terminating zero byte at the end of the trimmed "string." */
  charry[j] = '\0';
}
//_______________Trim End________________________

LOG.txt (4.24 KB)

rtc.pdf (5.67 KB)

2.2K! Wow, that is a hefty pullup.

Any chance bit 7 of the seconds register got set to stop time running?

// Assumes you're passing in valid numbers, Probably need to put in checks for valid numbers.

void setDateDs1307()                
{
  second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result
:
:
  Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock

Luan: Here is some of the code:

...

Some of the code? How about all of the code? Where is setup? Where is loop?

What is all this stuff about Serial.read for setting a clock that is sitting on a farm? Why not just set the clock with a small "clock set" sketch, and then just read it in your main sketch? Too much to go wrong here, IMHO.

    else if (command == 83)  //If command = "S" RTC1307 SQW/OUT Functions by Luan Celliers on 2011/01/11

I think I may have mentioned this before, but this would be more readable as:

    else if (command == 'S')  //If command = "S" RTC1307 SQW/OUT Functions by Luan Celliers on 2011/01/11

HI CrossRoads

I got the RTC diagram from Data-Logger Shield for Arduino
Please let me know what pull ups I should use?

I only use setDateDs1307() to change the time with the Serial port in the rest of the code I do not send anything to the RTC I only read from the RTC.
The RTC stopped working with out some one changing the time and this happened 2011/10/16 at 02:58 AM.

Thank you

Regards

Hi Nick

Yes I am using the RTClib.h lib.
And Yes we talked about the if (command == ‘S’) before, I did not have time to update it.
I did not write the RTC code I only added the SQW/OUT bit I don’t remember where I got it. I think it was from www.combustory.com and www.glacialwanderer.com

I left the RTC_config() in the code so that the time can be changed with out reloading the sketch and with the use of a terminal program.

I was made a copy mistake in the previous post so here in the code again.
Attached as a file I see I can only add so many lines in the post.

Thank you for the support

:wink:

RTC_code.txt (11.5 KB)

Hi All

So after reading you posts again and checking the Data sheet you are suggesting the problem is with the CH Bit at Bit 7 of Register 0? If this is the case why does it happen? Because I only read form the RCT in the main loop.

Do I need to make sure that the CH bit is set when I use setDateDs1307() and how do I do it? Do I use a mask at “ Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock”?

How do I only write to the CH bit without changing the seconds or bit 0-6?

When the seconds are read a mask is used. After a reset the time is still stoped so the CH bit is the problem.

Thank you

Regards

Luan

Luan: If this is the case why does it happen? Because I only read form the RCT in the main loop.

Well, not really.

void loop(void) 
{
  
  RTC_config();

In the main loop you keep attempting to configure the clock.

I left the RTC_config() in the code so that the time can be changed with out reloading the sketch and with the use of a terminal program.

How many hours are you going to waste on this, when in your main loop you possibly (who knows?) change the clock every few milliseconds, when you could set the clock once, and then let it run for 10 years on the battery?

I am suggesting that this "time-saving" code, that saves you quickly uploading a "clock change" sketch once every 5 or 10 years, might be (in some way) responsible.

Also, why do you do this:

 now = RTC.now();

  
  getDateDs1307();

Isn't that just two different ways of getting the time?

Hi Nick

Thank you for your input so far.

The farmer needs to be able to set the time using terminal without loading different code.

GetDateDs1307() is for saving the time and date on the SD card.
now = RTC.now() is used for date/time calculations.

Now back to my problem.
RTC_config() only works if it gets data on the Serial port. The only time the Serial port gets any data is when it is connected to a PC and a sting is send to the Arduino, this does not happen in normal operation.
I would like to know what causes the CH bit to change (by it self), I need to understand why it happens and solve the root of the problem.

How do I make sure that the CH bit is set?
How do I only write to the CH bit without changing the seconds or bit 0-6?

Thank you

Regards

Luan

Luan: Hi Nick

Thank you for your input so far.

My pleasure.

Luan: Now back to my problem. RTC_config() only works if it gets data on the Serial port. The only time the Serial port gets any data is when it is connected to a PC and a sting is send to the Arduino, this does not happen in normal operation.

How do you know that? What circuit or board are you using? Do you have the Rx line tied high with a pull-up resistor?

Luan: I would like to know what causes the CH bit to change (by it self), I need to understand why it happens and solve the root of the problem.

How do I make sure that the CH bit is set? How do I only write to the CH bit without changing the seconds or bit 0-6?

I doubt the CH bit is changing "by itself".

Let's work through how this might happen ...

In RTC_config you have this:

 if (Serial.available()) 
  {      // Look for char in serial que and process if found
    command = Serial.read();
    if (command == 84) 
    {      //If command = "T" Set Date
      setDateDs1307();

Now I do seem to recall going over this in the past, and perhaps you chose not to change any of it ...

Let's say that Serial.available() returns 1, and that only one byte is available. However despite that you call setDateDs1307 (). So there is one check you might do (that there is more data).

In setDateDs1307 you read from Serial without checking if data is available. That's not good. Not only that you don't check the data. That is worse. So "second" might be 99 which would turn on the CH bit.

void setDateDs1307()                
{
  second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  
  minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  dayOfWeek = (byte) (Serial.read() - 48);
  dayOfMonth = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));

In fact, if there is no serial data, Serial.read() returns -1 (or 0xFF if you like). So if there is no data, you get 0xFF. And you don't check if there is data. And if you get 0XFF seconds are invalid. Which you don't check. And if seconds is > 79 then that turns on the CH bit. So there are quite a few places that can fail there.

Here's my guess ... particularly if the Rx line is not definitely held high you get a bit of noise there. One day, many hours later, it happens to be a "T" (set date). Then this whole train of events is triggered. Not checking for more data. Not checking if the data is valid. And then stopping the clock.

Fix that all up, and then come back if it still does it.

Ola

I am still reading you post so give me few min, my RTC sch was posted on Reply #6 on: 2011-10-22 ttfn :-)

I saw that schematic but it hardly shows the wiring to the board itself. It doesn't show if you use any pull-up resistors on the Tx/Rx lines, decoupling capacitors, that sort of thing.

Hi

The 7V is actually 5V from the Arduino I use 5V from a regulator for the other components.
R25 and R26 are 2K2 pull ups. Where and why do I need decoupling capacitors.
The RTC is the only thing connected to I2C.

My sch is the same as ds1307.png I got it from github.com/adafruit/DS1307-breakout-board

rtc_ds1307_adafruit.png

Perhaps I am not being very clear. I did not ask about the DS1307 board, to which you already provided the schematic.

What Arduino board are you using? How is it wired up in general? Like, which pins are connected to what?