A Simple GPS Problem
I'm trying to get usable data parsed out of my GPS module, and I'm attempting to use a program borrowed from The Official Guide, Chapter Nine. For the purpose of the example Im trying to display the GPS time value on the PST. I chose time since it changes and does not require me to move around to confirm an updated value.
My routine: GPS_String_to_PST works just fine, so I know the GPS works.
However, my routine: GPS_Time sends a bunch of repeated gibberish to the PST.
I'm sure this problem has been soleved a hundred times before, so if anybody has SIMPLE, one cog example where I can write Heading:=GPS.heading, I would apprciate it very much.
Thank You!
Steve
My routine: GPS_String_to_PST works just fine, so I know the GPS works.
However, my routine: GPS_Time sends a bunch of repeated gibberish to the PST.
I'm sure this problem has been soleved a hundred times before, so if anybody has SIMPLE, one cog example where I can write Heading:=GPS.heading, I would apprciate it very much.
Thank You!
Steve


Comments
Thank You!
Steve
'' ***************************** '' GPS routines '' (c) 2007 Perry James Mole '' [email]pjm@ridge-communications.ca[/email] '' ***************************** '' 05-13-2009 - JMH - Modified to accept input pin number assignments '' 05-14-2009 - JMH - Added functions to seperate the deg/min from lat/long ' PVH Comment - Excellent small GPS reader routines. ' $GPRMC Recommended minimum data ie: $GPRMC,081836,A,3751.6565,S,14507.3654,E,000.0,360.0,130998,011.3,E*62 ' $GPGGA GPS Fix Data ie: $GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75 ' $PGRMZ eTrex proprietary barametric altitude ft ie: $PGRMZ,453,f,2*18 CON CR = 13 ' ASCII <CR> LF = 10 ' ASCII <LF> serXmit = 0 ' Serial Transmit for UART - not used VAR long gps_stack[10] byte GPRMCb[68],GPGGAb[80],PGRMZb[40] long GPRMCa[20],GPGGAa[20],PGRMZa[20] byte gps_buff[80],Rx',cksum long cog,cptr,ptr,arg,j long Null[1] byte latlong_buf[10] OBJ uart : "FullDuplexSerial_mini" PUB start(serRecvPin, baudRate) : okay '' Starts uart object (at baud specified) in a cog '' -- returns false if no cog available okay := uart.start(serRecvPin,serXmit,0,baudRate) return cog := cognew(readNEMA,@gps_stack) + 1 PUB readNEMA Null[0] := 0 repeat longfill(gps_buff,20,0) repeat while Rx <>= "$" ' wait for the $ to insure we are starting with Rx := uart.rx ' a complete NMEA sentence cptr := 0 repeat while Rx <>= CR ' continue to collect data until the end of the NMEA sentence Rx := uart.rx ' get character from Rx Buffer if Rx == "," gps_buff[cptr++] := 0 ' If "," replace the character with 0 else gps_buff[cptr++] := Rx ' else save the character if gps_buff[2] == "G" if gps_buff[3] == "G" if gps_buff[4] == "A" copy_buffer(@GPGGAb, @GPGGAa) if gps_buff[2] == "R" if gps_buff[3] == "M" if gps_buff[4] == "C" copy_buffer(@GPRMCb, @GPRMCa) if gps_buff[0] == "P" if gps_buff[1] == "G" if gps_buff[2] == "R" if gps_buff[3] == "M" if gps_buff[4] == "Z" copy_buffer(@PGRMZb, @PGRMZa) pub copy_buffer ( buffer,args) bytemove(buffer,@gps_buff,cptr) ' copy received data to buffer ptr := buffer arg := 0 repeat j from 0 to 78 ' build array of pointers if byte[ptr] == 0 ' to each if byte[ptr+1] == 0 ' record long[args][arg] := Null ' in else ' the long[args][arg] := ptr+1 ' data buffer arg++ ptr++ ' now we just need to return the pointer to the desired record pub altitude return PGRMZa[0] pub valid return GPRMCa[1] pub speed return GPRMCa[6] pub heading return GPRMCa[7] pub date return GPRMCa[8] pub GPSaltitude return GPGGAa[8] pub time return GPGGAa[0] pub latitude return GPGGAa[1] pub latitude_degpart | byte_ptr byte_ptr := GPGGAa[1] latlong_buf[0] := byte[byte_ptr++] latlong_buf[1] := byte[byte_ptr++] latlong_buf[2] := 0 return @latlong_buf pub latitude_minpart | byte_ptr, i, numchars byte_ptr := GPGGAa[1] + 2 numchars := strsize(byte_ptr) repeat i from 0 to (numchars-1) latlong_buf[i] := byte[byte_ptr++] 'Null terminate latlong_buf[i] := 0 return @latlong_buf pub N_S return GPGGAa[2] pub longitude return GPGGAa[3] pub longitude_degpart | byte_ptr byte_ptr := GPGGAa[3] latlong_buf[0] := byte[byte_ptr++] latlong_buf[1] := byte[byte_ptr++] latlong_buf[2] := byte[byte_ptr++] latlong_buf[3] := 0 return @latlong_buf pub longitude_minpart | byte_ptr, i, numchars byte_ptr := GPGGAa[3] + 3 numchars := strsize(byte_ptr) repeat i from 0 to (numchars-1) latlong_buf[i] := byte[byte_ptr++] 'Null terminate latlong_buf[i] := 0 return @latlong_buf pub E_W return GPGGAa[4] pub satellites return GPGGAa[6] pub hdop return GPGGAa[7] 'pub vdop ' return GPGSAa[14]You may want to protect yourself against returned NULL pointers which simply means this part isn't available (not necessarily the time entry).
Also, when you post code please wrap it in [noparse] [/noparse] tags.
I agree about code comments. As much as I appreciate the Chapter 9 code being posted to the FTP site the occasional lack of comments leaves guys like me in the dark.
I'll play with this tonight, but if I want the number values to the left of the decimal all I need to do is declare:
Time:= fds.str(time)
Likewise for the heading:
Heading:=fds.str(Heading)
Best Regards,
Steve
What is the best way to convert the string value to true number?
Thank You
Steve
{************************************************** * GETTING GPS DATA * * * *************************************************** The intent of this program is to practice extracting GPS Data from a data stream to PIN 1 of the Propeller at 9600 baud. } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 RxPin = 1 CR = 13 ' ASCII <CR> LF = 10 ' ASCII <LF> OBJ fds : "FullDuplexSerial" GPS : "GPS_IO_mini" VAR long Time Pub Main GPS_Time 'This sould display the GPS time data to the PST. Pub GPS_Time GPS.start(1,9600) 'Starts the GPS data parser to Rx data at 9600 fds.start(31,30,0,57600) 'Sending data to PST repeat Time:=GPS.time 'Setting global variable time equal to gps.time fds.str(time) 'Transmits time data to PST works great w/o VP active fds.tx(CR) fds.tx(LF) ' waitcnt(clkfreq+cnt)OBJ n: "Numbers" PUB null | addr, value addr := string("204800") value := n.FromStr(addr, n#DEC)There are other conversion objects out there but this one comes with the PropTool so it's available. addr is equivalent to GPS.time.PUB readNEMA Null[0] := 0 repeat [COLOR="red"]longfill(gps_buff,20,0)[/COLOR] repeat while Rx <>= "$" ' wait for the $ to insure we are starting with Rx := uart.rx ' a complete NMEA sentence cptr := 0 ...The line in question should read longfill(@gps_buff,0,20) and just to be on the safe side should really be a bytefill(@gps_buff,0,80). ATM the byte buffer is long aligned so the longfill will work. Alternatively you could simply null-terminate the received string which would void the requirement for clearing the buffer.The copy_buffer method looks slightly supicious as well as it scans 79 elements for arrays which are 68/80 and 40 in size.
Thank You for your prompt response. I think we can call this one solved, if I can just figure out how to re-label the post.
I will make the code changes you suggest to the Read_NEMA method.
Below is the code sample in the hopes that it helps the next person out.
{************************************************** * GETTING GPS DATA * * * *************************************************** The intent of this program is to practice extracting GPS Data from a data stream to PIN 1 of the Propeller at 9600 baud. } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 RxPin = 1 CR = 13 ' ASCII <CR> LF = 10 ' ASCII <LF> OBJ ss : "Simple_Serial" fds : "FullDuplexSerial" GPS : "GPS_IO_mini" n : "Numbers" VAR long Time, ShortTime Pub Main GPS_Time 'This sould display the GPS time data to the PST. Pub GPS_Time GPS.start(1,9600) 'Starts the GPS data parser to Rx data at 9600 fds.start(31,30,0,57600) 'Sending data to PST via FDS repeat fds.str(String("GPS Time as String = ")) fds.str(GPS.time) 'Transmits string pointer to PST displaying the current time fds.tx(CR) fds.tx(LF) fds.str(String("GPS Time as Variable 'TIME' = ")) 'Converts the string value of time to a 10 digit decimal Time := n.FromStr(GPS.time,10) 'Using BASE 10 format fds.dec(Time) ShortTime:=Time-5 'Just playing around and proving to myself that I actually have a real number fds.str(String(" ShortTime = ")) 'Of course when "Time" ends with 00 the value of ShortTime ends in 95 but that fds.dec(ShortTime) 'was not the point of the exercise fds.tx(CR) fds.tx(LF) waitcnt(clkfreq+cnt) 'wait a second just to keep too much data from going to the PSTPerry