cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 08:55am 01 Mar 2015 |
Copy link to clipboard |
Print this post |
|
Here's a MMBasic program that reads GPS data from the Parallax PAM-7Q GPS receiver and displays the "time tag" of the data and other relevant information. It uses code from Geoff's GPS.BAS program and TZAdvantage's day-of-the-week subroutine. The software pauses for 5000 milliseconds after each valid data message.
Note that the receiver communicates at 9600 baud via TTL. It could be used for Geoff's GPS-controlled clock or perhaps a GPS tracker.
' pam7q.bas
' demonstrates interface with Parallax PAM-7Q GPS
' receiver (#28509) using MMBasic version 4.6B
' thanks to Geoff and TZAdvantage for their code
' March 1, 2015
'''''''''''''''''''''''''''''''''''''''
' typical $GPRMC data (comma delimited)
'''''''''''''''''''''''''''''''''''''''
' $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011. 3,E*62
' contents and format of each data field
' 1 = UTC time (hhmmss.sss)
' 2 = data status (A = data valid, V = data not valid)
' 3 = latitude (ddmm.mmmm)
' 4 = N = north or S = south latitude
' 5 = longitude (ddd.mm.mmmm)
' 6 = E = east or W = west longitude
' 7 = speed over ground (knots)
' 8 = course over ground (degrees true)
' 9 = UTC date (ddmmyy)
' 10 = magnetic variation (degrees; east or west)
' 11 = mode indicator
' 12 = checksum
' 28-pin Micromite-to-GPS pin connections
' pin 21 to RXD, pin 22 to TXD
'''''''''''''''''''''''''''''''''''
' array to hold the GPS data fields
DIM gps_data$(15)
' day-of-the-week and calendar month arrays
dim days$(6), month$(11)
' read day-of-the-week strings
For I = 0 To 6
Read days$(I)
Next I
Data "Sunday"
Data "Monday"
Data "Tuesday"
Data "Wednesday"
Data "Thursday"
Data "Friday"
Data "Saturday"
' read month-of-the-year strings
For I = 0 To 11
Read month$(I)
Next I
Data "January"
Data "February"
Data "March"
Data "April"
Data "May"
Data "June"
Data "July"
data "August"
data "September"
data "October"
data "November"
data "December"
' open com port for communication with GPS receiver
OPEN "COM1:9600" AS #1
DO
' get the next GPS data message
GetGPSData
IF (gps_data$(0) = "GPGSV") THEN
' extract number of satellites in view
nSats = val(gps_data$(3))
endif
IF (gps_data$(0) = "GPRMC") THEN
' $GPRMC is the data message we want
IF (gps_data$(2) = "A") THEN
' "A" means locked on to satellites
' extract and format latitude (data element #3, ddmm.mmmm)
lat_deg$ = LEFT$(gps_data$(3), 2)
lat_min$ = MID$(gps_data$(3), 3, 2)
lat_sec$ = str$(cint(val(mid$(gps_data$(3), 5, 9)) * 60.0))
' extract and format longitude (data element #5, dddmm.mmmm)
long_deg$ = LEFT$(gps_data$(5), 3)
if (left$(long_deg$, 1) = "0") then
long_deg$ = " " + right$(long_deg$, 2)
endif
long_min$ = MID$(gps_data$(5), 4, 2)
long_sec$ = str$(cint(val(mid$(gps_data$(5), 6, 10)) * 60.0))
' extract calendar date (ddmmyy)
wrk_year = val(RIGHT$(gps_data$(9), 2)) + 2000
wrk_month$ = month$(val(MID$(gps_data$(9), 3, 2)) - 1)
wrk_day$ = LEFT$(gps_data$(9), 2)
' extract time stamp
hour$ = LEFT$(gps_data$(1), 2)
min$ = MID$(gps_data$(1), 3, 2)
sec$ = MID$(gps_data$(1), 5, 2)
' format "working" calendar date and compute day-of-the-week
wrk_date$ = wrk_day$ + "-" + MID$(gps_data$(9), 3, 2) + "-" + str$(wrk_year)
DayOfWeek
if (left$(wrk_day$, 1) = "0") then
wrk_day$ = right$(wrk_day$, 1)
endif
' reformat date to mmddyyyy for display
usa_date$ = wrk_month$ + " " + wrk_day$ + "," + " " + str$(wrk_year)
' display results
print
print
print days$(dow), " ", usa_date$, " ", hour$ + ":" + min$ + ":" + sec$ + " UTC"
print
PRINT "Latitude "; lat_deg$ + " deg " + lat_min$ + " min " + lat_sec$ + " sec " + gps_data$(4)
print
PRINT "Longitude "; long_deg$ + " deg " + long_min$ + " min " + long_sec$ + " sec " + gps_data$(6)
print
if (nSats <> 0) then
print "number of satellites in view ", nSats
endif
' pause 5000 ms
pause 5000
ELSE
'PRINT "GPS searching..."
ENDIF
ENDIF
LOOP
end
''''''''''''''
''''''''''''''
SUB GetGPSData
' subroutine to load the GPS data fields
' into the string array gps_data$()
DO
DO WHILE (INPUT$(1, #1) <> "$")
' wait for a valid message (first character = "$")
LOOP
' extract thirteen data items for the message
FOR i = 0 TO 15
' clear current array element for data
gps_data$(i) = ""
' parse the individual data items
DO
' get the next character
x$ = INPUT$(1, #1)
IF (x$ = ",") THEN
' encountered data deliminter = ","
exit
endif
IF (x$ = "*") THEN
' encountered first part of checksum
' we have all the data so exit subroutine
exit sub
endif
' add this character or number to the current data field
gps_data$(i) = gps_data$(i) + x$
LOOP
NEXT i
LOOP
END SUB
'''''''
'''''''
Sub DayOfWeek
' calculate day of the week using
' TZAdvantage's algorithm
' assumed date format = dd-mm-yyy
a = Int((14-Val(Mid$(wrk_date$, 4, 2))) / 12)
m = Val(Mid$(wrk_date$, 4, 2)) + 12 * a - 2
y = Val(Mid$(wrk_date$, 7, 4)) - a
d = Val(Mid$(wrk_date$, 1, 2))
dow = (d + y + Int(y / 4) - Int(y / 100) + Int(y / 400) + Int(31 * m / 12)) Mod 7
End Sub
|
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 07:03am 19 May 2015 |
Copy link to clipboard |
Print this post |
|
Here's a version of the software that logs GPS information to a microSD card using the Sparkfun OpenLog board. It writes the calendar date, UTC time, latitude and longitude and ground speed via COM2.
The latitude and longitude are in degrees with north latitudes positive, south latitude negative, east longitudes positive and west longitudes negative.
Additional data can be easily added to the stream.
option AUTORUN on
' lcd_pam7q.bas
' demonstrates interface with Parallax PAM-7Q GPS
' receiver (#28509) and data logging to OpenLog
' using MMBasic version 4.6B
' thanks to Geoff and TZAdvantage for their code
' May 19, 2015
'''''''''''''''''''''''''''''''''''''''
' typical $GPRMC data (comma delimited)
'''''''''''''''''''''''''''''''''''''''
' $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
' contents and format of each data field
' 1 = UTC time (hhmmss.sss)
' 2 = data status (A = data valid, V = data not valid)
' 3 = latitude (ddmm.mmmm)
' 4 = N = north or S = south latitude
' 5 = longitude (ddd.mm.mmmm)
' 6 = E = east or W = west longitude
' 7 = speed over ground (knots)
' 8 = course over ground (degrees true)
' 9 = UTC date (ddmmyy)
' 10 = magnetic variation (degrees; east or west)
' 11 = mode indicator
' 12 = checksum
' 28-pin Micromite-to-GPS pin connections (COM1)
' pin 21 to RXD, pin 22 to TXD
' 28-pin Miromite-to-OpenLog connections (COM2)
' pin 9 to RXI, pin 10 to TXO
' initialize LCD
lcd init 23, 24, 25, 26, 15, 16
'''''''''''''''''''''''''''''''''''
' array to hold the GPS data fields
DIM gps_data$(15)
' day-of-the-week and calendar month arrays
dim days$(6), month$(11)
' read day-of-the-week strings
For I = 0 To 6
Read days$(I)
Next I
Data "Sun"
Data "Mon"
Data "Tue"
Data "Wed"
Data "Thu"
Data "Fri"
Data "Sat"
' read month-of-the-year strings
For I = 0 To 11
Read month$(I)
Next I
Data "Jan"
Data "Feb"
Data "Mar"
Data "Apr"
Data "May"
Data "Jun"
Data "Jul"
data "Aug"
data "Sep"
data "Oct"
data "Nov"
data "Dec"
' open com port for communication with GPS receiver
OPEN "COM1:9600" AS #1
' open com port for communication with OpenLog
OPEN "COM2:9600" AS #5
DO
' get the next GPS data message
GetGPSData
IF (gps_data$(0) = "GPGSV") THEN
' extract number of satellites in view
nSats = val(gps_data$(3))
'print "number of satellites = ", nSats
endif
IF (gps_data$(0) = "GPRMC") THEN
' $GPRMC is the data message we want
IF (gps_data$(2) = "A") THEN
' "A" means locked on to satellites
' extract and format latitude (data element #3, ddmm.mmmm)
lat_deg$ = LEFT$(gps_data$(3), 2)
lat_min$ = MID$(gps_data$(3), 3, 2)
lat_sec$ = str$(cint(val(mid$(gps_data$(3), 5, 9)) * 60.0))
latitude = val(lat_deg$) + val(lat_min$) / 60.0 + val(lat_sec$) / 3600.0
if (gps_data$(4) = "S") then
latitude = -latitude
end if
' extract and format longitude (data element #5, dddmm.mmmm)
long_deg$ = LEFT$(gps_data$(5), 3)
if (left$(long_deg$, 1) = "0") then
long_deg$ = " " + right$(long_deg$, 2)
endif
long_min$ = MID$(gps_data$(5), 4, 2)
long_sec$ = str$(cint(val(mid$(gps_data$(5), 6, 10)) * 60.0))
longitude = val(long_deg$) + val(long_min$) / 60.0 + val(long_sec$) / 3600.0
if (gps_data$(6) = "W") then
longitude = -longitude
end if
' extract calendar date (data element #9; ddmmyy)
wrk_year = val(RIGHT$(gps_data$(9), 2)) + 2000
cal_month = val(MID$(gps_data$(9), 3, 2))
wrk_month$ = month$(cal_month - 1)
wrk_day$ = LEFT$(gps_data$(9), 2)
' extract time stamp
hour$ = LEFT$(gps_data$(1), 2)
min$ = MID$(gps_data$(1), 3, 2)
sec$ = MID$(gps_data$(1), 5, 2)
' format "working" calendar date and compute day-of-the-week
wrk_date$ = wrk_day$ + "-" + MID$(gps_data$(9), 3, 2) + "-" + str$(wrk_year)
DayOfWeek
if (left$(wrk_day$, 1) = "0") then
wrk_day$ = right$(wrk_day$, 1)
endif
' reformat date to mmddyyyy for display
usa_date$ = wrk_month$ + " " + wrk_day$ + "," + " " + str$(wrk_year)
' display results on lcd
wrkstr1$ = " " + days$(dow) + " " + usa_date$
lcd 2,1, wrkstr1$
wrkstr2$ = " " + hour$ + ":" + min$ + ":" + sec$ + " UTC"
lcd 1,1, wrkstr2$
wrkstr3$ = " Lat " + lat_deg$ + "d " + lat_min$ + "m " + lat_sec$ + "s " + gps_data$(4)
lcd 3, 1, wrkstr3$
wrkstr4$ = " Lon " + long_deg$ + "d " + long_min$ + "m " + long_sec$ + "s " + gps_data$(6)
lcd 4, 1, wrkstr4$
print #5, str$(cal_month);"-";wrk_day$;"-";str$(wrk_year);",";hour$ + ":" + min$ + ":" + sec$; ",";latitude;",";longitude;","; gps_data$(7)
' pause 30 seconds between updates
pause 30000
ELSE
'lcd 1, 1, "GPS searching..."
ENDIF
ENDIF
LOOP
close #5
end
''''''''''''
''''''''''''
SUB GetGPSData
' subroutine to load the GPS data fields
' into the string array gps_data$()
DO
DO WHILE (INPUT$(1, #1) <> "$")
' wait for a valid message (first character = "$")
LOOP
' extract thirteen data items for the message
FOR i = 0 TO 15
' clear current array element for data
gps_data$(i) = ""
' parse the individual data items
DO
' get the next character
x$ = INPUT$(1, #1)
IF (x$ = ",") THEN
' encountered data deliminter = ","
exit
endif
IF (x$ = "*") THEN
' encountered first part of checksum
' we have all the data so exit subroutine
exit sub
endif
' add this character or number to the current data field
gps_data$(i) = gps_data$(i) + x$
LOOP
NEXT i
LOOP
END SUB
'''''''''''
'''''''''''
Sub DayOfWeek
' calculate day of the week using
' TZAdvantage's algorithm
' assumed date format = dd-mm-yyy
a = Int((14-Val(Mid$(wrk_date$, 4, 2))) / 12)
m = Val(Mid$(wrk_date$, 4, 2)) + 12 * a - 2
y = Val(Mid$(wrk_date$, 7, 4)) - a
d = Val(Mid$(wrk_date$, 1, 2))
dow = (d + y + Int(y / 4) - Int(y / 100) + Int(y / 400) + Int(31 * m / 12)) Mod 7
End Sub
|