DS3231, UNO and unixtime

Hi to all,

I have a strange effect and no explanation:

Last week I adjusted manually (by means of a sketch) a DS3231 RTC (the base of my adjustment was an atomic clock on the internet, so the data should be correct).

Beginning of this week I connected the RTC to an UNO and loaded the following sketch:

#include <TimeLib.h>        //http://www.arduino.cc/playground/Code/Time 

#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
#include <DS3231.h>       //Jarzebski DS3231


DS3231 clock;
RTCDateTime dt;

uint32_t syncProvider()
{
  dt = clock.getDateTime();
  return dt.unixtime;
//  return dt.unixtime + 3600;
//there may be issues with the library's unix time and daylight or summer time and I had to add 1 hour //to match my rtc settings
}

void setup(void)
{
  Serial.begin(9600);
  Wire.begin();
  clock.begin();
 
  setSyncProvider(syncProvider);   // 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");      
}

void loop(void)
{
  dt = clock.getDateTime();
  timeDateDisplay();  
  delay(1000);
}

void timeDateDisplay(void)
{
  Serial.print("Unixtime from RTC:   ");
  Serial.println(clock.dateFormat("U", dt));
  Serial.print("Long number format:          ");
  Serial.println(clock.dateFormat("d-m-Y H:i:s", dt));
  Serial.println();
  Serial.print("Unix Time  directly from UNO : ");
  Serial.println(now());
  Serial.print(hour());
  printTime(minute());
  printTime(second());
  Serial.print(' ');
  Serial.print(day());
  printDate(month());
  printDate(year());
  Serial.println();
  Serial.println();
}

void printTime(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}
void printDate(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print('-');
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

When I run the sketch, the unixtime from both, RTC and UNO is the same (differs maybe by one second), but the output in readable text is correct when reading from the RTC, but 23 hrs advanced when reading from the UNO:

RTC has set the system time
Unixtime from RTC:   1455975283
Long number format:          19-02-2016 14:34:43

Unix Time  directly from UNO : 1455975283
13:34:43 20-02-2016

Unixtime from RTC:   1455975284
Long number format:          19-02-2016 14:34:44

Unix Time  directly from UNO : 1455975284
13:34:44 20-02-2016

Unixtime from RTC:   1455975285
Long number format:          19-02-2016 14:34:45

Unix Time  directly from UNO : 1455975285
13:34:45 20-02-2016

Unixtime from RTC:   1455975286
Long number format:          19-02-2016 14:34:46

Unix Time  directly from UNO : 1455975286
13:34:46 20-02-2016

Is there any logical explanation? (of course there is one…and most probably a simple one , the whole week i searched in the internet, learned a lot about unixtime, but did not find a hint to my problem…)

I do not think there is a problem with the time-zone, as the RTC has been set to MEZ, and 23 hrs are quite a bit. I also do not think, that the UNO is the reason, I did not yet try the whole thing with another model.

have a nice day

piqueremy

is it such a silly question that nobody will explain???

piqueremy

Piqueremy: is it such a silly question that nobody will explain???

piqueremy

Chill out. This is a global forum, so some people are sleeping when you post. I'm in China, how many hours different do you think my time zone is?

Try using these libraries instead. They are rock solid. https://github.com/JChristensen/DS3232RTC https://github.com/PaulStoffregen/Time

Hi,

thank you for your answer. Maybe you didn't realize when I posted my initial question...

I will try the libraries you recommend - but another stupid question - how can I replace the original TIME-library by the one you indicate? I tried it once, but the compiler used always the original library instead of the new one.

have a nice day

piqueremy

If it is in your sketches library folder, you can just delete the Timelib folder there.

May I add also this library to the list:

https://github.com/JChristensen/Timezone

Piqueremy: I do not think there is a problem with the time-zone, as the RTC has been set to MEZ, and 23 hrs are quite a bit. I also do not think, that the UNO is the reason, I did not yet try the whole thing with another model.

I think the same. If the RTC has been set to run in a fixed time zone like UTC or UTC+1, you typically never run into trouble, no matter what time format you might need in your application,

Your application will need two different time formats? 1. Unixtime 2. Local time in human readable form Right?

Typically there is just a small problem if you want the time in human readable form automatically adjusted between "standard time and "Daylight Saving time (summertime), with ther local time one hour in front of the actual time during summer months (i.e. UTC+2 summertime instead of UTC+1 during winter months).

But your actual problem is not about summertime/wintertime conversion, it is about unixtime and human readable time conversion? Despite of having ready-to-use-conversion functions in the different third-party libraries you are including and using in your sketch?

Well,

my problem is that the same UNIX-time ist translated in two different human-raedable times. I tried now the time -library recommended by aarg (as I wanted to keep the DS3231-library, cause the result from this reading is correct),and it changed the other way round - but I have no explanation

RTC has set the system time
Unixtime from RTC:   1457369200
Long number format:          08-03-2016 17:46:40

Unix Time  directly from UNO : 1457369200
16:46:40 7-03-2016

Unixtime from RTC:   1457369201
Long number format:          08-03-2016 17:46:41

Unix Time  directly from UNO : 1457369201
16:46:41 7-03-2016

Unixtime from RTC:   1457369202
Long number format:          08-03-2016 17:46:42

Unix Time  directly from UNO : 1457369202
16:46:42 7-03-2016

Unixtime from RTC:   1457369203
Long number format:          08-03-2016 17:46:43

Unix Time  directly from UNO : 1457369203
16:46:43 7-03-2016

As you can see, the date and time derived from the UNIX-time of RTC is still correct (today..), but the date and time derived from the same UNIX-time in the UNO is 23 hrs behind (in my last example it was 23 hrs. ahead). What the h... is going on here????? Or am I too stupid to understand???

piqueremy

I can not replicate your problem when I use the Christensen library with the Time library. I’ll download the Jarzebski library and see what I get.

#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
#include <Time.h> //http://www.arduino.cc/playground/Code/Time  
//#include <TimeLib.h>  //new name for Time Library
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)

