RTC RESET via software

Dear all,

problems> 1)When i working with DS1307 . I found that time has hanged at particular time. Is it possible to avoid hang operation through software. I have used external reset pin to reset RTC it worked. But i wanna know whether it possible to reset via software.If any changes to be made in below code let me know

2)while uploading below program, i found that date and time not get set properly . Let me know the reason for behaviour of RTC. once it properly writes woks properly .

example code for rtc write given below.

#include"Wire.h"

#define DS1307_ADDRESS 0x68
byte zero = 0x00; //workaround for issue #527

void setup(){
  Wire.begin();
  Serial.begin(9600);
 // rtc.Set_Time(13,36,0);
  // rtc.Set_Date(2013,3,4);
 setDateTime(); //MUST CONFIGURE IN FUNCTION
}

void loop(){
  
  printDate();
  delay(1000);
}

void setDateTime(){

  byte second =45; //0-59
  byte minute =59; //0-59
  byte hour =12; //0-23
  byte monthDay =12; //1-31
  byte month =3; //1-12
  byte year  =13; //0-99



 Wire.beginTransmission(DS1307_ADDRESS);

  Wire.write(zero); //stop Oscillator

  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.write(zero); //start

  Wire.endTransmission();

}

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

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

void printDate(){

  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);

  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS,7);

   int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time

  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

 /*  int second = 11;
  int minute =18;
  int hour = 18;
  int weekDay = 1;
  int monthDay = 2;
  int month = 11;
  int year = 12;
*/
  //print the date EG   3/1/11 23:59:59

  Serial.print(monthDay);
  Serial.print("/");
  
  
  Serial.print(month);
  Serial.print("/");
  
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

}

I have used external reset pin to reset RTC it worked.

The DS1307 doesn't have a RESET pin. How do you reset it by hardware? Why is it necessary to reset the chip?

The DS1307 is quite sensible to voltage drifts. Ensure you have a stable power source and your problems probably go away.

I'd move that wire.endTransmission() to the end of the wire.read() lines. Something like this:

tempaddr = 0x68;
  Wire.beginTransmission(tempaddr);
  Wire.write(0x00);
  Wire.endTransmission();                    // ****** I moved this line because it was in the wrong place as pointed out later in the thread
  Wire.requestFrom(int(tempaddr), 8);
  a = Wire.read();    // seconds
  b = Wire.read();    // minutes
  c = Wire.read();    // hour
  d = Wire.read();    // DOW (day of week)
  e = Wire.read();    // day of month
  f = Wire.read();    // month
  g = Wire.read();    // year
  h = Wire.read();    // sqwe 1hz 0x13
[s]  Wire.endTransmission();[/s]           //  It would be wrong to do this here

I had trouble when I read the device scores of times per second, it would eventually end up with the oscillator stopped. Don't know why, I just cut back the communications to it to a sensible rate and it seems to be ok now.

EDIT: I fixed the code above, it was incorrect. I have also fixed my program, maybe this was why I had the (extremely) intermittent issue with it stopping. I was also accessing a serial EEPROM on the same bus every time I accessed the DS1307.

Here is how I set the clock from hard coded values, until I added a better way to set it.

// Try to set the DS1307 clock

//  tempaddr = 0x68;
//  Wire.beginTransmission(tempaddr);
//  Wire.write(0x00);  // set address to 0
//  Wire.write(0x00);  // seconds in BCD
//  Wire.write(0x19);  // minutes in BCD
//  Wire.write(0x15);  // hours in BCD
//  Wire.write(0x06);  // day of week
//  Wire.write(0x15);  // date
//  Wire.write(0x02);  // month  
//  Wire.write(0x13);  // year
//  Wire.write(0x10);  // sq wave out 1HZ
//  Wire.endTransmission();

I'd move that wire.endTransmission() to the end of the wire.read() lines.

This is wrong. The wire.endTransmission finished a write operation. The write has to be done before the read to set the register address to read from. The original code is correct in this regard.

pylon:

I'd move that wire.endTransmission() to the end of the wire.read() lines.

This is wrong. The wire.endTransmission finished a write operation. The write has to be done before the read to set the register address to read from. The original code is correct in this regard.

Ok, well it seems to work ok the way that it is. Are you saying the OP doesn't even need a wire.endTransmission() at the end of his reads? Doesn't that just leave the bus hanging?

Ok, well it seems to work ok the way that it is. Are you saying the OP doesn't even need a wire.endTransmission() at the end of his reads? Doesn't that just leave the bus hanging?

No, I'm saying the OP needs the Wire.endTransmission() exactly where it is in his posted code, after the Wire.write(), before the Wire.requestFrom(). After the Wire.read()s he doesn't need it (he must not use it there) because the Wire.requestFrom() specifies how many bytes should be read from the device.

Ok, then I stand corrected. The datasheet is ridiculously vague about this. I looked at rtclib and it does what you say, so I assume that's correct. Still works the way I did it, go figure.

Still works the way I did it, go figure.

Your version may work in some cases in others it doesn't. Doing it your way does the write operation after the read completed. If that read/write combination is the only data sent to the device, it works because the write after the read is for the next block again a write before the read. But this is the exception and not the usual case.

The data written with the Wire.write() method is not sent to the device but put into a buffer. It is sent by the call to Wire.endTransmission() and not before. If you write more data than the buffer is in size (32 bytes) the rest will be discarded. You also get a description of this in the reference of the Wire library: http://arduino.cc/en/Reference/WireWrite

