gps> system clock> rtc set> verify utility

I found a sketch named gps_rtc_updater that may or may not actually set an RTC. I discovered that there was far more information available to display that helps to understand the process, and to verify that various stages have been performed successfully.

my changes were to the display and formatting of both the code and the Serial monitor output; I made no modifications in the engine room.

if you have a working GPS and a DS3231 I2C this will:

sync to your GPS;
set the Time parameters for the Time library;
adjust the Time to your time zone and display the results;
convert Time format to RTC format;
write this time to the RTC;
display the information sent to the RTC;
read the RTC;
display the results;
compare the two, and tell you if it succeeded.

when I know this works, I will add an SD utility to make it a full service datalogger diagnostic tool.

what I need now is for people to try it on their GPS > RTC > clock and see if it sets your RTC time correctly. my RTC responds, but some things get set right, some get set randomly, and the year is consistently 16 years ago. this is not a good day to need a CR1220 in a very small town.

and I just thought of a couple of things to add.

posted as an attachment because it’s too big for code tags

Level_1_Diagnostic.ino (9.37 KB)

OK - I’ve got it working.

It seems to be consistently setting the RTC about 18 seconds fast, otherwise it looks OK. I haven’t looked at the code yet to see if I can spot the problem.

You really should specify exactly which libraries you are using and where you got them if they aren’t supplied with the IDE. I am using TinyGPS++ version 1.0.0 obtained from GitHub - mikalhart/TinyGPSPlus: A new, customizable Arduino NMEA parsing library.

I have found that I typically have to invoke the Time library as <TimeLib.h> and this program was no exception.

The DS3231 I2C address is 0x68 - I don’t see how that can be changed so I’m not sure where your 0x51 value came from.

I had to move the readDS3231time() function before setup(). I suppose a properly written prototype would also work.

Don

I still haven't looked at the code but I did read the output more carefully. I really question why anyone would express a Binary Coded Decimal value in decimal.

Output:

Finding GPS data


GPS raw time adjusted to EST: 15:04:51 25/12/2018 Day of week: 3 Tuesday

Arduino Time is set

Sending Time to RTC:
  second: 51    BCD second: 81
  minute: 4    BCD minute: 4
    hour: 15      BCD hour: 21
 weekday: 3    BCD weekday: 3
     day: 25       BCD day: 37
   month: 12     BCD month: 18
    year: 2018    BCD year: 102

Arduino Time written to RTC

Time read from the RTC: 15:04:51 25/12/2018 Day of week: 3 Tuesday

Checksum: GPS: 128 RTC: 128
Success!
Job Done

Don

It seems to be consistently setting the RTC about 18 seconds fast, otherwise it looks OK. I haven’t looked at the code yet to see if I can spot the problem.

I added 18 seconds to the adjustTime code to compensate for the fact that GPS satellites are not adjusted for the 18 leap seconds since 1980. it’s after the TIMEZONE * SECS_PER_HOUR on line 68.

I have found that I typically have to invoke the Time library as <TimeLib.h> and this program was no exception.

if you read Time.h, the entirety of Time.h is

#include <TimeLib.h>

the author of Time ceded Time to the TimeLib author

The DS3231 I2C address is 0x68 - I don’t see how that can be changed so I’m not sure where your 0x51 value came from.

it came from my I2C scanner. nothing happened when I tried 0x68. it responds to 0x51.

I had to move the readDS3231time() function before setup(). I suppose a properly written prototype would also work.

I really question why anyone would express a Binary Coded Decimal value in decimal.

because it’s there. because it’s part of the process. because I may want to reverse the process and see if the output of that process matches the input. because I might print raw data retrieved from the RTC. it’s a not yet completed diagnostic tool.

what I get:

GPS raw time adjusted to MST: 15:14:37 25/12/2018 Day of week: 3 Tuesday

Arduino Time is set

Sending Time to RTC:
second: 37 BCD second: 55
minute: 14 BCD minute: 20
hour: 15 BCD hour: 21
weekday: 3 BCD weekday: 3
day: 25 BCD day: 37
month: 12 BCD month: 18
year: 2018 BCD year: 102

Arduino Time written to RTC

Time read from the RTC: 15:10:20 25/12/2002 Day of week: 3 Tuesday

Checksum: GPS: 124 RTC: 87
Error. Checksum mismatch. Time Incorrect. Verify RTC wiring. Replace RTC battery

in my case, hour, month, day and day of week are consistently right, year is -16, hours and minutes random.

Are you sure you aren't using a PCF8563 RTC ?

You are probably using an older version of the IDE. Keep my other comments in mind after you update.

Don

apparently I fell into the eBay trap where everything is IIC I2C SPI WiFi even if it has no connectors. proper DS3231 ordered.

I'm surprised it worked as well as it did! It looks like not only is the data stored in different registers but it may also be stored in straight binary rather than in packed BCD.

Speaking of packed BCD.... Your conversions between BCD and Decimal seem a bit unusual since they don't take into account the 'packed' nature of the data. That may in fact be why the program almost worked.

A binary coded decimal digit consists of four bits. When you put two of them together in one eight-bit byte you now have packed BCD. These are still two individual numbers, they just happen to be stored next to one another. Converting these 8 bits to their decimal equivalent yields garbage. The fact that you can convert the garbage back to packed BCD doesn't make it stink any less.

So - going back to the output in reply #2 --> [color=blue]second: 51    BCD second: 81[/color]

To convert the decimal number 51 to BCD you treat the two digits separately - the decimal digit 5 converts to 0101 and the decimal digit 1 converts to 0001.

When you pack the two BCD values together you get a byte that looks like this --> 01010001

When you convert this binary value to decimal you get 81 but this is NOT the 'BCD second' it is the decimal equivalent of the packed BCD information which bears no legitimate relation to the original value of 51.

Does any of this make any sense to you?

PS - At least you cleaned up the Kiwi language from the original code.

Don

I took a closer look at what I wrote last night.

floresta:
. . .
Speaking of packed BCD… Your conversions between BCD and Decimal seem a bit unusual since they don’t take into account the ‘packed’ nature of the data. That may in fact be why the program almost worked.

The conversions are OK. That should have been obvious to me since I did successfully set my RTC!

I’m more familiar with the conversions that involve shifting and masking. Here’s a pilfered example:

// turns a standard byte into a BCD equivalent
byte DecToBcd(byte val)
{
   return( ((val/10) << 4) | (val%10) );
}

// turns a BCD-encoded byte back into a standard one
byte BcdToDec(byte bcd)
{
   return( ((bcd >> 4) * 10) + (bcd&0xF) );
}

A binary coded decimal digit consists of four bits. When you put two of them together in one eight-bit byte you now have packed BCD. These are still two individual numbers, they just happen to be stored next to one another. Converting these 8 bits to their decimal equivalent yields garbage. The fact that you can convert the garbage back to packed BCD doesn’t make it stink any less.
. . .

I stand by this part. After you have successfully converted your decimal number to BCD it makes absolutely no sense to express that resulting data as a different decimal number.

EDIT: Here’s a link to the whole article I got the above code from, it’s not long and is well written.

His take on my ‘garbage’ comment is: “If you’re ever using constants in your code which are BCD values, then it’s highly recommended that you use them in their hexadecimal form, as it’ll make it clearer what your code is doing.”

Don