tmElements_t tm;

void setup(void)
{
  Serial.begin(9600);
  Serial.println("DS3231RTC/Time Library Unix Time Test");
  setSyncProvider(RTC.get);// the function to get the unix time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
  Serial.println();

}

void loop()
{

  Serial.println();
  displayAVR_Time();
  displayRTC_Time();
  Serial.println();

  delay(1000);
}

void displayRTC_Time()
{
  //read time from RTC
  int status = RTC.read(tm); //TimeElements variable
  Serial.print("Ok, RTC Time = ");
  print2digits(tm.Hour);
  Serial.write(':');
  print2digits(tm.Minute);
  Serial.write(':');
  print2digits(tm.Second);
  Serial.print(", Date (D/M/Y) = ");
  Serial.print(tm.Day);
  Serial.write('/');
  Serial.print(tm.Month);
  Serial.write('/');
  Serial.print(tmYearToCalendar(tm.Year));
  Serial.println();
  //unix time
  Serial.print("Unix Time ");
  Serial.println(RTC.get());
}

void displayAVR_Time(void)
{
  // digital clock display of the time from Arduino clock time library
  Serial.print("Ok, AVR Time = ");
  Serial.print(hour());
  Serial.write(':');
  print2digits(minute());
  Serial.write(':');
  print2digits(second());
  Serial.print(", Date (D/M/Y) = ");
  Serial.print(day());
  Serial.print('/');
  Serial.print(month());
  Serial.print('/');
  Serial.print(year());
  Serial.println();
  Serial.print("Unix Time ");
  Serial.println(now());
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}
DS3231RTC/Time Library Unix Time Test
RTC has set the system time


Ok, AVR Time = 17:29:53, Date (D/M/Y) = 8/3/2016
Unix Time 1457458193
Ok, RTC Time = 17:29:53, Date (D/M/Y) = 8/3/2016
Unix Time 1457458193


Ok, AVR Time = 17:29:54, Date (D/M/Y) = 8/3/2016
Unix Time 1457458194
Ok, RTC Time = 17:29:54, Date (D/M/Y) = 8/3/2016
Unix Time 1457458194


Ok, AVR Time = 17:29:55, Date (D/M/Y) = 8/3/2016
Unix Time 1457458195
Ok, RTC Time = 17:29:55, Date (D/M/Y) = 8/3/2016
Unix Time 1457458195

This sketch demonstrates that the Jarsebski library treatment of Unix time is broken. There’s a misssing 90000 seconds(25 hours). I’m not going to go through the library in detail to determine exactly why. I leave that task to you. :slight_smile:

#include <Wire.h>

//Jarzebski
#include <DS3231.h>
DS3231 clock;
RTCDateTime dt;

//Christensen
#include <DS3232RTC.h>
tmElements_t tm;

#include <Time.h> //http://www.arduino.cc/playground/Code/Time  
//#include <TimeLib.h>  //new name for Time Library

