RTC DS1307 Malfunction and goes in to a Loop

Hi All

I would like to know if any one else had the same problem and how do I fix it and prevent it from happening again.

My project logs the temperature on a SD card and controls the windows of the pig pen.

I installed my temperature controller/logger on the farm and it was running fine from 2011/9/07 until 2011/9/17 2:38:11. Then it seams the the Arduino reset it self and the date and time changed and went back to 2011/9/6 23:43:12.

Now the other strange thing the time went in to a loop every two days after that as follow:
the time incremented normally from 2011/9/6 23:43:12 to 2011/9/7 11:3:34
The it looks like a reset again and the time changed to 2011/9/6 23:43:12 and ran for two days.
The same thing now keeps on happening.

Please let me know if you would like to see the log file.

I am using the RTClib.

Any ideas and help would be appreciated.

Thank you in advanced

Best regards

Luan

Luan,

Did you have a set time function in the setup? Let's not discuss the "why arduino resets" but when it resets and if you have a set time in the setup, it returns to the same time. What I suggest you do is to:

  1. set the time in setup, upload code to set time. Then comment out the set time from setup and upload the code again. Also have a working backup battery on the RTC.

  2. have an interactive interface to set up the time in the field so you don't have to put an initial time in the setup, which ruins the time every time arduino resets. An interactive alarm clock would be a good starting point to make an interface to enter time.

Hi Liudr

Thanx for your response.

Why does the RTC go wrong if the Arduino resets?

The RTC has a Backup battery connected it.

Here is the code that I use:

void setup(void) 
{
 
 Serial.begin(57600);
 //left other code out

  Wire.begin();
  getDateDs1307();

  //left other code out

  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__));
  }

 now = RTC.now();

 //left other code out
}


void loop(void) 
{
  RTC_config();
  delay(1000);  //Delay between checks

  now = RTC.now();

  //Get temp code
  getDateDs1307();
  //Write to SD code

  ControlDevicesDepeningOnTemp();
   WriteDataIfTempChanged();

  Serial.flush();

}

//_______________RTC_config Begin___________________

 //* T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99) - T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year) - T Sets the date of the RTC DS1307 Chip. 
// * Example to set the time for 02-Feb-09 @ 19:57:11 for the 3 day of the week, use this command - T1157193020209
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________________________

//_______________decToBcd Begin_________________________
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
//_______________decToBcd End_________________________


//_______________bcdToDec Begin_______________________
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) ); 
}

//_______________bcdToDec End_______________________


//_______________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);

}
//_______________getDateDs1307 End_________________

If I understand correctly I must remove the following from setup after the RTC is initialized at least once?

  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__));
  }

And can I leave RTC_config(); in the main loop to change the time if necessary?

Before I installed the system on the farm I tested it for quite some time and I did not get the problem. Just to be sure it is a software problem and not a hardware problem?

Thank you for your input.

Best Regards

Luan

if it was a problem with the rtc and lets say the back up battery was not working then it would reset to 0:0 not anything else, so it obviously resetting to your compile date meaning it is software , so if you compile your software once with the current time and upload rightaway , WHILE HAVING THE BACK UP BATTER CONNECTED , then remove any set time functions because have already set the time and adjust your code so if the arduino resets for what ever reason it will still run fine meaning any variables that you may have are not reset such as counters etc.. could store them in EEPROM where they will not get erased on reset, as far as why it is resetting perhaps a psu problem?

I kind of suspect back up battery is not working. So if you set up your system and then disconnect power then reconnect power, will time reset? If it does, it means the back up battery is not powering the RTC while the main power is cut. In that case the RTC stops and when arduino is back on, it finds RTC stopped and resets the time to compile time, which is on 9/6/2011

Hi

Where does the compiled date get stored? I thought it gets the date from the PC.
I did compile it on the 6th.

Thanx for all your help I am learing more every day.

Regards

Luan

Luan:
Hi

Where does the compiled date get stored? I thought it gets the date from the PC.
I did compile it on the 6th.

