parsing GPS NMEA data on a picaxe

hobgoblin

New Member
i am wondering if it is possible to get a picaxe to extract the time and date information from a NMEA serial data stream from a gps module.
the GGA - (Global Positioning System Fix Data) message is the one with all the info im interested in.
see page 7 of http://www.sparkfun.com/datasheets/GPS/Modules/SUP500F_v3.pdf for the structure of the sentance.

i need some ideas and help with the code so that it will output the time and date. (to send to an LCD)

can the picaxe do this fast enough as the GPS module sends the data at 10Hz?

am i correct that if i used the line
serin 1,N9600,(“$GPGGA,”),#b1
with the example sentence in the PDF that b1 would end up 111?
 

Jamster

Senior Member
to be honest, if you just want time and date dont go to the expense of a gps module. i would use a 555 timer and then count the pulses. you can then alter the time with push buttons.

if you do need the gps module then i think you would need to set a higher frequency which you cannot do on some chips.

jamster
 

hobgoblin

New Member
the reason for the GPS module is because it is so accurate and also because i can!!
i also just want to play with them and maybe use it as a simple display for long and lat on the lcd. (geocaching anyone??)
 

Svejk

Senior Member
Yes it is, see this little YouTube video. Uses Picaxe 40x2 but it can be done with a 28x2.

To extract the time just use serin with $GPGGA as a qualifier, then wait for x commas until the field of interest comes up. Something along the lines (assumes field of interest is 5th)

Code:
SERIN Pin, Baud, ("$GPGGA")
for b0 = 0 to 4
  SERIN Pin, Baud, (",")
next b0

PTR = 0

SERIN Pin, Baud, @ptrinc, @ptrinc 'etc
 

MPep

Senior Member
i am wondering if it is possible to get a picaxe to extract the time and date information from a NMEA serial data stream from a gps module.
the GGA - (Global Positioning System Fix Data) message is the one with all the info im interested in.
see page 7 of http://www.sparkfun.com/datasheets/GPS/Modules/SUP500F_v3.pdf for the structure of the sentance.

i need some ideas and help with the code so that it will output the time and date. (to send to an LCD)

can the picaxe do this fast enough as the GPS module sends the data at 10Hz?

am i correct that if i used the line
serin 1,N9600,(“$GPGGA,”),#b1
with the example sentence in the PDF that b1 would end up 111?
Hi HobGoblin,

Incorrect usage of SERIN here.

Use as follows
Code:
 serin 1,N9600.("$GPGGA,"),b1,b2,b3,b4,b5,b6
Now: B1 = 1, B2 = 1, B3 = 1, B4 = 6, B5 = 3, and B6 = 6. Please note that all values are the ASCII values, so "1" is 0x31, or (in Decimal) 48, etc. Use an ASCII converter table to find out the rest :).
Subtract 0x30 and the actual number will be available.

Hope this helps.

MPep.
 

elios

Senior Member
Just putting it out there, I had a pig of a job getting the NMEA to work. I ended up using some elses code, which I have slightly modified for my own testing use.

So thank you to the guy who did this code, here on the PICAXE Forum! I can't remember your name though :(

BEWARE I didn't update the comments :p

Code:
 #PICAXE 20X2
 #TERMINAL 38400
 
 SETFREQ M32
 
'Written on 21-Feb-2009
'For PicAxe28X1  and Serial GMouse GPS
'GPS Serial input on pin 18 ser RX
'LED on pin 28


SYMBOL Hours 		= B1
SYMBOL Minutes 		= B3
SYMBOL Seconds 		= B5
SYMBOL MilliSeconds	= W6


'Blink LED
loop1:


main:
hsersetup B9600_32, %001 		'baud 4800 at 4MHz
hserin [4000,nodata],0,80,("$") 	'wait for $ then receive 80 bytes into sp
ptr = 0 					'reset scratchpad pointer

gettime: 					'GPGGA GPRMC sentences have the time HHMMSS.sss
B0=@ptrinc : if B0<>"G" then mainx
B0=@ptrinc : if B0<>"P" then mainx
B0=@ptrinc : if B0<>"G" then lookforR
B0=@ptrinc : if B0<>"G" then mainx
B0=@ptrinc : if B0<>"A" then mainx
sertxd ("$GPGGA",cr,lf)
goto TXControllerInfo

lookforR:
if B0<>"R" then mainx
B0=@ptrinc : if B0<>"M" then mainx
B0=@ptrinc : if B0<>"C" then mainx
sertxd ("$GPRMC",cr,lf)


'============================================================
TXControllerInfo:
B0 = @ptrinc				'skip comma after NMEA Sentence ID

B0 = @ptrinc - 48				'get tens of hour value
Hours = B0 * 10 + @ptrinc - 48	'add units of the hour value

B2 = @ptrinc - 48				'get tens of minutes value 
Minutes = B2 * 10 + @ptrinc - 48	'add units of the minutes value

B4 = @ptrinc - 48				'get tens of the seconds value
Seconds = B4 * 10 + @ptrinc - 48	'get units of the seconds value

B0 = @ptrinc				'skip decimal