void setup()
{
  Serial.begin(9600);

  // Initialize DS3231
  Serial.println("Initialize DS3231");;
  clock.begin();
}

void loop()
{
  displayJarsebski_Time();
  displayChristensen_Time();
  
  Serial.println("set Jarsebski value of unix time");
  setTime(dt.unixtime);
  displayTimeLibrary_Time();

  Serial.println("set Christensen value of unix time");
  setTime(RTC.get());
  displayTimeLibrary_Time();
  
  delay(1000);
}

void displayJarsebski_Time()
{
  dt = clock.getDateTime();
  Serial.print("Jarsebski Raw data: ");
  Serial.print(dt.year);   Serial.print("-");
  Serial.print(dt.month);  Serial.print("-");
  Serial.print(dt.day);    Serial.print(" ");
  Serial.print(dt.hour);   Serial.print(":");
  Serial.print(dt.minute); Serial.print(":");
  Serial.print(dt.second); Serial.println("");
  Serial.print("Unix Time  ");
  Serial.println(dt.unixtime);
  Serial.println("************");
}

void displayChristensen_Time()
{
  //read time from RTC
  int status = RTC.read(tm); //TimeElements variable
  Serial.print("Christensen Time = ");
  print2digits(tm.Hour);
  Serial.write(':');
  print2digits(tm.Minute);
  Serial.write(':');
  print2digits(tm.Second);
  Serial.print(", Date (D/M/Y) = ");
  Serial.print(tm.Day);
  Serial.write('/');
  Serial.print(tm.Month);
  Serial.write('/');
  Serial.print(tmYearToCalendar(tm.Year));
  Serial.println();
  //unix time
  Serial.print("Unix Time ");
  Serial.println(RTC.get());
  Serial.println("************");
}

void displayTimeLibrary_Time(void)
{
  Serial.print("TimeLibrary Time = ");
  print2digits(hour());
   Serial.write(':');
  print2digits(minute());
   Serial.write(':');
  print2digits(second());
   Serial.write(':');
  Serial.print(' ');
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year()); 
  Serial.println(); 
  Serial.print("Unix Time ");
  Serial.println(now());
  Serial.println("************");
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}
Jarsebski Raw data: 2016-3-8 20:30:54
Unix Time  1457379054
************
Christensen Time = 20:30:54, Date (D/M/Y) = 8/3/2016
Unix Time 1457469054
************
set Jarsebski value of unix time
TimeLibrary Time = 19:30:54: 3/7/2016
Unix Time 1457379054
************
set Christensen value of unix time
TimeLibrary Time = 20:30:54: 3/8/2016
Unix Time 1457469054
************

cattledog: This sketch demonstrates that

A DS3231 internally is working with two-digit-years in the year register, so if you set the date to 08/3/16, you will have to configure whether this date actually is 08/03/1916 or 08/03/2016

In your sketch I don't see such a configuration setting, so you leave it up to the libraries whether they interpret year xx as year 19xx or 20xx?

Time Zone handling in your demonstration sketch is the same mess: I's not existing!

So most lkely you set your RTC to UTC time and run it in UTC time only, right?

tIME ZONE handling is not existing and century handling is not existing and left to the libraries used and their default settings, so if using different libraries they might treat centuries from 2-digit RTC different: One is treating year 00 as1900 the next one as 2000, and your sketch just don't cares about, but expects everything works flawlessly from and to 2/4 digit year conversion and the RTC module?

Time zone does not matter in your applications in any way?

Yes. For those reasons, it is a reasonable policy to use the same library to set the RTC time, as you do to read it.

aarg: Yes. For those reasons, it is a reasonable policy to use the same library to set the RTC time, as you do to read it.

Even when using the same library for reading and writing date to/from RTC, it is NOT a no-brainer and you have to test reading/writing RTC date.

4-digit-year to 2-digit-year converion is typically always done by cutting the century digits. So every library should convert 1916 o 16 and also 2016 to 16 in a two-digit year conversion.

But the other way round from 2-digit-year to 4-digit-year may be unpredictable.

While nowadays software will most likely add 2000 years for 4-digit-year converion, 20 years ago most softwarejust added 1900 years to convert a 2-digit-year into a 4-digit-year.

tIME ZONE handling is not existing and century handling is not existing and left to the libraries used

That's why advice was given to use the Christensen library. It plays well with the Time Library, and I have never seen any of the issues with it that the OP reported when using the Jarsebski library.

