DS3231 Strange behaviour while setting time

Hello all!

So I have DS3231 chinese board which I ordered from Ebay.

I have a new battery installed and if I set time, disconnect the RTC and reconnect it few minutes later the time reading matches what it should. So internal oscillator must be running fine.

Also if I set time from my program using buttons and the same SetTime-function the new time gets correctly updated to the RTC module and everything works even after reboot/recompiling and uploading the code.

However if I directly put this line in my code in the setup section:

void setup()
{
	Serial.begin(115200);
	Wire.begin();

	clock->Begin();

	clock->setTime(0,0,0);
}

void Clock::setTime(int second, int minute, int hour)
{
	_time[SECOND] = constrain(second, 0, 59);
	_time[MINUTE] = constrain(minute, 0, 59);
	_time[HOUR] = constrain(hour, 0, 23);

	setExternalDateTime();
}

void Clock::setExternalDateTime() {

	byte second = _time[SECOND]; //0-59
	byte minute = _time[MINUTE]; //0-59
	byte hour = _time[HOUR]; //0-23
	byte weekDay = 7; //1-7
	byte monthDay = _date[DAY]; //1-31
	byte month = _date[MONTH]; //1-12
	byte year = _date[YEAR]; //0-99
	byte normalMode = 24;

	Wire.beginTransmission(DS3231_I2C_ADDRESS);
	Wire.write(ZERO); 
	Wire.write(decToBcd(second));
	Wire.write(decToBcd(minute));
	Wire.write(decToBcd(hour));
	Wire.write(decToBcd(weekDay));
	Wire.write(decToBcd(monthDay));
	Wire.write(decToBcd(month));
	Wire.write(decToBcd(year));
	Wire.endTransmission();
	
	_externalResyncNeeded = true;
}

Here is the strage thing which I am unable to comprehend:

  1. First I run the code with SetTime(0,0,0) written in Setup-function.
  2. RTC get new time correctly and polling confirms that RTC now holds our set time of 0,0,0 and starts counting up as it should
  3. I comment out the SetTime(0,0,0) from Setup function and reupload the code.
  4. The clock starts again counting from 0,0,0.

And the thing is that it is not always 0,0,0 where it starts but it will start from point whatever I put in SetTime-function in step 1. What even could cause thing like this as the code should be commented out?

This is only a small problem as everything seems to work normally if I use my devices keyboard to set the time instead of hard coded SetTime(...) code in setup function. Would be nice to understand what is happening though.

This is the debugging code I use to set the time with device's keyboard. To me this is exactly the same as my earlier example as both use the same SetTime function.

if (button == DIR_ENT) {
	clock->setTime(clock->second() + 10, clock->minute(), clock->hour());
	button = DIR_NONE;
}

http://bildr.org/2011/03/ds1307-arduino/
Time is pre-entered. Start is on release of the reset button.

Nick_Pyner:
Do You Have The Time? DS1307 RT Clock + Arduino – bildr
Time is pre-entered. Start is on release of the reset button.

I am unsure what you mean by that link. I have different IC, the DS3231, and according to the datasheet there are differences between these two although they are similar. Biggest one being the oscillator stop/start bit on register 0x0.

And maybe I was unclear about my "problem" but the DS3231 seems to be working just fine generally. Almost everything is as expected but I am having a hard time understanding what could cause the strage behavior.

Can I2C line hold the old data there and flush everything into the bus when recompiling/uploading of the code is initiated? I was thinking something like this because when I disconnect the I2C lines from DS3231 during the upload process and connect it back again after upload has finished the clock holds the value I gave it on earlier start-function SetTime(...) + time that has passed since.

Post your complete code.

The link can be used for both DS1307 and DS3231 - no changes required. I'm afraid I don't understand the last para, and I can't even begin to think why you would want to disconnect I2C lines. I note that you put quotes around "problem", which is probably the correct thing to do.

I believe the code you posted is more or less the same as the timesetting code I linked to

gfvalvo:
Post your complete code.

Well we can observe the same phenomenon with the example code Nick_Pyner linked

#include <Wire.h>
#define DS1307_ADDRESS 0x68
byte zero = 0x00; //workaround for issue #527

void setup(){
Wire.begin();
Serial.begin(115200);
setDateTime(); //MUST CONFIGURE IN FUNCTION
}

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

void setDateTime(){

byte second = 45; //0-59
byte minute = 40; //0-59
byte hour = 0; //0-23
byte weekDay = 2; //1-7
byte monthDay = 1; //1-31
byte month = 3; //1-12
byte year = 11; //0-99

Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero);

Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekDay));
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(zero);
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 weekDay = bcdToDec(Wire.read()); //0-6 -> sunday – Saturday
int monthDay = bcdToDec(Wire.read());
int month = bcdToDec(Wire.read());
int year = bcdToDec(Wire.read());

//print the date EG 3/1/11 23:59:59
Serial.print(month);
Serial.print("/");
Serial.print(monthDay);
Serial.print("/");
Serial.print(year);
Serial.print(" ");
Serial.print(hour);
Serial.print(":");
Serial.print(minute);
Serial.print(":");
Serial.println(second);

}

So when I initially set the time to DS3231 and let the program run for a moment I get following output to serial monitor:

