News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

A happy ending

Started by charliecoutas, Today at 02:39 PM

Previous topic - Next topic

charliecoutas

We have a 7 segment clock display on the ceiling above our bed (it saves having to lean over to see a bedside clock) and this morning, at 07.30 I leapt out of bed to make our breakfast. On returning, Lynda, sleepily eyed, asked why I was up at 06.30? (She had looked at her watch). The clock was one hour fast.

The clock is driven by a little GPS module. I got out of bed and looked at the heating controller which is also driven by the same GPS module. "Wednesday the 10th of March 2007" it said. Having seen this before on another GPS module, I knew what it was. I am writing this up because it is surely bound to happen to some forum members at some time in the future. The problem is this:

The bright sparks who designed the GPS receivers decided that a 10 bit week counter would be enough. 1024 weeks is long enough not to bother anyone. Well no, 1024 weeks is 19.2 years so every 19.2 years the day, month and years will be wrong from then on. I think it's also known as an Epoch Error.

The solution last time was to root around in my Aladins cave and find another GPS module. But this time I reasoned that simply adding 19.2 years on to the (wrong) reported date would fix it. I found a few algorithms on the web and converted one from C to Positron. To my surprise it worked second time and I offer the code below. The brackets look a bit dangerous but Positron obviously handles the lack of brackets in the same way that C does. It will go wrong again in another 19.2 years but I don't care.

So get the day of month, month and year from the dicky GPS module and convert it to Julian days (the number of days since Julian Clary was born). Add 1024 weeks-worth days (7168) then de-convert it back again. There weren't many comments in the code I found but it works. I have probably used DWord where Word would do but I played safe):


; Get GPS data into:- Day_in_month, Month_no, Year_no. Jnd is the number of Julian days

    Calc_Julian()                             ;convert the wrongly reported date to "Julian days"
    Jdn = Jdn+7168                            ;Add 1024 weeks in days
    Reverse_Julian()                          ;convert back to corrected date   

Dim Ja      As Dword                          ;workspace
Dim Jy      As Dword                          ;year number
Dim Jm      As Dword                          ;month number
Dim Jdn     As Dword                          ;day in month number
   
Proc Calc_Julian()
    Ja = (14-Month_no)/12
    Jy = Year_no + 4800 - Ja
    Jm = Month_no + 12 * Ja - 3
    Jdn = Day_in_month + (153 * Jm + 2) / 5 + 365 * Jy + Jy / 4 - Jy / 100 + Jy / 400 - 32045
EndProc

Dim Jf As Dword
Dim Je As Dword
Dim Jg As Dword
Dim Jh As Dword

Proc Reverse_Julian()
    Jf = Jdn + 1401 + (((4 * Jdn + 274274) / 146097) * 3) / 4 - 38
    Je = 4 * Jf + 3
    Jg = (Je//1461) / 4
    Jh = 5 * Jg + 2
    Day_in_month = (Jh//153) / 5 + 1
    Month_no = (Jh / 153 + 2)//12 + 1
    Year_no = Je / 1461 - 4716 + (14 - Month_no) / 12
EndProc

▲