Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 09:25 08 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : GPS Code

Author Message
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 12:11am 15 Aug 2016
Copy link to clipboard 
Print this post

Geoff's GPS code is excellent but as I discovered once you put OPTION EXPLICIT and OPTION DEFAULT NONE in, it breaks

For those that are new to Microbasic like I am I thought it might be helpful if I posted the corrected code

The code as it is works for GMT in the UK, but Australian DST settings are in the last function - just comment out the UK code and uncomment the DST code
Don't forget to set the timezone and USE DST sections correct for where you are.
Thanks to WhiteWizzard who helped me with the GMT section and Matherp for his help in understanding why certain sections didn't work and everyone else who helped

Hopefully it might be of some use to someone

[code]''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' GPS CODE '
' Geoff Graham, March 2014 '
' Modified by lew247 (15/08/2016)to include the OPTION statements '
'(Hope you don't mind Geoff) '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Configuration constants
OPTION EXPLICIT
OPTION DEFAULT NONE
DIM INTEGER TIMEZONE
DIM INTEGER USEDST
DIM INTEGER dms
DIM INTEGER dhs
DIM INTEGER dme
DIM INTEGER dhe
DIM INTEGER i
DIM INTEGER year
DIM INTEGER month
DIM INTEGER hour
DIM INTEGER sec
DIM INTEGER latitude
DIM INTEGER longitude
DIM INTEGER mins
DIM INTEGER min
DIM INTEGER yr
DIM INTEGER mth
DIM INTEGER hr
DIM INTEGER day
DIM STRING LINE1
DIM STRING LINE2
DIM STRING x,LAT_DEG,lat_min,lat_sec,long_deg,long_min,long_sec
DIM INTEGER md(12)
DIM STRING arg$(20)

' Configuration constants
TimeZone = 0.0 ' hours from GMT (+ or -)
UseDST = 1 ' set to 1 to enable daylight saving time (DST/GMT) adjust
dms = 3 ' the month that DST starts
dhs = 2 ' the hour that DST starts
dme = 10 ' the month that DST ends
dhe = 2 ' the hour that DST ends
DATA 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
FOR i = 1 TO 12: READ md(i): NEXT i
OPEN "COM1:9600" AS #1 ' open the GPS serial interface 9600 baud

' this is the main program loop, it never exits
'*********************************************************************************************
DO
KeepSearching:
DO
GetGPSRecord ' get a GPS record
LOOP UNTIL arg$(0) = "GPRMC" ' we only want the RMC record
IF arg$(2) <> "A" THEN ' "A" means valid record
print "Searching", " For Satellites" ' TEST ***DOES NOT PRINT THIS
GOTO KeepSearching ' go back and keep looking
ENDIF
' the GPS has the valid time

' first extract the elements of the date/time from the GPS record
year = VAL(RIGHT$(arg$(9), 2)) ' extract the date
month = VAL(MID$(arg$(9), 3, 2))
day = VAL(LEFT$(arg$(9), 2))
hour = VAL(LEFT$(arg$(1), 2)) ' extract the time
min = VAL(MID$(arg$(1), 3, 2))
sec = VAL(MID$(arg$(1), 5, 2))


' extract and format latitude (data element #3, ddmm.mmmm)
lat_deg$ = LEFT$(arg$(3), 2)
lat_min$ = MID$(arg$(3), 3, 2)
lat_sec$ = str$(cint(val(mid$(arg$(3), 5, 9)) * 60.0))
latitude = val(lat_deg$) + val(lat_min$) / 60.0 + val(lat_sec$) / 3600.0

' extract and format longitude (data element #5, dddmm.mmmm)
long_deg$ = LEFT$(arg$(5), 3)
long_min$ = MID$(arg$(5), 4, 2)
long_sec$ = str$(cint(val(mid$(arg$(5), 6, 10)) * 60.0))
longitude = val(long_deg$) + val(long_min$) / 60.0 + val(long_sec$) / 3600.0


' convert the time to minutes since midnight 1st Jan 2014
' then add/subtract the timezone and if required add daylight saving
' this calculation takes just 15mS at 40MHz
mins = GetMins(year, month, day, hour, min)
mins = mins + TimeZone * 60 ' adjust for the timezone
If mins < GetDST(year, dme, dhe) OR mins > GetDST(year, dms, dhs) THEN
mins = mins + 60 'adjust for AWST DST
EndIf
ENDIF

' because we will display the time at the start of the next second
' we have to add 1 second to the current time
sec = sec + 1
IF sec >= 60 THEN sec = 0 : mins = mins + 1

