Hello!
I want to share my little program. This is not a final project but the core functions are complete. I'm using a GPS module from adafruit [url]http://www.adafruit.com/products/746[/url] and its working great, even indoors. The basic idea of processing the NMEA sentences comes from forum member Glena. Thanks for it! The code have three different parts, one for displaying coordinates, time, DOP values, speed, etc., one for displaying the parameters of the satellites in view like PRN number, azimuth, elevation and SNR values. These values can be used for making an SNR bargraph for the tracked satellites (which will be a further improvement). The third function is drawing a skyplot with icons and PRN numbers. I'm using a display with a PCF8833 controller from an old Nokia 3100.
Here is the code (sorry for the multilingual variable names):
[code:1:5dc2b13265]
'GPS Info by doncarlos with atmega128 and PCF8833 display for processing standard NMEA data
$regfile = "m128def.dat"
$crystal = 11059200
$hwstack = 256
$swstack = 256
$framesize = 256
$lib "lcd-pcf8833BR2.lbx"
Config Graphlcd = Color , Controlport = Portc , Cs = 1 , Rs = 0 , Scl = 3 , Sda = 2
'######################## Color definitons ###################################
Const Blue = &B00000011
Const Yellow = &B11111100
Const Red = &B11100000
Const Green = &B00011100
Const Black = &B00000000
Const White = &B11111111
Const Brightgreen = &B00111110
Const Darkgreen = &B00010100
Const Darkred = &B10100000
Const Darkblue = &B00000010
Const Brightblue = &B00011111
Const Orange = &B11111000
'###############################################################################
Config Com1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Com2 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Serialin = Buffered , Size = 250 , Bytematch = 13 ' GPS Buffer
Dim Gps_data_flag As Byte
Dim Strbytes(252) As Byte
Dim Gpsline As String * 251 At Strbytes(1) Overlay ' NMEA sentence holder
Dim Gpsline_t As String * 251
Dim Strlen As Byte
Dim Index As Byte
Dim Chksum As Byte
Dim Gps_chksum As String * 2
Dim Gps_chksum_b As Byte
Dim Dollar As String * 1
Dim Z As Byte
Dim Gps_adatok(21) As String * 15 'Array for storing various GPS data
Dim Gpstime_s As String * 10
Dim Gpsdate_s As String * 10
Dim Gpslat_s As String * 10
Dim Gpslon_s As String * 10
Dim Pos_status As String * 1 , Nofix As Bit
Dim Dms_lat As String * 15 , Dms_long As String * 15
Dim We As String * 1 , Ns As String * 1
Dim Pdop As String * 4 , Hdop As String * 4 , Vdop As String * 4 , Magassag As String * 6 , Sebesseg As String * 7
Dim Fix_type(4) As String * 8 , Fix_szam As Byte
Dim Sat_track As String * 2
Dim Timezone As Byte
Dim Perc As String * 2 , Mp As String * 2 , Ora As String * 2 , Ora_b As Byte 'Time values: min, sec, hour
Dim Nap As String * 2 , Honap As String * 2 , Ev As String * 2 'Date values: date, month, year
Dim Ido As String * 8 , Datum As String * 8
Dim Sentence_count As Byte , Sentence_num As Byte , Satinview As Byte
Dim Szamlalo As Byte , Szamlalo2 As Byte , Cim As Byte , L As Byte , K As Byte , Cim_temp As Byte , Lineindex As Byte 'some indexing values
Dim Satinfo(64)as String * 3 'Array for the PRN display data (PRN, Azimuth, Elevation, SNR)
Dim I As Byte , H As Byte
Dim Index_temp1 As Byte , Index_temp2 As Byte , Dy As Byte , Dx As Byte 'More indexing values
Dim Pr_number As String * 2 , Ele As String * 2 , Azi As String * 3 , Snr As String * 2
Dim Azi_single As Single , Ele_int As Integer
Dim Ticker As Byte
Timezone = 2 'Modify this for setting your timezone
Declare Function Dmtodms(byval Szog_string As String) As String
Declare Sub Skyplot(azimuth As Single , Byval Elevation As Integer , Prn As String * 2 , Byval Ncolor As Byte)
'######################### LCD Init ############################################
Glcdcmd &H21
Glcdcmd &H36
Glcddata &H48 '40 = RGB or 48 = BGR
'###############################################################################
Open "Com2:" For Binary As #2
Enable Interrupts
Cls
Print "Serial1 init"
Print #2 , "Serial2 init"
Setfont Color8x8
Lcdat 63 , 30 , "GPS" , Black , White
Cls
Fix_type(1) = "SPS fix"
Fix_type(2) = "DGPS fix"
Fix_type(3) = "PPS fix"
Fix_type(4) = "RTK fix"
Szamlalo = 1
Szamlalo2 = 1
'!!!!!!!!!!!!!!!!!! For now this is the function selector !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'!!!!!!!!!!!!!!!!! uncomment one of the gotos to select !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!! a function, if both commented out the text display will run !!!!!!!!!!!!!!!!!!
'Goto Sky
'Goto Prn_snr
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'###############################################################################
Lcdat 4 , 2 , "GPS Ido:" , Black , White
Lcdat 14 , 2 , "Koordinatak:" , Black , White
Lcdat 44 , 2 , "Elev:" , Black , White
Lcdat 54 , 2 , "Speed:" , Black , White
Szoveges:
Do
If Gps_data_flag > 0 Then Gosub Processgps
If Pos_status = "V" Then
If Nofix = 1 Then Goto Szoveges
Nofix = 1
Lcdat 74 , 2 , " NO FIX! " , Black , White
Lcdat 4 , 66 , " " , Black , White
Lcdat 24 , 2 , " " , Black , White
Lcdat 34 , 2 , " " , Black , White
Lcdat 44 , 56 , " " , Black , White 'clearing the display
Lcdat 54 , 56 , " " , Black , White 'this is faster then a cls
Lcdat 64 , 2 , " " , Black , White
Lcdat 94 , 2 , " " , Black , White
Lcdat 104 , 2 , " " , Black , White
Lcdat 114 , 2 , " " , Black , White
Else
Nofix = 0
Ora = Mid(gpstime_s , 1 , 2)
Perc = Mid(gpstime_s , 3 , 2)
Mp = Mid(gpstime_s , 5 , 2)
Nap = Mid(gpsdate_s , 1 , 2)
Honap = Mid(gpsdate_s , 3 , 2)
Ev = Mid(gpsdate_s , 5 , 2)
Ora_b = Val(ora) + Timezone
If Ora_b > 24 Then Ora_b = Ora_b - 24
Ora = Str(ora_b)
Ido = Ora + ":" + Perc + ":" + Mp
Datum = Ev + "." + Honap + "." + Nap
Dms_lat = Dmtodms(gpslat_s)
Dms_long = Dmtodms(gpslon_s)
Lcdat 4 , 66 , Ido , Black , White
Lcdat 24 , 2 , Ns ; " " ; Dms_lat , Black , White
Lcdat 34 , 2 , We ; " " ; Dms_long , Black , White
Lcdat 44 , 56 , Magassag ; "M"
Lcdat 54 , 56 , Sebesseg ; "Km/h"
Lcdat 64 , 2 , "Sat trk: " ; Sat_track
Lcdat 74 , 2 , Fix_type(fix_szam) ; " "
Lcdat 94 , 2 , "PDOP: " ; Pdop ; " "
Lcdat 104 , 2 , "HDOP: " ; Hdop ; " "
Lcdat 114 , 2 , "VDOP: " ; Vdop ; " "
End If
Loop
'###############################################################################
Prn_snr:
Cls
Do
If Gps_data_flag > 0 Then Gosub Processgps
Lcdat 4 , 2 , "PRN" , Black , White : Lcdat 4 , 34 , "Ele" , Black , White : Lcdat 4 , 70 , "Azi" , Black , White : Lcdat 4 , 102 , "SNR" , Black , White
For I = 1 To Satinview
For H = 1 To 4
Index_temp1 = I - 1
Index_temp1 = Index_temp1 * 4
Index_temp2 = H + Index_temp1
Dy = I - 1
Dx = H - 1
Dy = Dy * 8 '12
Dy = Dy + 15
Dx = Dx * 35
Dx = Dx + 4
Setfont Color5x5
Lcdat Dy , Dx , Satinfo(index_temp2)
Setfont Color8x8
Next H
Next I
Loop
'###############################################################################
Sky:
Cls
Circle(66 , 66) , 60 , Black 'Drawing the skyplot background
Circle(66 , 66) , 40 , Black ' |
Circle(66 , 66) , 20 , Black ' |
Line(66 , 0) -(66 , 132) , Black ' |
Line(0 , 66) -(132 , 66) , Black ' ˇ
Do
If Gps_data_flag > 0 Then Gosub Processgps
For I = 1 To Satinview
Index_temp1 = I - 1
Index_temp1 = Index_temp1 * 4
Pr_number = Satinfo(1 + Index_temp1)
Ele = Satinfo(2 + Index_temp1) : Ele_int = Val(ele)
Azi = Satinfo(3 + Index_temp1) : Azi_single = Val(azi)
If Azi_single <> 0 And Ele_int <> 0 And Pr_number <> "" Then
'Call Skyplot(azi_old , Ele_old , Pr_number , White)
Call Skyplot(azi_single , Ele_int , Pr_number , Red)
End If
'Azi_old = Azi_single : Ele_old = Ele_int
Next I
Waitms 250
Loop
'###############################################################################
Serial0charmatch:
Pushall
Incr Gps_data_flag 'Increment the NMEA sentence counter
Popall
Return
'###############################################################################
Processgps:
Decr Gps_data_flag
'############################################
Do
Dollar = Inkey() 'Start finding
If Dollar = "" Then Return
Loop Until Dollar = "$"
'############################################
Input Gpsline Noecho
'############################################
Strlen = Len(gpsline)
Chksum = 0
Gps_chksum_b = 0
Strlen = Strlen - 3
For Index = 1 To Strlen
Chksum = Chksum Xor Strbytes(index) 'Checksum generation
Next Index
Gps_chksum = Right(gpsline , 2)
Gps_chksum_b = Hexval(gps_chksum)
'#############################################
If Chksum = Gps_chksum_b Then 'If the checksum matches then we can process the right data
Gpsline_t = Left(gpsline , Strlen)
Z = Split(gpsline_t , Gps_adatok(1) , ",")
Select Case Gps_adatok(1)
Case "GPRMC" 'position and time data
Pos_status = Gps_adatok(3)
If Pos_status = "A" Then
Gpstime_s = Gps_adatok(2)
Gpsdate_s = Gps_adatok(10)
Gpslat_s = Gps_adatok(4)
Gpslon_s = Gps_adatok(6)
We = Gps_adatok(7)
Ns = Gps_adatok(5)
End If
Case "GPGGA" 'fix type, tracked sat number and elevation
Fix_szam = Val(gps_adatok(7))
If Fix_szam <> 0 Then Magassag = Gps_adatok(10)
Sat_track = Gps_adatok(8)
Case "GPGSA" 'DOP values
Pdop = Gps_adatok(16)
Hdop = Gps_adatok(17)
Vdop = Left(gps_adatok(18) , 4)
Case "GPVTG" 'speed
Sebesseg = Gps_adatok(8)
Case "GPGSV"
Satinview = Val(gps_adatok(4))
Sentence_count = Val(gps_adatok(2))
Sentence_num = Val(gps_adatok(3))
If Sentence_num <= Sentence_count Then
If Sentence_num = Szamlalo Then
'###################################################################
For L = 1 To 4 'Filling up the satinfo array
If Szamlalo2 > Satinview Then
Szamlalo2 = 1
Exit For
Else
For K = 1 To 4
Cim_temp = L - 1
Cim_temp = Cim_temp * 4
Cim = K + Cim_temp
Lineindex = K + Cim_temp
Lineindex = Lineindex + 4
Cim_temp = Sentence_num - 1
Cim_temp = Cim_temp * 16
Cim = Cim + Cim_temp
Satinfo(cim) = Gps_adatok(lineindex)
Next K
Incr Szamlalo2
End If
Next L
If Szamlalo = Sentence_count Then
Szamlalo = 1
Else
Incr Szamlalo
End If
'###################################################################
End If
End If
Case Else
End Select
End If
Return
'###############################################################################
Function Dmtodms(szog_string As String) As String 'function to convert the nmea degrees and miutes to degrees minutes and seconds
Local Szogmp As Single
Local Fok_s As String * 3 , Szogperc_s As String * 2 , Szogmp_s As String * 5
If Len(szog_string) = 9 Then
Fok_s = Left(szog_string , 2)
Szogperc_s = Mid(szog_string , 3 , 2)
Szogmp_s = Right(szog_string , 5)
Szogmp_s = "0" + Szogmp_s
Szogmp = Val(szogmp_s)
Szogmp = Szogmp * 60
Szogmp_s = Fusing(szogmp , "#.##")
End If
If Len(szog_string) = 10 Then
Fok_s = Left(szog_string , 3)
Szogperc_s = Mid(szog_string , 4 , 2)
Szogmp_s = Right(szog_string , 5)
Szogmp_s = "0" + Szogmp_s
Szogmp = Val(szogmp_s)
Szogmp = Szogmp * 60
Szogmp_s = Fusing(szogmp , "#.##")
End If
Dmtodms = Fok_s + Chr(127) + Szogperc_s + Chr(39) + Szogmp_s + Chr(34)
End Function
Sub Skyplot(azimuth As Single , Elevation As Integer , Prn As String * 2 , Ncolor As Byte)
Local X As Single , Y As Single
Local X1 As Integer , Y1 As Integer
Local X2 As Integer , Y2 As Integer
Local Azimuth_rad As Single
Local Temp As Single , Temp2 As Single
Temp = Azimuth - 90 'Turning the polar coordinate system with 90°
Azimuth_rad = Deg2rad(temp)
Temp2 = 90 - Elevation 'Inverting the elevation values because for a normal polar coordinate system 90° of elevation would be the furthest and in a skyplot the 90° is the center of the coordinate system
Temp2 = Temp2 * 0.666667 'Scaling down the elevation value because the small screen space
X = Cos(azimuth_rad)
X = X * Temp2 'or * Elevation if you have a bigger screen to work with
X = X + 66
X1 = X
X2 = X1 - 4
Y = Sin(azimuth_rad)
Y = Y * Temp2 'or * Elevation
Y = Y + 63
Y1 = Y
Y2 = Y1 - 4
Lcdat Y2 , X2 , Chr(132) , Ncolor , White 'GPS sat icon drawing
Y2 = Y2 + 9 : X2 = X2 - 1 'PRN number align
Setfont Color5x5
Lcdat Y2 , X2 , Prn 'Prn
Setfont Color8x8
End Sub
Close #2
End
'fonts
$include "color8x8.font"
$include "color5x5.font"
[/code:1:5dc2b13265]
I attach my font file because i draw a GPS satellite icon at the 132 position.
Feel free to ask anything and if someone wants i will take some pictures. And of course any improvements, error corrections, suggestions are welcomed!
↧