If the OP, or you, think it is solid and a good choice for a DS3231 in conjuction with the the Time Library after explicitly dealing with time zone and century, then you are free to use it. :)

cattledog: That's why advice was given to use the Christensen library. It plays well with the Time Library, and I have never seen any of the issues with it that the OP reported when using the Jarsebski library.

If he, or you, think it is solid and a good choice for a DS3231 in conjuction with the the Time Library after explicitly dealing with time zone and century, then you are free to use it. :)

Times are a changing all the time, aren't they?

I think it is just two years ago that nobody in this forum was discussing a bout "Jarsebski library" or "Christensen library" but nearly everybody here was recommending a "Michael Margolis 2009"time library.

So favourite time libraries used by Arduino forum users change as well as the time itself changes over time. ;) "

Well,

now I tried the "Christensen library" -and it works pefectly. I did (not yet) check where the error is in the "Jarsebski library" - for the time being I'm glad to have a problem solved - thanks a lot to all!

Now I'm struggling with another issue - is there a way to detect a connected RTC resp. to detect that NO working RTC is connected (e.g. in the case of an exhausted battery, broken wires etc). With the different libraries the first RTC.Get hangs forever if there is no RTC and doesn' issue any hint, what's wrong. I guess it's the call of "i2cEndTransmission()" in the "DS3232RTC::read(tmElements_t &tm)", but there my wisdom ends. Is there any possibility to implement a return-code after a timeout?

With the different libraries the first RTC.Get hangs forever if there is no RTC and doesn' issue any hint, what's wrong.

The issue of hangs due to the while loops in the wire (twi) library is well known. There is an alternative library for the master. http://www.dsscircuits.com/articles/arduino-i2c-master-library

Ther is more information about it on the Nick Gammon i2c page. http://www.gammon.com.au/i2c

Alternative I2C library

Some people have reported on the Arduino forum that I2C "hangs" under certain circumstances. This may well be because the inbuilt "Wire" library expects certain interrupts to happen, and loops until they do. If the interrupt is lost, the library hangs.

An alternative library is described here:

http://dsscircuits.com/articles/arduino-i2c-master-library

In case that site ever goes down, a copy of the the actual library zip file is here:

http://www.gammon.com.au/Arduino/I2C_Rev5.zip

Note that this is a library for the "master" end only, not the slave.

An exhausted battery would not cause a failure of the I2C read. Here's a snippet from one of my clock programs:

    if (not RTC.oscStopped(not RESET_OSC_STOPPED_FLAG))
    {
      utc = RTC.get(); //Get RTC time

If it fails, the display shows a "!set" message. The RTC is designed so that even a momentary loss of backup power will set the oscillator stopped flag. In most schemes, you have to set the time to clear it. I don't know about the other libraries, but the JC library gives you a choice of clearing it or not when it's checked, as you can see above. It is cleared any time the time set method is called.

While I am not defending the oversight of allowing a hardware interface to hang the system on a failure to respond, I would like to point out that hardware failures are a hardware problem. If you are worried about those wires breaking, you should design them so they don't break. Really, there are many hardware problems that can freeze the program. Loss of power for example. :)

Also, a reporting interface places a responsibility of handling on the programmer. What do you want to do if the RTC read fails? Try again? Stop? Report something? It's up to you. It's good to have choices, but sadly, many lazy programs don't even bother to look at status codes that are returned. A hardware failure in an embedded device usually means that the designer has failed. A complete shutdown of the system can be appropriate, as the only appropriate response may be to return it into the hands of the designer.

But since a battery change is something predictable, and has a simple solution that the user can fix, it would not be good to just freeze. So it's nice that the system doesn't just freeze, so I can at least report an error.

Well again a big THANKS to all, this alternative library solved my problems. It would be nice, if this (already rather old) library could be impemented as a standard in the IDE.

@ aarg: As a longtime hobby and professional programmer (40+ years) I became a strict follower of Murphy's law and try to anticipate all human or technical failures which might influence my programs.So even in the case of a broken wire or a corroded contact, I know at least, there is something wrong and can figure out other solutions (e.g. switch to a second RTC ). Of course, the programs will grow with the implementation of all eventualities - but for the sake of almost faultless execution, I do not want to blame others ("Hardware") for faults, I can mostly (mostly...) overcome (or at least where I can issue an alarm). And in my specific case a hanging call to a RTC doesn't issue anything with the usual libraries - so I cannot react...

So once again a THANK YOU and I think we can close the post...