Hi ,
I have bought a Garmin GLO 2 for testing.
I can use it to access and analyze all NMEA data.
Only one thing is not working properly and that is the GPS time! It deviates from the internal GPS time by 3-4 seconds and I don't know where this is coming from.
For the GSP time I use the NMEA-Sentence $GPGGA.
Maybe I have a mistake somewhere and don't realize it, or someone has a better solution.
Or it is simply because the NMEA sentences cannot provide the exact GPS time.
This picture shows the correct GSP time of a cell phone that uses the internal GPS receiver:
This picture shows the inaccurate GSP time of a cell phone with the Garmin GLO-2 GPS receiver:
This below is the classe(clsNMEA) used by me:
I have bought a Garmin GLO 2 for testing.
I can use it to access and analyze all NMEA data.
Only one thing is not working properly and that is the GPS time! It deviates from the internal GPS time by 3-4 seconds and I don't know where this is coming from.
For the GSP time I use the NMEA-Sentence $GPGGA.
Maybe I have a mistake somewhere and don't realize it, or someone has a better solution.
Or it is simply because the NMEA sentences cannot provide the exact GPS time.
This picture shows the correct GSP time of a cell phone that uses the internal GPS receiver:
This picture shows the inaccurate GSP time of a cell phone with the Garmin GLO-2 GPS receiver:
This below is the classe(clsNMEA) used by me:
B4X:
#Event: SatelliteReceived (GPSSat As List)
#Event: LocationChanged (location1 As Location)
Sub Class_Globals
'NMEA-Variablen
Private satelliteNumber As Short
Private pseudoRandomCode As Short
Private azimuth As Short
Private elevation As Short
Private noOfMessages As Short
Private gPGSVsequence As Short
Private lstGPSSat As List
Private DefaultTimeFormat As String
Private offspan As Double
Private oldLatitude, oldLongitude As Double
Type myGPSSatellite(azimuth As Float, Prn As Int, Snr As Float, elevation As Float, UsedInFix As Boolean)
Private location1 As Location
Private mEventName As String 'ignore
Private mCallBack As Object 'ignore
End Sub
'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(Callback As Object, EventName As String)
mEventName = EventName
mCallBack = Callback
DefaultTimeFormat = DateTime.TimeFormat
offspan = DateTime.GetTimeZoneOffsetAt(DateTime.now) * DateTime.TicksPerHour
lstGPSSat.Initialize
location1.Initialize
End Sub
' Processes information from the GPS receiver
Public Sub ParseSentence(sentence As String) As Boolean
Dim Ps As Boolean
' Discard the sentence if its checksum does not match calculated checksum
If Not (IsValid(sentence)) Then
Return False
End If
Log("sentence=" & sentence)
' Divide the sentence into words and Look at the first word to decide where to go next
Dim words() As String = GetWords(sentence)
' Divide the sentence into words and Look at the first word to decide where to go next
Select Case words(0)
Case "$GPGSV", "$GLGSV" ' A "Satellites in View" sentence was recieved
' Indicate that the sentence was recognised
Ps = ParseGPGSV(words)
Case "$GPGGA", "$GNGGA" ' Global positioning system fixed data
' Indicate that the sentence was recognised
Ps = Parse_GPGGA(words)
' Case "$GPRMC", "$GNRMC" ' A "Recommended Minimum" sentence was found!
' ' Indicate that the sentence was recognised
' Ps = Parse_GPRMC(words)
Case "$GPVTG" ' Track Made Good and Ground Speed.
Ps = Parse_GPVTG(words)
Case Else
' Indicate that the sentence was not recognised
Ps = False
End Select
If location1.Latitude > 0 And location1.Speed > 0 And location1.Time > 0 Then
If oldLatitude <> location1.Altitude Or oldLongitude <> location1.Longitude Then
oldLatitude = location1.Altitude
oldLongitude = location1.Longitude
CallSub2(mCallBack, mEventName & "_LocationChanged", location1)
Dim location1 As Location
location1.Initialize
End If
End If
Return Ps
End Sub
Private Sub IsValid(sentence As String) As Boolean
' Compare the characters after the asterisk to the calculation
Return GetChecksum(sentence)
End Sub
' Calculates the checksum for a sentence
Private Sub GetChecksum(sentence As String) As Boolean
Dim checksum As Int
Dim startIndex, endIndex As Int
Dim givenChecksum As Int
startIndex = sentence.IndexOf("$") + 1
endIndex = sentence.IndexOf("*")
If startIndex <= 0 Or endIndex <= 0 Or endIndex <= startIndex Then
Return False
End If
checksum = Asc(sentence.CharAt(startIndex))
For i = startIndex + 1 To endIndex - 1
checksum = Bit.Xor(checksum, Asc(sentence.CharAt(i)))
Next
Try
givenChecksum = Bit.ParseInt(sentence.SubString(endIndex + 1), 16)
Catch
Return False
End Try
Return checksum = givenChecksum
End Sub
Private Sub GetWords(sentence As String) As String()
'strip off final * + checksum
Dim wrd() As String
If sentence.Length > 3 Then
sentence = Left(sentence, sentence.Length - 3)
End If
'Divide sentence into individual words
wrd = Regex.Split(",", sentence)
Return wrd
End Sub
Private Sub ParseGPGSV(words() As String) As Boolean
' number of messgaes in complete message
If Not (strEmpty(words(1))) Then
noOfMessages = words(1)
End If
' GPGSV sequence
If Not (strEmpty(words(2))) Then
gPGSVsequence = words(2)
End If
'Neues GPS-Status
If noOfMessages > gPGSVsequence And gPGSVsequence = 1 Then
lstGPSSat.Clear()
End If
'Each sentence contains four blocks of satellite information.
'Read each block and report each satellite's information
Dim count As Short
For count = 1 To 4
'identify satellite
If gPGSVsequence <> 0 Then satelliteNumber = (gPGSVsequence - 1) * 4 + count
' Does the sentence have enough words to analyse?
If words.Length - 1 >= (count * 4 + 3) Then
' Yes. Proceed with analysing the block. Does it contain any information?
If Not (strEmpty(words(count * 4))) And Not (strEmpty(words(count * 4 + 1))) _
And Not (strEmpty(words(count * 4 + 2))) _
And Not (strEmpty(words(count * 4 + 3))) Then
' Yes. Extract satellite information and report it
pseudoRandomCode = words(count * 4)
elevation = words(count * 4 + 1)
azimuth = words(count * 4 + 2)
'signalToNoiseRatio = words(count * 4 + 3).Replace("*","") 'Änderung von mir
Dim GPSSat As myGPSSatellite
GPSSat.Initialize
GPSSat.Azimuth = azimuth
GPSSat.Prn = satelliteNumber
GPSSat.Snr = pseudoRandomCode
GPSSat.Elevation = elevation
GPSSat.UsedInFix = True
lstGPSSat.Add(GPSSat)
End If
End If
Next
If noOfMessages = gPGSVsequence Then
CallSub2(mCallBack, mEventName & "_SatelliteReceived", lstGPSSat)
End If
' Indicate that the sentence was recognised
Return True
End Sub
' Interprets a $GPGGA message
Private Sub Parse_GPGGA(words() As String) As Boolean
' Divide the sentence into words
' satellite-derived time?
If Not(strEmpty(words(1))) And words(6) > 0 Then ParseTime(words(1))
' location?
If Not(strEmpty(words(2))) And Not (strEmpty(words(4))) And words(6) > 0 And words(7) > 6 Then ParseLatLon(words(2), words(4))
'GPS quality indicator (0=invalid; 1=GPS fix; 2=Diff. GPS fix)
If Not(strEmpty(words(6))) Then ParseGPSQuality(words(6))
'HDOP - Horizontal dilution of position
If Not(strEmpty(words(8))) Then ParseAccuracy(words(8))
'Altitude
If Not(strEmpty(words(9))) And IsNumber(words(9)) Then ParseAltitude(words(9))
'Altitude Units
Return True
End Sub
Private Sub Parse_GPRMC(words() As String) As Boolean
' Divide the sentence into words
' satellite-derived time?
If Not(strEmpty(words(1))) Then ParseTime(words(1))
' location?
If Not(strEmpty(words(3))) And Not (strEmpty(words(5))) Then ParseLatLon(words(3), words(5))
'Speed over the ground in knots
If Not(strEmpty(words(7))) Then ParseSpeed(words(7))
Return True
End Sub
Private Sub Parse_GPVTG(words() As String) As Boolean
If Not(strEmpty(words(5))) Then ParseSpeed(words(5))
' Indicate that the sentence was recognised
Return True
End Sub
Private Sub ParseGPSQuality(word As String)
location1.Accuracy = word
End Sub
Private Sub ParseAccuracy(word As String)
location1.Accuracy = word
End Sub
Private Sub ParseSpeed(word As String)
location1.Speed = word / 1.852
End Sub
Private Sub ParseTime(word As String)
Select word.Length
Case 6
DateTime.TimeFormat = "HHmmss"
Case 8
DateTime.TimeFormat = "HHmmss.S"
Case 9
DateTime.TimeFormat = "HHmmss.SS"
Case 10
DateTime.TimeFormat = "HHmmss.SSS"
End Select
location1.Time = DateTime.TimeParse(word) + offspan
DateTime.TimeFormat = DefaultTimeFormat
End Sub
Private Sub ParseLatLon(latWord As String, lonWord As String)
Dim myval1 As Double
Dim myval2 As Double
' Parse Latitude
myval1 = latWord.SubString2(0, 2) ' First two characters
myval2 = latWord.SubString(2) ' Remaining characters
myval2 = myval2 / 60.0
location1.Latitude = NumberFormat(myval1 + myval2, 1, 14)
' Parse Longitude
myval1 = lonWord.SubString2(0, 3) ' First three characters
myval2 = lonWord.SubString(3) ' Remaining characters
myval2 = myval2 / 60.0
location1.Longitude = NumberFormat(myval1 + myval2, 1, 15)
End Sub
Private Sub ParseAltitude(Word As String) 'ignore
location1.Altitude = Word
End Sub
Private Sub strEmpty(st As String) As Boolean
If st.Length = 0 Or st.Trim = "" Then Return True
Return False
End Sub
Private Sub Left(Text As String, Length As Int) As String
If Length>Text.Length Then Length=Text.Length
Return Text.SubString2(0, Length)
End Sub