This project demonstrates how to retrieve and make sense of the data
from a NEO-6M GPS Module (costing less than a fiver from ebay).
Other modules can be used, but may have a different serial baud rate,
Using software serial for the GPS module leaves the hardware serial available for 'printing' out the satellite data to serial monitor. It's a quick way to confirm that your module is working correctly and sending back useful data, and it's nice to see where you are on google earth.
It also gives an idea of some of the logging and charting and tracking possibilities available.
When initially powered up it will not have any useful data to send until it has aquired tracking lock on at least 5 satellites, which will then cause it to flash a blue LED to indicate it has tracking lock.
An onboard battery or super-capacitor can hold the satellite info if the module is powered off, but it is not very 'super', so won't hold it very long.
While tracking GPS satellites the module will keep issuing data in the form of NMEA 'sentences', I found out what I needed to know about them from: http://www.gpsinformation.org/dale/nmea.htm but there are many other websites offering similar information.
Basically an NMEA sentence is a comma-delimited string of data - different sentence 'types' sending out different details.
All sentences start with $GPxxx and end with a checksum prefixed with * (ie:*nn) followed by ascii carraige-return+linefeed.
The Neo-6M will run from 3.3v or 5v, and in normal use only requires its TX to connect to a receivers RX (unless you wish to re-program it).
The following snippet receives GPS data into serial2 RX pin 5 and sends the raw characters straight out for viewing on the serial port monitor...
serial2.mode 9600, 4, 5
onserial2 gpschr: wait gpschr: print serial2.chr$; return This next snippet pauses long enough to allow several sentences to be read into a string, then prints the string out to the serial monitor...
serial2.mode 9600, 4, 5
onserial2 gpsinput:
wait
gpsinput:
pause 150 gpsdata$ = serial2.input$ print gpsdata$ return I don't know why the character data shows sentence types that don't appear in the string data and vice versa, but I wasn't bothered enough to find out, because for my purposes I was only interested in 2 types anyway, $GPRMC and $GPGGA to get all the info I wanted.
They both return...
TIME
LATITUDE
LONGITUDE
In addition $GPGGA returns
ALTITUDE
And $GPRMC returns
GROUND SPEED
DIRECTION
DATE
Unfortunately the same info is returned in different positions in different sentence types, but the following script manages the juggling.
When run, notice that the numbered comma-delimited fields show data differently and in different places when selecting different sentence 'types' from the listbox, but the available data is displayed in the correct appropriate fields below for both the $GPRMC and $GPGGA sentences. The Exit button was added to disable serial2 branching on exit to try to prevent the frequent 'exception error' rebooted disconnectionss, but it didn't seem to make any difference. Strangely the errors occur after the script has been stopped rather than during its execution, but perhaps it may be more stable if and when hardware serial becomes available. Eventually I hope to use it in my camper as a means of syncing date and time without
internet access rather than using an RTC, and if sufficient storage media becomes available (ie: SD) it should be possible to data-log travels and overlay the journeys onto google earth maps... but that's something for the future.
Basic:
option.lowram 10000
options$ = "$GPRMC,$GPGGA,$GPGSA,$GPVTG" choice$ = "$GPRMC" gosub clear gpsdat$ = "" gpsdate$ = "" gpstim$ = "" gpstime$ = "" gpslat$ = "" gpshem$ = "" gpslon$ = "" gpsdir$ = "" gpsalt$ = "" gpsmet$ = "" gpsspd$ = "" gpsang$ = "" gosub paint onhtmlreload paint ' TX RX (Only RX is needed) serial2.mode 9600, 4, 5 onserial2 gpsinfo: 'onserial2 gpsinput: 'onserial2 gpschr: wait paint: cls refresh a$ = "" a$ = a$ + |<style> td {padding-right:20px;} </style>| a$ = a$ + |<table style='text-align:right;'>| a$ = a$ + |<tr><td>| + "1" + |</td><td>| + textbox$(w1$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "2" + |</td><td>| + textbox$(w2$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "3" + |</td><td>| + textbox$(w3$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "4" + |</td><td>| + textbox$(w4$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "5" + |</td><td>| + textbox$(w5$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "6" + |</td><td>| + textbox$(w6$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "7" + |</td><td>| + textbox$(w7$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "8" + |</td><td>| + textbox$(w8$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "9" + |</td><td>| + textbox$(w9$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "10" + |</td><td>| + textbox$(w10$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "11" + |</td><td>| + textbox$(w11$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "12" + |</td><td>| + textbox$(w12$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "13" + |</td><td>| + textbox$(w13$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "14" + |</td><td>| + textbox$(w14$,"win100") + |</td></tr>| a$ = a$ + |<tr><td>| + "15" + |</td><td>| + textbox$(w15$,"win100") + |</td></tr>| a$ = a$ + |</table>| a$ = a$ + |<br><br>| a$ = a$ + "Sentence: " + listbox$(choice$,options$,"win100") + string$(10," ") a$ = a$ + "Time:" + textbox$(gpstime$,"win70") + string$(10," ") a$ = a$ + "Date:" + textbox$(gpsdate$,"win70") + string$(10," ") a$ = a$ + "Lat:" + textbox$(gpslat$,"win100") + " " + textbox$(gpshem$,"win25") + string$(10," ") a$ = a$ + "Lon:" + textbox$(gpslon$,"win100") + " " + textbox$(gpsdir$,"win25") + string$(10," ") a$ = a$ + "Alt:" + textbox$(gpsalt$,"win50") + " " + textbox$(gpsmet$,"win25") + string$(10," ") a$ = a$ + "Speed:" + textbox$(gpsspd$,"win50") + string$(10," ") a$ = a$ + "Angle:" + textbox$(gpsang$,"win50") + "<br><br><br>" a$ = a$ + cssid$("win25","width:25px;") a$ = a$ + cssid$("win50","width:50px;") a$ = a$ + cssid$("win70","width:70px;") a$ = a$ + cssid$("win100","width:100px;") a$ = a$ + button$("Exit",serial2exit) + |<br>| refresh html a$ return gpsinfo: pause 170 'start = millis gpsdat$ = serial2.input$ type$ = choice$ sentence$ = "" pos = instr(gpsdat$,type$) if pos > 0 then sentence$ = mid$(gpsdat$,pos) 'pos = instr(sentence$,chr$(13)) pos = instr(sentence$,"*") if pos > 0 then sentence$ = left$(sentence$,pos + 2) if instr(sentence$,type$) = 1 then w1$ = word$(sentence$,1,",") w2$ = word$(sentence$,2,",") w3$ = word$(sentence$,3,",") w4$ = word$(sentence$,4,",") w5$ = word$(sentence$,5,",") w6$ = word$(sentence$,6,",") w7$ = word$(sentence$,7,",") w8$ = word$(sentence$,8,",") w9$ = word$(sentence$,9,",") w10$ = word$(sentence$,10,",") w11$ = word$(sentence$,11,",") w12$ = word$(sentence$,12,",") w13$ = word$(sentence$,13,",") w14$ = word$(sentence$,14,",") w15$ = word$(sentence$,15,",") select case type$ case "$GPRMC" gpstim$ = w2$ gpstime$ = Str$(val(left$(gpstim$,2))+1) + ":" + mid$(gpstim$,3,2) + ":" + mid$(gpstim$,5,2) gpslat$ = w4$ gpshem$ = w5$ gpslon$ = w6$ gpsdir$ = w7$ gpsspd$ = w8$ gpsang$ = w9$ gpsdat$ = w10$ gpsdate$ = Str$(val(left$(gpsdat$,2))+1) + "/" + mid$(gpsdat$,3,2) + "/" + mid$(gpsdat$,5,2) gpsalt$ = "" gpsmet$ = "" case "$GPGGA" gpstim$ = w2$ gpstime$ = Str$(val(left$(gpstim$,2))+1) + ":" + mid$(gpstim$,3,2) + ":" + mid$(gpstim$,5,2) gpslat$ = w3$ gpshem$ = w4$ gpslon$ = w5$ gpsdir$ = w6$ gpsalt$ = w10$ gpsmet$ = w11$ gpsspd$ = "" gpsang$ = "" gpsdate$ = "" case else gpstim$="": gpslat$="": gpshem$="": gpslon$="": gpsdir$="": gpsalt$="": gpsmet$="": gpsspd$="": gpsang$="": gpsdate$="" end select else gosub clear endif endif refresh return serial2exit: onserial2 off end return clear: w1$="": w2$="": w3$="": w4$="": w5$="": w6$="": w7$="": w8$="": w9$="": w10$="": w11$="": w12$="": w13$="": w14$="": w15$="" refresh return gpsinput: pause 150 gpsdata$ = serial2.input$ print gpsdata$ return gpschr: print serial2.chr$; return '-------------------- End --------------------- |