Thanx for all your help I am learing more every day.

Regards

Luan

It's a constant that took the value at the time of the compilation and stored in arduino. It won't change once the sketch is loaded to arduino until next time you compile again and upload to arduino.

The RTC gets the date from your PC the second you compile it and then it gets stored on the RTC, but if at any point you lose power from all sources such as back up battery and arduino then the date is reset to 0:0 , however if you set the date in the setup of your sketch it will give it the date in which the sketch was compiled, which would of course be a wrong date. Thats why i think your back up battery is fine if your getting an actual date after it is reset, hence the problem would most likely be spftware. A solution might be everytime you read the date also store it in eeprom, but before you store it in eeprom compare it to what you stored last time and if this new date is less then the last date which would mean you went back in time then your rtc has reset again so you could just set it to the last entry you made on the eeprom, since your reading once a second it would be off by a second. though i think this is very crude and impracticle but it would work, and im sure that 1 second lag would eventually add up after several resets.

Hi Eddiea

Thanx for the RTC eeprom idea. I will try it for an extra fail safe.

I just want to make sure and understand the RTC at setup, If I remove the following will it prevent the date going back to compile date?

  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__));
  }

And lets presume the battery is working fine, will the RTC reset to 00/00/00 00:00 if the Arduino resets?

Now my next question what can cause the Arduino to reset by is self, or should I start a new topic for it?

Many thanx so far.

Luan

well you see that checks to see if the Rtc is not running but why would it not be running? If it has power and battery is fine then it has no reason to not be running.
either way anytime you put RTC.adjust(DateTime(DATE, TIME)); it will go back to compile date its best to handle the isNotRunning function some other way.
As far as why it is resetting i can only think it must be either shorting out, or somehow dropping below a certain voltage level at which the chip turns off.

perhaps you could try using the RTClib GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC Arduino library and check your hardware and wiring

When you post code like this:

void setup(void) 
{
 
 Serial.begin(57600);
 //left other code out

  Wire.begin();
  getDateDs1307();

... one wonders if the "left other code out" part is the crucial problem area.

For example, in my code which tests the clock I have an RTC.begin () which I don't see in your code.

  // clock uses I2C
  Wire.begin();
  
  // activate clock
  RTC.begin();

So if the clock is not initialized, it might fail this test:

if (! RTC.isrunning())

So then you always set the clock back to the compile date.

And lets presume the battery is working fine, will the RTC reset to 00/00/00 00:00 if the Arduino resets?

No. What would be the point of the battery then?

liudr:
I kind of suspect back up battery is not working. So if you set up your system and then disconnect power then reconnect power, will time reset? If it does, it means the back up battery is not powering the RTC while the main power is cut. In that case the RTC stops and when arduino is back on, it finds RTC stopped and resets the time to compile time, which is on 9/6/2011

What I was suggesting should not be hard to test and I wonder why you're so not interested in doing it.

Hi

I tested it at home, The working prototype is on the farm 100Km away, I will go there next week.

With the other PCB at home:
If I power it down and reconnect the power it keep the time.

With code below:

  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__));
  }

in place if I remove the RTC chip and put it back, after reset it has the compile time.

With the above code removed when I remove the chip it resets the time to 00/1/1 00:01 and it does not increment the time, when I set the time with the serial port it set the time and works again.

When I get back from the farm I will let you know what I found, maybe a lose connection.

Thanx

ttfn

Thanks for clarifying. If the prototype you have at home is identical to the one on the farm, then I don't know what went wrong. It seems to operate as it should. Maybe replace the battery of the farm unit and try unplug arduino and put it back when you are at the farm.

Luan:
Here is the code that I use:

...

if (command == 84)
    {      //If command = "T" Set Date

...

}
    else if (command == 81)
    {      //If command = "Q" RTC1307 Memory Functions
...

How about making the code more readable? Instead of:

 if (command == 84)   // got "T"
...

 else if (command == 81)  // got "Q"

Do this:

 if (command == 'T')   
...

 else if (command == 'Q')

and so on for elsewhere.

This part is fundamentally flawed:

 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();


...


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();
}