3/1/11 0:40:45
3/1/11 0:40:46
3/1/11 0:40:47
3/1/11 0:40:48
3/1/11 0:40:49
3/1/11 0:40:50
3/1/11 0:40:51
3/1/11 0:40:52
3/1/11 0:40:53
3/1/11 0:40:54
3/1/11 0:40:55
3/1/11 0:40:56
3/1/11 0:40:57
3/1/11 0:40:58
3/1/11 0:40:59
3/1/11 0:41:0
3/1/11 0:41:1
3/1/11 0:41:2
3/1/11 0:41:3
3/1/11 0:41:4
3/1/11 0:41:5
3/1/11 0:41:6
3/1/11 0:41:7
3/1/11 0:41:8
3/1/11 0:41:9
3/1/11 0:41:10
3/1/11 0:41:11
3/1/11 0:41:12
3/1/11 0:41:13
3/1/11 0:41:14
3/1/11 0:41:15
3/1/11 0:41:16
3/1/11 0:41:17
3/1/11 0:41:18
3/1/11 0:41:19

Note that the clock started at 0:40:40 and has now advanced to 0:41:19.

Next step I just comment out the setDateTime(); at row 8. I would expect the clock retain its time and start again outputting to serial monitor as soon as Arduino Uno finishes its reboot. Also I would expect the clock to be few seconds more than what it was when I uploaded this new modified code. However every time I get this output:

3/1/11 0:40:49
3/1/11 0:40:50
3/1/11 0:40:51
3/1/11 0:40:52
3/1/11 0:40:53
3/1/11 0:40:54
3/1/11 0:40:55
3/1/11 0:40:56
3/1/11 0:40:57
3/1/11 0:40:58
...

So clock starts again from what the SetDateTime function set before + few seconds, even though it has now been commented out.

Another note is that if I now just upload the same code again the clock will not reset and continues from where it was before reupload.

Nick_Pyner:
The link can be used for both DS1307 and DS3231 - no changes required. I'm afraid I don't understand the last para, and I can't even begin to think why you would want to disconnect I2C lines. I note that you put quotes around "problem", which is probably the correct thing to do.

I believe the code you posted is more or less the same as the timesetting code I linked to

Yes you are right that it is the same code now that I read it through.

I disconnected I2C lines just to see what would happen. So I disconnected them before uploading the version of the code with commented out SetDateTime() row. I really dont know what causes that or what I dont now understand about this. To me this should be pretty darn simple!

Quotes around the problem was a reference to my earlier comment about the behavior only happening when I comment out the SetDateTime() not if I set the time from some user input within the code. Therefore this problem really is not that big deal. I just wanted to understand what causes this.

Jonttup88:
I disconnected I2C lines just to see what would happen. To me this should be pretty darn simple!

Yes indeed, and it certainly is dumb too. The clock communicates with Arduino via the I2C bus. Disconnect the I2C means no communication - just what everybody needs. I'm sure there is no point in asking what the expectation could be from such a futile exercise.

It is not clear that you are aware that there are two programmes - one to set the time, and the other to read it. There is no need to comment out anything. You just don't use the timesetting code in your normal working programmes.

Nick_Pyner:
Yes indeed, and it certainly is dumb too. The clock communicates with Arduino via the I2C bus. Disconnect the I2C means no communication - just what everybody needs. I'm sure there is no point in asking what the expectation could be from such a futile exercise.

It is not clear that you are aware that there are two programmes - one to set the time, and the other to read it. There is no need to comment out anything. You just don't use the timesetting code in your normal working programmes.

Well my expectation was to see whether it helps or not and I was right. The clock didn't get reset as it would have if the I2C lines were connected during upload process of code where SetDateTime was commented out. I reconnected them afterwards and the clock resumed where it should have.

What is your expectation of what happens when we run the code from your link? Because if you think that running second code sets the time and then uploading the first code just polls the time then read post #5 in this thread. Expected result is not what we get.

Actually did you even read the text I wrote? Because even in the link you pasted here it is mentioned that "So after you have set it, either upload the above code, or comment out setDateTime from setup, and re-upload the sketch." see? ...COMMENT OUT...

As I wrote above I just did that and still the clock resets to what was hard coded time before. You do realise that if row 8 is commented out the code runs the same as the first example.

So clock starts again from what the SetDateTime function set before + few seconds, even though it has now been commented out.

Another note is that if I now just upload the same code again the clock will not reset and continues from where it was before reupload.

As I wrote above I just did that and still the clock resets to what was hard coded time before. You do realise that if row 8 is commented out the code runs the same as the first example.

I certainly can not confirm your experience, and the code performs as expected for me.

I have no idea what is the cause of the problem you are seeing.

Perhaps there something is wrong with your ide/environment, and the updated code is not being sent to the Arduino each time.

If you play around with the blink example, and you change the blink times, can you see the changes each time you upload the code?

cattledog:
I certainly can not confirm your experience, and the code performs as expected for me.

I have no idea what is the cause of the problem you are seeing.

Perhaps there something is wrong with your ide/environment, and the updated code is not being sent to the Arduino each time.

If you play around with the blink example, and you change the blink times, can you see the changes each time you upload the code?

Oh then this is even more cryptic what I thought! I initially just thought that I made some mistake or I that I have missed some simple thing.

Problems wit IDE/environment sounds like a plausible thing as I have tested multiple times and the results are always the same. Also I have now uploaded dozens and dozens of code changes to this Uno unit and not a single time it has failed. I also tested with another DS3231 unit and the results are the same.

Anyway thank you very much for testing it yourself and giving me some kind of "closure". As I tried to explain this is not a huge problem overall.