This is my fault for not bothering to look at the library to start with. I know about start, stop and rest of it, but didn't go look to see what happened with endTransmission. I just tried to make assumptions and move on. ;) I didn't know the writes got buffered up like that, I don't recall seeing that in the documentation online. I guess I'll go look at the code and see how it works.

This what have done : i have assigned pin to reset the RTC syntax: if pin is high rtc _write() else keep reading rtc _time()

Here time get reset to user date and time .

pylon:

I have used external reset pin to reset RTC it worked.

The DS1307 doesn't have a RESET pin. How do you reset it by hardware? Why is it necessary to reset the chip?

The DS1307 is quite sensible to voltage drifts. Ensure you have a stable power source and your problems probably go away.

please let me know . is it possible to reset the ds1307 if it get hanged. If yes , how we do that for above code.

pylon:

Still works the way I did it, go figure.

Your version may work in some cases in others it doesn't. Doing it your way does the write operation after the read completed. If that read/write combination is the only data sent to the device, it works because the write after the read is for the next block again a write before the read. But this is the exception and not the usual case.

The data written with the Wire.write() method is not sent to the device but put into a buffer. It is sent by the call to Wire.endTransmission() and not before. If you write more data than the buffer is in size (32 bytes) the rest will be discarded. You also get a description of this in the reference of the Wire library: http://arduino.cc/en/Reference/WireWrite

AMPS-N:
please let me know . is it possible to reset the ds1307 if it get hanged. If yes , how we do that for above code.

When you say it “hangs” do you mean it stops counting time seconds or does it completely stop responding to I2C communications. I have had mine get the first bit set in the seconds register which stops the clock, but it isn’t hung. It just stops incrementing time.

If you need an external reset, then you will have to use an I/O pin to power the 1307.

yes it stop completly counting time seconds.It will completely stop responding.Even-through i press reset button of arduino ,it didn't worked. How come out of this problem??

some time i observed that once i upload code every parameter getting update expect date part. Please let me know why it is doing that.

afremont:

AMPS-N: please let me know . is it possible to reset the ds1307 if it get hanged. If yes , how we do that for above code.

When you say it "hangs" do you mean it stops counting time seconds or does it completely stop responding to I2C communications. I have had mine get the first bit set in the seconds register which stops the clock, but it isn't hung. It just stops incrementing time.

If you need an external reset, then you will have to use an I/O pin to power the 1307.

AMPS-N: yes it stop completly counting time seconds.It will completely stop responding.Even-through i press reset button of arduino ,it didn't worked. How come out of this problem??

some time i observed that once i upload code every parameter getting update expect date part. Please let me know why it is doing that.

If it stops responding on the I2C bus, then that's a problem. I believe there is way to reset at least some devices from software, but I don't know if it will work for the 1307.

After an interruption in protocol, power loss or system reset, any 2-
wire part can be reset by following these steps:
(a) Clock up to 9 cycles, (b) look for SDA high in each cycle while SCL is high and then
(c) create a start condition as SDA is high.

As for your date setting, you are not clocking enough bytes out. You left out one of the fields after the hours (weekDay). You have to send 9 bytes, you are only sending 8. Also your comment is wrong on the first byte clocked out. It sets the register address that is going to be accessed, that is why it is a 0. The second byte transmitted would set the seconds register and could also stop the clock oscillator if you set the most significant bit. Look at my example for setting the date, it is correct to the best of my knowledge. It does work.

Do you have pull-up resistors?

As for I2C:

http://gammon.com.au/i2c

Can you able to post the code after editing. I am not understanding below points which specified in my code

As for your date setting, you are not clocking enough bytes out. You left out one of the fields after the hours. You have to send 9 bytes, you are only sending 8. Also your comment is wrong on the first byte clocked out. It sets the register address that is going to be accessed, that is why it is a 0. The second byte transmitted would set the seconds register and could also stop the clock if you set the most significant bit. Look at my example for setting the date, it is correct to the best of my knowledge. It does work.

Yes i have pull off resistor. it work fine for week . after 1 week it will get hang @ particular time.

[quote author=Nick Gammon link=topic=153785.msg1154338#msg1154338 date=1363158441] Do you have pull-up resistors?

As for I2C:

http://gammon.com.au/i2c [/quote]

You need to send weekDay when you set the clock. You are not sending it, causing the following fields to get wrong data. In my first post in this thread, I have some code that will set the clock. I have also fixed my code that reads the clock. I haven't tested it yet.

  tempaddr = 0x68;
  Wire.beginTransmission(tempaddr);
  Wire.write(0x00);  // set address to 0
  Wire.write(0x00);  // seconds in BCD
  Wire.write(0x19);  // minutes in BCD
  Wire.write(0x15);  // hours in BCD
  Wire.write(0x06);  // day of week        DONT FORGET THIS
  Wire.write(0x15);  // date
  Wire.write(0x02);  // month  
  Wire.write(0x13);  // year
  Wire.write(0x10);  // sq wave out 1HZ  
  Wire.endTransmission();

AMPS-N: Yes i have pull off resistor. it work fine for week . after 1 week it will get hang @ particular time.

Hmm, does it always hang at the exact same time of day and day of week (eg. always Friday at 16:00), or exactly one week after restart? Or is it approximately a week?

No it will not exactly hang particular time of the week.we are keep observing data frequently .

afremont:

AMPS-N: Yes i have pull off resistor. it work fine for week . after 1 week it will get hang @ particular time.

Hmm, does it always hang at the exact same time of day and day of week (eg. always Friday at 16:00), or exactly one week after restart? Or is it approximately a week?