Once you get the "T" command you go ahead and read from Serial without checking if anything further is available. The processor is much faster than the serial port, most or all of those serial reads will return -1, giving you invalid data.

Hi Nick

Thank you for your suggestions, the RTC code you are referring to I got of the net, It was working so I did not change much. At the moment I am only reading from the Serial port to change the time. When I read more stuff I will make the necessary changes and check the amount of bytes received and so on.

I appreciate you efforts and interest.

Thank you

Best regards

Luan

Hi all

I am now trying the RTC eeprom backup idea from Eddiea.

It seams to work when I change the time back a bit and reset the Arduino before setDs1307ExtraMem(); runs in the main loop.

Results of set time back and manually reset of Arduino:

Hello daar
EX 11/9/25 18:49:42
now 2011/9/25 18:49:42 = 1316976582s /
BackupTime 2011/9/25 18:49:28 = 1316976568s /
Time OK
Setup complete
reset now
EX 11/9/25 18:49:47
BackupTime 2011/9/25 18:49:47 = 1316976587s /
2011/9/25 18:49:47
reset now
EX 11/9/25 18:49:52
BackupTime 2011/9/25 18:49:52 = 1316976592s /
2011/9/25 18:49:52
reset now
EX 11/9/25 18:49:57
BackupTime 2011/9/25 18:49:57 = 1316976597s /
2011/9/25 18:49:57
reset now
EX 11/9/25 18:50:3
BackupTime 2011/9/25 18:50:3 = 1316976603s /
2011/9/25 18:50:3

Command: 84 //changed time and pressed the reset button
reset now
Hello daar
EX 11/9/25 18:22:10
now 2011/9/25 18:22:10 = 1316974930s /
BackupTime 2011/9/25 18:50:3 = 1316976603s /
Time Problem restoring Backup Time
EX 11/9/25 18:22:10
Setup complete
reset now
EX 11/9/25 18:50:8
BackupTime 2011/9/25 18:50:8 = 1316976608s /
2011/9/25 18:50:8
reset now

But when I unplug the Arduino remove the RTC chip, and put it back and power it up again I get the following:

Hello daar
EX 0/1/1 0:0:0
now 2000/1/1 0:0:0 = 946684800s /
BackupTime 2002/90/20 9:0:20 = 1989997220s /
Time Problem restoring Backup Time
EX 0/1/1 0:0:0
Setup complete
reset now
EX 2/10/20 9:0:24
BackupTime 2002/10/20 9:0:24 = 1035104424s /
202/10/20 9:0:24
reset now

Please let me know why the data in the NV SRAM is different when I remove the chip.

When I unplug the Arduino and wait a few seconds it also works see results below and note the the Backup Time is behind the RTC time:

Hello daar
EX 11/9/25 18:58:53
now 2011/9/25 18:58:53 = 1316977133s /
BackupTime 2011/9/25 18:57:43 = 1316977063s /
Time OK
Setup complete
reset now
EX 11/9/25 18:58:58
BackupTime 2011/9/25 18:58:58 = 1316977138s /
2011/9/25 18:58:58
reset now
EX 11/9/25 18:59:3
BackupTime 2011/9/25 18:59:3 = 1316977143s /
2011/9/25 18:59:3
reset now

I attached the code.

Thank you

RTC_Backup_Time.pde (11.7 KB)

well your programming skills seem to surpass mine so i cannot give feed back on the code side of things but even though the "backing up" of time does sort of fix the issue it would still be nice to know why the chip isnt just keeping time for the supposed "5 years" with the coin cell, personally i have an rtc chip and cell battery which no matter what i did never ever ever worked when removing power and keeping only that battery connected . battery worked fine , connections where tripple to the tenth power checked and everything was fine so i assumed it was the chip.
we should wait and see what Mr. Nick Gammon or Sir liudr think