RTC problem

Hi, I have been trying to use a RTC DS1307 with an arduino for controlling the lights on my aquarium. The problem is that the RTC cannot keep up the time accurately. I uploaded this program yesterday, with the time from my computer (the RTC has been running on battery), but now the time is about 7 minutes ahead of the actual time. I have read that it is a problem of the chip itself. Is there any solution to this problem other than replacing the RTC?
The RTC is in a board I bought from ebay. Also the ‘SQW’ pin in the DS1307 is left open, as I have read in tutorials that it is not required.

Here is the code I am using:

#include <Wire.h>
#include "RTClib.h"
#include <Time.h>
#include <TimeAlarms.h>

RTC_DS1307 RTC;

const int buttonPin = 2; 

int buttonState = 0;   


void setup() 
{
    Serial.begin(9600);
    Wire.begin();
    RTC.begin();
    
    pinMode(buttonPin, INPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
    pinMode(11, OUTPUT);

  if (! RTC.isrunning()) 
  {
    Serial.println("RTC is NOT running!");
   }
}

void loop() 
    {
    DateTime now = RTC.now();
    Serial.print(now.hour(), DEC);
    Serial.write(':');
    Serial.print(now.minute(), DEC);
    Serial.write(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    delay (1000);
//pin 2= button
//pin 3= blue LED    
//pin 4= red LED
//pin 5= small LED
//pin 6= big LED
//pin 7= pumps
//pin 8,9,10,11= motor


buttonState = digitalRead(buttonPin);  
{
if (buttonState == HIGH) 
{     
  digitalWrite(6, LOW);

if((now.hour() >= 8 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 23 ))
  {
  digitalWrite(3,HIGH);
  Serial.println("blue LED on");
  }
else
  {
  digitalWrite(3,LOW);
   }

if((now.hour() >= 10 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 19 ))
  {
  digitalWrite(4,HIGH);
  Serial.println("red LED on");
  }
else
  {
  digitalWrite(4,LOW);
   }

if((now.hour() >= 9 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 20 ))
  {
  digitalWrite(5,HIGH);
  Serial.println("SMALL LED on");
  }
else
  {
  digitalWrite(5,LOW);
   }

if((now.hour() >= 10 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 19 ))
  {
  digitalWrite(6,HIGH);
  Serial.println("BIG LED on");
  }
else
  {
  digitalWrite(6,LOW);
   }
   
if(now.hour() >= 9 && now.hour()< 22 )
  {
  digitalWrite(7,HIGH);
  Serial.println("Pump on");
  }
else
  {
  digitalWrite(7,LOW);
   }
   
if (( now.hour() >=8 && now.hour()< 9) || (now.hour()>=21 && now.hour()<22))
  {
    if ((now.minute() >= 30 && now.minute()< 32))
    {
          digitalWrite(8, HIGH);   
          delay(1);
          digitalWrite(8, LOW);    
          delay(1);
          digitalWrite(9, HIGH);   
          delay(1);
          digitalWrite(9, LOW);    
          delay(1);
          digitalWrite(10, HIGH);   
          delay(1);
          digitalWrite(10, LOW);    
          delay(1);
          digitalWrite(11, HIGH);   
          delay(1);
          digitalWrite(11, LOW);    
          delay(1);
    }
  }    
} 
  
else {
    digitalWrite(6, HIGH);
    digitalWrite(3,LOW);
    digitalWrite(4,LOW);
    digitalWrite(5,LOW);
    digitalWrite(7,LOW);
    digitalWrite(8,LOW);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(11,LOW);
    Serial.println("BIG LED on");
     }
}
}

Untitled.jpg

Hi Rajdeep

I uploaded this program yesterday, with the time from my computer (the RTC has been running on battery), but now the time is about 7 minutes ahead of the actual time.

Was the time displayed by the Arduino correct when the program started running?

Can you post the code you used to set the time in the RTC.

Regards

Ray

Hackscribble:
Was the time displayed by the Arduino correct when the program started running?

Can you post the code you used to set the time in the RTC.

Regards

Ray

Yes, when I first uploaded the code, the time was exactly same as the computer time; here is the code, it came with the ‘DS1307RTC’ library:

#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>

const char *monthName[12] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

tmElements_t tm;

void setup() {
  bool parse=false;
  bool config=false;

  // get the date and time the compiler was run
  if (getDate(__DATE__) && getTime(__TIME__)) {
    parse = true;
    // and configure the RTC with this info
    if (RTC.write(tm)) {
      config = true;
    }
  }

  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
  delay(200);
  if (parse && config) {
    Serial.print("DS1307 configured Time=");
    Serial.print(__TIME__);
    Serial.print(", Date=");
    Serial.println(__DATE__);
  } else if (parse) {
    Serial.println("DS1307 Communication Error :-{");
    Serial.println("Please check your circuitry");
  } else {
    Serial.print("Could not parse info from the compiler, Time=\"");
    Serial.print(__TIME__);
    Serial.print("\", Date=\"");
    Serial.print(__DATE__);
    Serial.println("\"");
  }
}

void loop() {
}

bool getTime(const char *str)
{
  int Hour, Min, Sec;

  if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
  tm.Hour = Hour;
  tm.Minute = Min;
  tm.Second = Sec;
  return true;
}

bool getDate(const char *str)
{
  char Month[12];
  int Day, Year;
  uint8_t monthIndex;

  if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
  for (monthIndex = 0; monthIndex < 12; monthIndex++) {
    if (strcmp(Month, monthName[monthIndex]) == 0) break;
  }
  if (monthIndex >= 12) return false;
  tm.Day = Day;
  tm.Month = monthIndex + 1;
  tm.Year = CalendarYrToTm(Year);
  return true;
}

My wild guess is that it's a counterfeit chip, and / or doesn't have the correct crystal.

Hi Rajdeep, I would recommend you get a replacement RTC with a DS3231 chip. They are considerably more accurate than DS1307, but work almost exactly the same. You code may not need any changes at all.The DS3231 also has a built-in temperature sensor that your sketch can read, and the modules often seen on eBay have extra flash/eeprom memory that can be used for logging purposes.

Paul

JimboZA:
My wild guess is that it's a counterfeit chip, and / or doesn't have the correct crystal.

Maybe the chip is counterfeit, but I have read some people also had the same problem! Also the RTC board came with a 'Tested OK' written behind the pcb!

Is there some alternate method of controlling lights with arduino other than RTC?

Seven minutes fast in one day is pretty bad! My DS1307 was running 7 seconds fast per day and I wasn't happy with that.

I thought about using a DS3231 or DS3234 ($8-10), but instead I replaced the crystal, and also the RTC with a different chip that's pin compatible. It is now very accurate, as good as the DS3231 but over a more limited temperature range.

The crystal I chose was one that Maxim suggested: CFS-206, 6pF. It cost $0.60. That by itself improved the accuracy so it was off by about 1 second/day.

The RTC I used was the [PCF85263A](http://www.digikey.com/product-search /en?KeyWords=568-12405-1-ND&WT.z_header=search_go) ($1.05). It has identical pin-out and was easy to replace.

The interface is a little different, however. For one thing, it has a resolution of 1/100ths of a second. It also provides a means to adjust the capacitance for the crystal as well as introduce an offset to correct for frequency error. Using the default values, mine is running 4ppm slow, about 1/3 of second per day. I set the offset register to +4ppm to counter that. Now it's more than good enough for the range of temperatures it will encounter indoors.

I'm just going to write a few simple functions to interface with it. I did a brief search and only found one library for it on the internet. For someone looking for a quick replacement that could be a sticking point.

jboyton:
I thought about using a DS3231 or DS3234 ($8-10)

Well, that module I linked to on eBay is £0.99 !

I don't know if the chips are genuine, but the one I have is still less than a minute out after about 2 years.

Ha! Yes, that's probably better.

My RTC is on a shield and I'd rather not glue on a separate breakout board. I also wanted the crystals and RTC for another project, so I was going to buy them anyway.

It is interesting how this kind of stuff from China is so cheap, cheaper than the cost of the ICs even if you buy them in quantity. How does that work exactly?

Can someone help me with adding a drift correction statement on my program? Since my RTC goes 8 minutes ahead, so will this do anything:
"if(now.hour() >=23)
{
now.minute = now.minute-8
}

It corrects the clock every night at 11pm?

No, it will sub 8 minutes every time through loop for the whole hour of 230000 to 235959.

You could use a boolean flag say timeAdjusted, initially false. Then put the adjust code in an if, where you check timeAdjusted. If it's false, adjust the time and set it true so it doesn't do it a gazillion times.

Then set it false again when the new day starts, ready for that day's 2300.

Will it work now?

"boolean timeAdjust = false;

void loop()
{
if(now.hour() >=23)
{
if (timeAdjust= false)
{
now.minute = now.minute-8;
}
timeAdjust = true;
}
} "

It does not compile; shows the following error:
"RTC_4.ino: In function 'void loop()':
RTC_4:117: error: invalid use of member (did you forget the '&' ?)"

 if (timeAdjust= false)

Should be

 if (timeAdjust== false)

Or just

 if (!timeAdjust)

Why let it run away for eight minutes before adjusting.
Why not use millis, and adjust the clock one minute every 10,800,000 milliseconds.
Or even finer. 20 seconds every hour, or whatever.
That number could be a user adjustable variable.
Leo..

Wawa:
Why let it run away for eight minutes before adjusting.
Why not use millis, and adjust the clock one minute every 10,800,000 milliseconds.
Or even finer. 20 seconds every hour, or whatever.
That number could be a user adjustable variable.
Leo…

Because, it will be controlling the lights, so 8 minutes a day is not a factor. Also, if I set up for adjusting 20 seconds every hour, & there is a power loss (it happens here on daily basis), then the clock will miss the adjustment. By keeping it every night at 11, atleast I can be sure that it will not miss on the adjustment as power loss is very rare at that period of night.

PaulRB:

 if (timeAdjust= false)

Should be

 if (timeAdjust== false)

It still shows the same error. The error is related to this line: "now.minute = now.minute-8;"

Post your current code so someone can try compile and diagnose. Nobody (well, me anyways) is going to retrofit odd lines of code into a previous version of code.

Here is the code:

#include <Wire.h>
#include "RTClib.h"
#include <Time.h>
#include <TimeAlarms.h>

RTC_DS1307 RTC;

const int buttonPin = 2; 

int buttonState = 0;   
//
boolean timeAdjust = false;
//

void setup() 
{
    Serial.begin(9600);
    Wire.begin();
    RTC.begin();
    
    pinMode(buttonPin, INPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
    pinMode(11, OUTPUT);

  if (! RTC.isrunning()) 
  {
    Serial.println("RTC is NOT running!");
   }
}

void loop() 
    {
    DateTime now = RTC.now();
    Serial.print(now.hour(), DEC);
    Serial.write(':');
    Serial.print(now.minute(), DEC);
    Serial.write(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    delay (1000);
//pin 2= button
//pin 3= blue LED    
//pin 4= red LED
//pin 5= small LED
//pin 6= big LED
//pin 7= pumps
//pin 8,9,10,11= motor


buttonState = digitalRead(buttonPin);  
{
if (buttonState == HIGH) 
{     
  digitalWrite(6, LOW);

if((now.hour() >= 8 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 23 ))
  {
  digitalWrite(3,HIGH);
  Serial.println("blue LED on");
  }
else
  {
  digitalWrite(3,LOW);
   }

if((now.hour() >= 10 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 19 ))
  {
  digitalWrite(4,HIGH);
  Serial.println("red LED on");
  }
else
  {
  digitalWrite(4,LOW);
   }

if((now.hour() >= 9 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 20 ))
  {
  digitalWrite(5,HIGH);
  Serial.println("SMALL LED on");
  }
else
  {
  digitalWrite(5,LOW);
   }

if((now.hour() >= 10 && now.hour()< 14 )  || (now.hour() >= 15 && now.hour()< 19 ))
  {
  digitalWrite(6,HIGH);
  Serial.println("BIG LED on");
  }
else
  {
  digitalWrite(6,LOW);
   }
   
if(now.hour() >= 9 && now.hour()< 22 )
  {
  digitalWrite(7,HIGH);
  Serial.println("Pump on");
  }
else
  {
  digitalWrite(7,LOW);
   }
//   
if(now.hour() >=23)
  {
    if (timeAdjust== false)
    {
      now.minute = now.minute-8;   //the problem is here.
    }
    timeAdjust = true;
  }
//
if (( now.hour() >=8 && now.hour()< 9) || (now.hour()>=21 && now.hour()<22))
  {
    if ((now.minute() >= 30 && now.minute()< 32))
    {
          digitalWrite(8, HIGH);   
          delay(1);
          digitalWrite(8, LOW);    
          delay(1);
          digitalWrite(9, HIGH);   
          delay(1);
          digitalWrite(9, LOW);    
          delay(1);
          digitalWrite(10, HIGH);   
          delay(1);
          digitalWrite(10, LOW);    
          delay(1);
          digitalWrite(11, HIGH);   
          delay(1);
          digitalWrite(11, LOW);    
          delay(1);
    }
  }    
} 
  
else {
    digitalWrite(6, HIGH);
    digitalWrite(3,LOW);
    digitalWrite(4,LOW);
    digitalWrite(5,LOW);
    digitalWrite(7,LOW);
    digitalWrite(8,LOW);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(11,LOW);
    Serial.println("BIG LED on");
     }
}
}

Is the problem of synchronizing arising due to the serial print function? I have read in older posts that due to the serial monitor display function there is a slight delay, although my clock is adding up about 20 seconds per hour

Can someone please show me the code for sending a command to the RTC. All the codes I found are used for either reading the time, or for setting it from the serial monitor.

Rajdeep_Banik:
Can someone please show me the code for sending a command to the RTC.

I think the best place for that is to look in the .h file of the library you used, which will show what functions are available in the library.

Alternatively, if there's something you need to do which isn't in the library, you'll need to examine the RTC's datasheet and do it from first principles.