Arduino + Ethernet + DS1307 overflow(?) error

Hello,
I am doing a project with ethernet shield (5100) and DS1307 RTC,

I had 2 problems, the first one was the the arduino would just stop responding every few couple of hours, apparently it has gotten alot better after connecting it to an external power source. although it still freeze after 2 days~ (last time I checked)

the second one is that after about 1.5 days the RTC has started to give garbage. instead of the time it responded with 450/521/2030

or something similar.

I cant find the problem.. did anyone had the same or similar problems?

Why does the Ethernet freeze (I use the Arduino "Official" Ethernet Library) and for the rtc a library called "DS1307RTC" I can post it here if it is necessary...

How come the ethernet freezes after 2 days, and how can I prevent it?

thanks.

How come the ethernet freezes after 2 days, and how can I prevent it?

Using which version of the IDE?

I am using the new 1.0.1.

I have this part of the code that syncs the RTC with arduino. that is the only part of the code that handles the RTC (Except for writing it)

does it look ok?

setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus()!= timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");

Do you use this libary ? Arduino Playground - Time

I'm looking at the library right now, but it is not easy to understand.
You could have a ram or stack overflow, or the Time library could have problems with rollover.

You check timeStatus() for timeSet, but can you check which value it is ? Is it "timeNotSet" or "timeNeedsSync".
If it is "timeNeedsSync" you might just ignore that value and try once more.

You might have a rollover problem in you own code.
If you use millis() for example.
Can you measure somehow how long it takes to freeze ? Is it the same every time ?

One of the RTC libraries does not check return values. I would add that check in. Example:

DateTime RTC_DS1307::now() {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send((byte) 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);
}

This is wrong in two ways:

  • There is no check on the Wire.endTransmission line for a 0 (meaning "good").
  • There is no check on Wire.requestFrom that it returns 7 bytes. So if it got 4 bytes then 3 will be garbage.

Yours may be more up-to-date than the above, but that is where I would be checking.

Of course, you have to decide what to do if the "read" fails. Perhaps loop and do it again until it succeeds.

I am having some freezing problems with my arduino uno+ethernet+ds1037. I believe the problem lies within the ds1037 as it sometimes give me garbage which is probably the source for the freezing.

what is your preferred ds1037 library?
thanks.

I just read somewhere that I might need to add resistors to the inputs of the ds1037 or to use pullups\pulldowns..

can anyone assist me with what I need to configure?

actually, this is the library I use:

I just updated the code so when it converts the time to decimal it will never give garbage, so in the worst case scenario it will return 0.

I wonder if this fix will work..

/*
 * DS1307RTC.h - library for DS1307 RTC
  
  Copyright (c) Michael Margolis 2009
  This library is intended to be uses with Arduino Time.h library functions

  The library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  
  30 Dec 2009 - Initial release
  5 Sep 2011 updated for Arduino 1.0
 */

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

#define DS1307_CTRL_ID 0x68 

DS1307RTC::DS1307RTC()
{
  Wire.begin();
}
  
// PUBLIC FUNCTIONS
time_t DS1307RTC::get()   // Aquire data from buffer and convert to time_t
{
  tmElements_t tm;
  read(tm);
  return(makeTime(tm));
}

void  DS1307RTC::set(time_t t)
{
  tmElements_t tm;
  breakTime(t, tm);
  tm.Second |= 0x80;  // stop the clock 
  write(tm); 
  tm.Second &= 0x7f;  // start the clock
  write(tm); 
}

// Aquire data from the RTC chip in BCD format
void DS1307RTC::read( tmElements_t &tm)
{
  Wire.beginTransmission(DS1307_CTRL_ID);
#if ARDUINO >= 100  
  Wire.write((uint8_t)0x00); 
#else
  Wire.send(0x00);
#endif  
  Wire.endTransmission();

  // request the 7 data fields   (secs, min, hr, dow, date, mth, yr)
  Wire.requestFrom(DS1307_CTRL_ID, tmNbrFields);
#if ARDUINO >= 100    
  tm.Second = bcd2dec(Wire.read() & 0x7f);   
  tm.Minute = bcd2dec(Wire.read() );
  tm.Hour =   bcd2dec(Wire.read() & 0x3f);  // mask assumes 24hr clock
  tm.Wday = bcd2dec(Wire.read() );
  tm.Day = bcd2dec(Wire.read() );
  tm.Month = bcd2dec(Wire.read() );
  tm.Year = y2kYearToTm((bcd2dec(Wire.read())));
#else
  tm.Second = bcd2dec(Wire.receive() & 0x7f);   
  tm.Minute = bcd2dec(Wire.receive() );
  tm.Hour =   bcd2dec(Wire.receive() & 0x3f);  // mask assumes 24hr clock
  tm.Wday = bcd2dec(Wire.receive() );
  tm.Day = bcd2dec(Wire.receive() );
  tm.Month = bcd2dec(Wire.receive() );
  tm.Year = y2kYearToTm((bcd2dec(Wire.receive())));
#endif  
}

void DS1307RTC::write(tmElements_t &tm)
{
  Wire.beginTransmission(DS1307_CTRL_ID);
#if ARDUINO >= 100  
  Wire.write((uint8_t)0x00); // reset register pointer  
  Wire.write(dec2bcd(tm.Second)) ;   
  Wire.write(dec2bcd(tm.Minute));
  Wire.write(dec2bcd(tm.Hour));      // sets 24 hour format
  Wire.write(dec2bcd(tm.Wday));   
  Wire.write(dec2bcd(tm.Day));
  Wire.write(dec2bcd(tm.Month));
  Wire.write(dec2bcd(tmYearToY2k(tm.Year))); 
#else  
  Wire.send(0x00); // reset register pointer  
  Wire.send(dec2bcd(tm.Second)) ;   
  Wire.send(dec2bcd(tm.Minute));
  Wire.send(dec2bcd(tm.Hour));      // sets 24 hour format
  Wire.send(dec2bcd(tm.Wday));   
  Wire.send(dec2bcd(tm.Day));
  Wire.send(dec2bcd(tm.Month));
  Wire.send(dec2bcd(tmYearToY2k(tm.Year)));   
#endif
  Wire.endTransmission();  
}
// PRIVATE FUNCTIONS

// Convert Decimal to Binary Coded Decimal (BCD)
uint8_t DS1307RTC::dec2bcd(uint8_t num)
{
  return ((num/10 * 16) + (num % 10));
}

// Convert Binary Coded Decimal (BCD) to Decimal
uint8_t DS1307RTC::bcd2dec(uint8_t num)
{
  if((((num/16 * 10) + (num % 16))>=0 && ((num/16 * 10) + (num % 16))<=60) || (((num/16 * 10) + (num % 16))>=2010 && ((num/16 * 10) + (num % 16))<=2030))
return ((num/16 * 10) + (num % 16));
else
return(0);
}

DS1307RTC RTC = DS1307RTC(); // create an instance for the user

The DS1307 I think you meant, is an I²C device. The I²C bus operates around the principals of the devices being open-drain (or open collector for ancient TTL devices).

As a result the bus requires pull-up resistors to make it work properly.

Add 10K resistors between SCL and +5V, and SDA and +5V.

Anyway, isn't this a cross-post of http://arduino.cc/forum/index.php/topic,109648.0.html?

that makes sense..

I will put and chech if that works. thanks.

actually, no this is a different topic, an issue that I still struggle with.

does anyone has any recommendation on a stable DS1037 library?