B6 = @ptrinc - 48				'get 1st digit of milliseconds
B7 = @ptrinc - 48				'get 2nd digit of milliseconds
B8 = @ptrinc - 48				'get 3rd digit of milliseconds
MilliSeconds = B6*10 + B7*10 + B8	'calc milliseconds , NOTE the tricky math here with B6*10 not *100 as you would think
sertxd (#Hours,":",#Minutes,":",#Seconds,".",#MilliSeconds," UTC",cr,lf)


goto loop1

nodata:
sertxd ("no data",cr,lf)
goto loop1
mainx:
;sertxd ("x")
goto loop1
 

hobgoblin

New Member
i read about a document from Rev-ed " Introduction to GPS and PICAXE.pdf that explains using gps with picaxe's bur cant find it anywhere.
 

hippy

Ex-Staff (retired)
@ hobgoblin : Yes, it should be as simple as that -

serin 1,N9600.("$GPGGA,"),b1,b2,b3,b4,b5,b6

That should read the six ASCII characters after "$GPGGA," which is the hhmmss text, and -

serout 2,N9600,b1,b2,b3,b4,b5,b6

Should just pass those characters out to the LCD. You'll probably need to set the LCD cursor position to line 1, column 1 before each write to get an overwriting display.

Put it in a loop and it should be done.

You don't need # for the variables because you are reading each of six characters individually, rather than reading a numeric value represented by a sequence of characters.

You could use SERIN ... ("$GPGGA,"),#w0 to read the hhmmss sequence up to its ending comma as a number, but because the value can be greater than 65535 it will get truncated so will not work in practice.
 

hobgoblin

New Member
@ hippy :and add ":" between the hours and minuets and minuets and seconds. ie.
serout 2,N9600,b1,b2,":",b3,b4,":",b5,b6

thanks for that its clear in my head now
 

hobgoblin

New Member
one final question, if i want to do longitude and latitude as well i will need lots of variables so which picaxe has the most variables (18M2 ??)

i could use the eeprom memory but this would slow down the clock and make it less accurate
 
Last edited:

Svejk

Senior Member
One way is to use pointers. Have a read in Manual #2. Some Picaxe have 1024 pointer variables.

Eeprom memory wears with use, not recomended to hold variables.
 

Pauldesign

Senior Member
Any of the X2 PICAXES can do; they have the highest numbers of variables.

Alternatively to variables usage, you may use scratch pad memory; accessing it using the @ptr commands.
 

hippy

Ex-Staff (retired)
You can also re-use variables, for example assume you are reading the time as before -

SerIn 1, N9600, ("$GPGGA,"), b1, b2, b3, b4, b5, b6

Only wanted the seconds value and only wanted to use the minimum number of variables -

SerIn 1, N9600, ("$GPGGA,"), b1, b1, b1, b1, b1, b2

Earlier values put into a variable will be replaced by later values received, so b1 and b2 will ultimately contain the 'ss' part of the time.
 

papaof2

Senior Member
If you're using an X2 chip with background receive (HSERIN), the following code parses the RMC message (the only message needed in the project this code was lifted from). There are many possible improvements - this code was intended to explain (to an Access programmer) what has to be done to get the GPS data. He has come along nicely - he's now writing uMFPU assembly code to parse the GPS data and compute distance and direction to another point, based solely on the two sets of GPS coordinates. Before someone asks, I can't provide that code because of the NDA.

You'll need the proper HSERSETUP line, which depends on the serial speed and the chip speed.
Code:
'==========================================

'B.7 has a Serial LCD that displays the GPS data

main:
hserin [1100, hfail], 0, 64, ("$")	'get GPS message into scratchpad
'goes to hfail when no message in 1.1 seconds

ptr = 2				'point to 3rd character received (0,1,2)
b3 = @ptr			'put character in b3
if b3 <> "R" then		'not an RMC message
	goto main		'back to top
endif

ptr = 17			'18th character
b3 = @ptr
if b3 <> "A" then		'"A" is a valid fix
	serout B.7, t9600, (" No Fix  ")
	goto main
endif

serout B.7, t9600, (254,1)	'clear LCD screen - show valid data

serout B.7, t9600, ("Time:")
ptr = 6				'1st character of time
serout B.7, t9600, (@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc)
'@ptrinc gets value of byte at ptr, then increments ptr by one

serout B.7, t9600, (" ")

ptr = 55					'check for spacing
Dirspace = @ptr
if Dirspace = "," then	'nnn.nn direction
	ptr = 56
else
  ptr = 55				'nn.nn direction
     'yes, ptr set to 55 twice - this is teaching code
endif
serout B.7, t9600, (@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc)

serout B.7, t9600, ("  Lat:")
ptr = 19
serout B.7, t9600, (@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc)
ptr = 29
serout B.7, t9600, (@ptr)

serout B.7, t9600, ("      Lon:")
ptr = 31
serout B.7, t9600, (@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc)
ptr = 42
serout B.7, t9600, (@ptr)

serout B.7, t9600, ("     Spd:")
ptr = 44
serout B.7, t9600, (@ptrinc,@ptrinc,@ptrinc,@ptrinc)

serout B.7, t9600, (" Dir:")
ptr = 49
serout B.7, t9600, (@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc)
if Dirspace = "," then
	serout B.7, t9600, (@ptrinc)
end if

goto main

'===============================
John
 

NXTreme

Senior Member
Alternatively to variables usage, you may use scratch pad memory; accessing it using the @ptr commands.
Unless I'm mistaken, which may well be, the scratchpad memory will wear down as well. If your using it to store variables it will eventually wear out.
 

hippy

Ex-Staff (retired)
True, it seems everything wears out with use and even if not used, but scratchpad is far, far less likely to wear out where Eeprom is guaranteed to wear out with excessive writing.

There would be very few cases where anyone would have to fret over scratchpad wearing out.
 
Top