Proton BASIC Compiler - Extracting GPS Data


  • PicŪ Basic


  • Extracting GPS Data

    The following code example extracts data from the NMEA sentences transmitted by GPS modules.

    Example 1 - extracting GPS data from NMEA string - written by Les and originally posted on the PDS forum

    Below is a program that will parse a GPS string using two methods. Fixed length and position, and a parser subroutine to extract the value after a certain comma. The program is written for use with PROTON+ Version 2.1 and uses a 16-bit core device, but this can easily be replaced with a 14-bit core type, but rememeber, 16-bit core types handle memory better, especially if using arrays and strings.

    '
    ' Read and display GPS info on a graphic LCD.
    '
    Include "PROTON18_G4.INT" ' For use with a 16-bit core device on a PROTON board

    '----[VARIABLE DECLARATIONS]-------------------------------------------------

    Dim BLOOP as Byte SYSTEM ' General purpose loop variable

    ' Value extraction variables
    Dim EXTRACT_ITEM as Byte
    Dim COMMA_COUNT as Byte
    Dim CHARPOS as Byte
    Dim CHAR as Byte

    ' GPS variables
    Dim DAY as Byte
    Dim MONTH as Byte
    Dim YEAR as Byte
    Dim HOURS as Byte
    Dim MINUTES as Byte
    Dim SECONDS as Byte
    Dim LATITUDE_DEGREES as Byte
    Dim LATITUDE_MINUTES as Byte
    Dim LATITUDE_SECONDS as Byte
    Dim LATITUDE_BEARING as Byte
    Dim LONGITUDE_DEGREES as Byte
    Dim LONGITUDE_MINUTES as Byte
    Dim LONGITUDE_SECONDS as Byte
    Dim LONGITUDE_BEARING as Byte
    Dim FIX_TYPE as Byte
    Dim SATELLITES_IN_VIEW as Byte
    Dim DATA_STRING[20] as Byte
    Dim RX_BUFF[200] as Byte

    '-----------------------------------------------------------------------------

    Delayms 200 ' Wait for the PICŪ micro to stabilise
    ALL_DIGITAL = TRUE ' Set PORTA and PORTE to all digital
    Cls
    Goto MAIN_PROGRAM_LOOP ' Jump over the subroutines

    '----[EXTRACT A VALUE BASED ON THE COMMA THAT IT FOLLOWS]----------------------
    ' Locates and extracts the value following the comma placed in EXTRACT_ITEM
    ' The extracted text is returned in array DATA_STRING with a NULL terminator
    ' If an invalid value is found, then 000000 will be returned in the array
    EXTRACT_THE_VALUE:
    StrN DATA_STRING = "0000000000000000000"
    COMMA_COUNT = 0 ' Reset the comma counting variable
    CHARPOS = 0 ' Start at the beginning of the array
    Repeat
    CHAR = RX_BUFF[CHARPOS] ' Scan the array to parse
    If CHAR = "," Then Inc COMMA_COUNT ' Increment COMMA_COUNT if a comma is found
    If COMMA_COUNT = EXTRACT_ITEM Then ' Have we found the correct comma ?
    BLOOP = 0 ' Yes. So....
    Repeat ' Form a loop
    Inc CHARPOS ' Skip over the comma and keep scanning the array
    CHAR = RX_BUFF[CHARPOS] ' Extract the pieces of the value into CHAR
    If CHAR = 0 Then Break
    If CHAR = "," Then Break
    DATA_STRING[BLOOP] = CHAR ' Fill DATA_STRING with the value
    Inc BLOOP ' Point to the next data piece
    Until CHARPOS >= 199 ' Keep looping until a terminator is found
    DATA_STRING[BLOOP] = 0 ' Add a NULL to DATA_STRING
    Break
    Endif
    Inc CHARPOS
    Until CHARPOS >= 199
    Return

    '----[PARSE GPS DATA]----------------------------------------------------------
    ' Extract the location data from the GPS strings
    ' The date is returned in byte array DATA_STRING
    ' All the rest are returned in their respective variables
    PARSE_GPS:
    Clear
    Rsin wait("$GPGGA,"),STR RX_BUFF\63 ' Pull the GPGGA string from the GPS data
    BLOOP = 0
    Repeat
    RX_BUFF[BLOOP] = RX_BUFF[BLOOP] - 48 ' Convert ASCII to INT and load array RX_BUFF
    Inc BLOOP
    Until BLOOP > 63
    HOURS = RX_BUFF#1 + (RX_BUFF#0 * 10)
    MINUTES = RX_BUFF#3 + (RX_BUFF#2 * 10)
    SECONDS = RX_BUFF#5 + (RX_BUFF#4 * 10)

    LATITUDE_DEGREES = RX_BUFF#12 + (RX_BUFF#11 * 10)
    LATITUDE_MINUTES = RX_BUFF#14 + (RX_BUFF#13 * 10)
    LATITUDE_SECONDS = RX_BUFF#17 + (RX_BUFF#16 * 10)
    LATITUDE_BEARING = RX_BUFF#21 + 48
    LONGITUDE_DEGREES = (RX_BUFF#25 * 100) + (RX_BUFF#24 * 10) + RX_BUFF#23
    LONGITUDE_MINUTES = RX_BUFF#27 + (RX_BUFF#26 * 10)
    LONGITUDE_SECONDS = RX_BUFF#30 + (RX_BUFF#29 * 10)
    LONGITUDE_BEARING = RX_BUFF#34 + 48
    FIX_TYPE = RX_BUFF#36
    SATELLITES_IN_VIEW = RX_BUFF#39 + (RX_BUFF#38 * 10)
    '
    ' Find the date of the fix
    '
    Rsin wait("$GPRMC,"),STR RX_BUFF\63 ' Pull the GPRMC string from the GPS data
    EXTRACT_ITEM = 8 ' Parse the value after the 8th comma
    Gosub EXTRACT_THE_VALUE
    Return
    '------------------------------------------------------------------------------
    MAIN_PROGRAM_LOOP:

    While 1 = 1

    Gosub PARSE_GPS
    If FIX_TYPE > 0 Then
    Print at 0,0,"DATE ",DATA_STRING#0,DATA_STRING#1,":",DATA_STRING#2,DA TA_STRING#3,":",DATA_STRING#4,DATA_STRING#5
    Print at 1,0,"TIME ",Dec2 HOURS,":",Dec2 MINUTES,":",Dec2 SECONDS," UTC"
    Print at 2,0,"LAT ",Dec2 LATITUDE_DEGREES,39," ",Dec2 LATITUDE_MINUTES,".",Dec2 LATITUDE_SECONDS,34,LATITUDE_BEARING
    Print at 3,0,"LON ",Dec3 LONGITUDE_DEGREES,39," ",Dec2 LONGITUDE_MINUTES,".",Dec2 LONGITUDE_SECONDS,34,LONGITUDE_BEARING
    Print at 4,0, "FIX TYPE ", Dec1 FIX_TYPE
    Print at 5,0, "SATELLITES ",Dec SATELLITES_IN_VIEW
    Else
    Cls
    Print at 3,0,"NO SATELLITES IN VIEW"
    Repeat
    Gosub PARSE_GPS
    Until FIX_TYPE > 0
    Cls
    Endif
    Wend

    '-----------------------------------------------------------------------------
    Include "FONT.INC"
    contributed by Les Johnson.