' finally convert the minutes back into the current date/time
Line1 = GetDate$(mins)
Line2 = GetTime$(mins)

' we now have the date/time for the next second ready for display
' we have to wait for the end of the data stream from the GPS
' then we wait for the start of the next second and only then update the LCD
DO : LOOP WHILE TIMER < 950 ' wait for the data to finish
DO : LOOP WHILE INPUT$(200, #1) <> "" ' clear the input buffer
DO WHILE INPUT$(1, #1) <> "$" : LOOP ' wait for a new second to start
TIMER = 0

' display the date and time for this second
IF sec MOD 5 = 0 THEN '***********displays data below every 5 seconds************
PRINT Line1$ " ", Line2$ " " latitude " " ,(arg$(4))" ",longitude " ",(arg$(6))""
TIME$ = LINE2$
print TIME$
ENDIF
LOOP

'**********************************************************************************************



' subroutine to get a GPS record into the array arg$()
SUB GetGPSRecord
DO
DO WHILE INPUT$(1, #1) <> "$" : LOOP ' wait for the start
FOR i = 0 TO 20
arg$(i) = "" ' clear ready for data
DO ' loops until a specific exit
x$ = INPUT$(1, #1) ' get the character
IF x$ = "," THEN EXIT DO ' new data item, new field
IF x$ = "*" THEN EXIT SUB ' end of record, so return with it
arg$(i) = arg$(i) + x$ ' add to the data
LOOP ' keep going
NEXT i ' increment the field
LOOP
END SUB


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' calculate the minutes since midnight 1st Jan 2014
FUNCTION GetMins(yr as integer, mth as integer, day as integer, hr as integer, min as integer) as integer
GetMins = (yr - 14) * (365 * 24 * 60) + ((yr - 13) \ 4) * (24 * 60)
GetMins = GetMins + (md(mth) * (24 * 60))
GetMins = GetMins + ((day - 1) * (24 * 60))
GetMins = GetMins + (hr * 60)
GetMins = GetMins + min
IF (yr - 16) MOD 4 = 0 AND mth > 2 THEN GetMins = GetMins + (24 * 60)
END FUNCTION


' convert minutes back into the time (as a string)
FUNCTION GetTime$(minutes AS INTEGER)
LOCAL hr AS INTEGER, min AS INTEGER, am$
hr = (minutes \ 60) MOD 24
IF hr = 0 THEN hr = 12
min = minutes MOD 60
GetTime$ = STR$(hr) + ":"
GetTime$ = GetTime$ + RIGHT$("0" + STR$(min), 2) + ":"
GetTime$ = GetTime$ + RIGHT$("0" + STR$(sec), 2) + " " + am$
END FUNCTION


' convert minutes back into the date (as a string)
FUNCTION GetDate$(minutes AS INTEGER)
LOCAL yr AS INTEGER, mth AS INTEGER, day AS INTEGER, mths$, days$
mths$ = " JanFebMarAprMayJunJulAugSepOctNovDec"
days$ = "SunMonTueWedThuFriSat"
FOR yr = 14 TO 99
IF minutes < GetMins(yr + 1, 1, 1, 0, 0) THEN EXIT FOR
NEXT yr
FOR mth = 1 TO 12
IF minutes < GetMins(yr, mth, 1, 0, 0) THEN EXIT FOR
NEXT mth
mth = mth - 1
day = ((minutes - GetMins(yr, mth, 1, 0, 0)) \ (24 * 60)) + 1
GetDate$ = MID$(days$, ((((minutes \ (24 * 60)) + 3) MOD 7) * 3) + 1,3)+" "
GetDate$ = GetDate$ + RIGHT$(" " + STR$(day), 2)
GetDate$ = GetDate$ + "-" + MID$(mths$,mth*3,3) + "-" + STR$(yr + 2000)
END FUNCTION


' get the minutes that GMT will start or end in a month
' modified for UK GMT which starts on the LAST Sunday of the month
FUNCTION GetDST(yr AS INTEGER, mth AS INTEGER, hr AS INTEGER) AS INTEGER
LOCAL as INTEGER d, m, n
m = GetMins(yr, mth, 1, hr, 0)
d = ((m \ (24 * 60)) + 3) MOD 7
m = m + (((7 - d) MOD 7) * 24 * 60)
n = GetMins(yr, mth + 1, 1, 0, 0)
do while m + (7 * 24 * 60) < n
m = m + (7 * 24 * 60)
loop
GetDST = m
END FUNCTION

' get the minutes that DST will start or end in a month
'FUNCTION GetDST(yr, mth, hr)
' LOCAL d, m
' m = GetMins(yr, mth, 1, hr, 0)
' d = ((m \ (24 * 60)) + 3) MOD 7
' GetDST = m + (((7 - d) MOD 7) * 24 * 60)
'END FUNCTION
[/code]
Edited by lew247 2016-08-16
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 12:15am 15 Aug 2016
Copy link to clipboard 
Print this post

EDIT
I've set it to it sets the Micromite clock to the correct time
(TIME$ = LINE2$ )
If you don;t want that comment it out or delete the line
also I've got it looping every 5 seconds - this was only so I could see it was working properly
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 12:43am 15 Aug 2016
Copy link to clipboard 
Print this post

Sorry,

But I've gotta be blunt...

The two examples I see of Geoff's code using GPS are the Boat Computer & the Super Clock.

In both cases he explicitly declares variables....

[Code]
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Boat Computer
' Geoff Graham, Feb 15
'
' Requires MMBasic 5.1 or later and an ILI9341 based LCD panel with touch
' Plus a GPS module
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Option autorun on
Option explicit
Option default integer


AND


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Super Clock
' Geoff Graham, April 2016
'
' Requires MMBasic 5.1 or later and an ILI9341 based LCD panel with touch
' Plus a DS3231 Real Time Clock or a GPS module
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
Option Default None
[/code]

Everyone should.

You've defied this practice, sorry,

[Quote=Lew247]BTW the reason I don't use
OPTION EXPLICIT.....
[/quote]

That is just asking for trouble, others have said it....

Defined variables removes the unknown..

String is:-
"ABC", or "Abc123", or "123" where 123 are just like other letters but numbers.

Integer is 1 or 2 or 3, even 2745;
ALL whole numbers, no decimals.

Float is:-
Numbers with decimals.

So "123" can be a string, just like "ABC";

BUT you can't do something like multiply 123 by 2 if its a String,
Just like you can't multiply ABC by 2;

It makes no sense.

That's why declaring variables is so important.


Cheers

Phil

 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 12:47am 15 Aug 2016
Copy link to clipboard 
Print this post

I wish I'd see the boat computer and super clock
The one I saw was This

I really don't get "You've defied this practice, sorry, "

And the reason I used OPTION EXPLICIT was I got told off yesterday for NOT using it
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 01:01am 15 Aug 2016
Copy link to clipboard 
Print this post

Hmmm,

Ok I hadn't relly looked at that code.

In any case, as he didn't declare stuff, it meant variables defaulted to FLOAT, as mentioned on page 64.

Like I said, "You can't multiply abc by 2....

But as far as INTEGERS and FLOAT variables are concerned they can interact.

Consider it this way, mixing floating and integers...


Two floating numbers....

2.0 & 2.5;

2.0 x 2.5 = 5.

A float & an Integer....

2 & 2.5; (the integer can only be a whole number.....)

But still;

2 x 2.5 works, basic takes care of it.

If 2 happened to be a String, it becomes just like "ABC",

And ABC x 2.5 doesn't work.

Hope that explains it a bit more.


Cheers.


 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 01:12am 15 Aug 2016
Copy link to clipboard 
Print this post

Actually,

When you look closely at that code of Geoff's you will see that some variables are "Declared on the Fly"; don't know that that's the correct term.

When he uses say;-
[Code]UseDST = 0 ' set to 1 to enable daylight saving time (DST) adjust
dms = 10 ' the month that DST starts
dhs = 2 ' the hour that DST starts
dme = 4 ' the month that DST ends
dhe = 2 ' the hour that DST ends
[/code]

They will all be assumed as Floating variables.

But a few lines later he uses a variable:-

Arg$

and a few more lines down

Line1$ & Line2$,

In all these cases the dollar sign, "$", on the end, tell Basic that these variables are STRINGs, not FLOATs, which is the default.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6269
Posted: 12:50pm 15 Aug 2016
Copy link to clipboard 
Print this post

Lew,
I think the GPS_clock.bas you are referring to was put together before MMBasic had OPTION EXPLICIT.

I hate OPTION EXPLICIT and the language I wrote MMEdit in doesn't have it.
MMEdit is about 13000 lines now and the number of times I have 'kicked the cat' in frustration because I had a spelling error and ended up using the wrong variable...

I use OPTION EXPLICIT to save the cat getting too bruised and save me getting too frustrated.

(Animal lovers should be advised that I don't have a cat)

Jim

VK7JH
MMedit
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 03:10am 16 Aug 2016
Copy link to clipboard 
Print this post


And feral cats definitely don't deserve love in Tassie Jim
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025