Arduino – GPS

Denna lektion är avsedd för att lära ut lite om GPS och att hantera seriell kommunikation via RS232. En GPS är användbar i många fall såsom att få reda på exakt tid & datum, position och mycket mer. GPSen kan användas för att styra robotar, göra kompasser, verktyg för geocaching och mycket mer. Det trevliga med GPS är att oftast behöver de inte initieras alls, utan direkt från det att de får spänning börjar de spotta ut data via RS232 och som standard finns oftast all information man vill ha. Den GPS modul vi använder i denna lektion är Svensktillverkad från Servicepunkten och finns här i vår webshop, men det finns många andra moduler som vår kod & labb passar till, dels Adfruits modul som bygger på samma GPS chip.

Modulen matas med 5V och kan köras med intern eller extern antenn, vi kör med extern i detta fallet (med magnetfäste) så vi får bra mottagning när vi sitter inomhus och testar. GPS moduler har en standard som heter NMEA 183 och det finns många sidor på nätet om denna standard, men GPSen spottar ut långa strängar av ASCII text som startar med $ sedan en text som beskriver vilken information det är och avslutas med en checksumma och CR+LF (Carrige Return och Line Feed). Dessa strängar är långa och måste “parsas” ut för att få information och det finns många sätt att hantera detta, i detta exempel har vi gjort ett enkelt program för att få ut tid, datum, hastighet samt position och visa detta på en LCD, vi visar positionen i 5 sekunder sedan tid, datum & hastighet i 5 sekunder osv.

Vill man bara testa GPS modulen utan att skriva en rad kod kan man faktiskt koppla in den direkt till Arduino Uno genom att koppla “TX” från GPS till “TX->1” till Arduino Uno, på så vis skickas data upp via USB till debugfönstret. Enheten är förinställd på 9600baud. OBS, det är viktigt att det inte finns något program i Arduino Uno som använder denna I/O, utan sätt den som en ingång utan pullup. I debugfönstret får man du upp alla NMEA kommandon som t.ex. nedan. Denna enkla test fungerar endast på Arduino Uno och inte på Leonardo, då den har en separat UART skild från den man laddar ner program.

$GPGGA,094507.000,5609.6095,N,01335.7731,E,1,9,1.05,80.8,M,38.8,M,,*6B
$GPGSA,A,3,02,05,14,12,25,21,29,31,10,,,,1.47,1.05,1.03*0B
$GPRMC,094507.000,A,5609.6095,N,01335.7731,E,0.03,88.49,120913,,,A*51
$GPVTG,88.49,T,,M,0.03,N,0.05,K,A*06
$PGTOP,11,3*6F $GPGGA,094508.000,5609.6095,N,01335.7731,E,1,9,1.05,80.8,M,38.8,M,,*64
$GPGSA,A,3,02,05,14,12,25,21,29,31,10,,,,1.47,1.05,1.03*0B
$GPRMC,094508.000,A,5609.6095,N,01335.7731,E,0.02,88.49,120913,,,A*5F
$GPVTG,88.49,T,,M,0.02,N,0.04,K,A*06
$PGTOP,11,3*6F
$GPGGA,094509.000,5609.6095,N,01335.7731,E,1,9,1.05,80.8,M,38.8,M,,*65
$GPGSA,A,3,02,05,14,12,25,21,29,31,10,,,,1.47,1.05,1.03*0B
$GPRMC,094509.000,A,5609.6095,N,01335.7731,E,0.02,88.49,120913,,,A*5E
$GPVTG,88.49,T,,M,0.02,N,0.04,K,A*06
$PGTOP,11,3*6F
$GPGGA,094510.000,5609.6095,N,01335.7731,E,1,9,1.05,80.8,M,38.8,M,,*6D
$GPGSA,A,3,02,05,14,12,25,21,29,31,10,,,,1.47,1.05,1.03*0B
$GPRMC,094510.000,A,5609.6095,N,01335.7731,E,0.03,88.49,120913,,,A*57
$GPVTG,88.49,T,,M,0.03,N,0.05,K,A*06
$PGTOP,11,3*6F
$GPGGA,094511.000,5609.6095,N,01335.7731,E,1,9,1.05,80.8,M,38.8,M,,*6C
$GPGSA,A,3,02,05,14,12,25,21,29,31,10,,,,1.47,1.05,1.03*0B
$GPGSV,3,1,12,29,75,210,48,25,68,122,48,31,54,277,32,02,34,057,32*7C
$GPGSV,3,2,12,12,27,111,47,33,21,213,,10,13,046,23,23,07,350,24*7A
$GPGSV,3,3,12,05,07,095,32,21,05,188,29,14,05,234,27,04,04,031,23*7A
$GPRMC,094511.000,A,5609.6095,N,01335.7731,E,0.02,88.49,120913,,,A*57
$GPVTG,88.49,T,,M,0.02,N,0.03,K,A*01
$PGTOP,11,3*6F

Arduino Uno kan arbeta med s.k. “software UART’s”, dvs. där man använder andra pinnar än I/O-0 och I/O-1 för att ta emot eller skicka seriell information, men i detta exempel vi kör här använder vi den inbyggda hårdvaru UARTen, detta då det är mycket information som kommer in och man kan annars lätt missa tecken (en mjukvarubaserad UART är inte snabb, då allt måste emuleras i mjukvaran).

Den NMEA sträng vi skall använda oss av är $GPRMC och det är den som är den mest vanliga som alla GPSer spottar ut. Vi har märkt dessa med fet stil ovan. Som ni ser är varje information separerad med kommatecken, så det är lätt att få ut informationen vi vill använda (man kallar detta för parsing i Engelskan). Parsing används överallt, från att få ut information från givare till att tolka text i en kompilator när texten skall översättas till maskinkod. I denna sträng finns tid, info om data är OK, latitud, longitud, hastighet (i knop), riktning, datum samt en checksumma (efter * finns 2 tecken som är checksumman, men denna kan man kolla om informationen är rätt och ingen felaktigt tecken har smugit sig in). Tid och datum är GMT (Greenwich Mean Time) och är således en timme efter Svensk normaltid (Vindertid), så på sommaren är den 2 timmar efter. Latitud (N/S) och Longitud (E/W) är uppbyggt av grader och minuter, så informationen i NMEA stängen 5609.6156,N samt 01335.7534,E blir +56° 9.6156′ samt +13° 35.7534′ (Norr och Öster är positiva tal). Matar man in detta (+56° 9.6156′, +13° 35.7534′) direkt i Google Maps så får man positionen där LAWICEL AB ligger i Tyringe.

GPS och LCD

Eftersom vi använder oss utav hårdvaru UARTen i Arduino Uno kommer den att krocka med USB så vi kan inte ladda ner program när GPSen är ansluten (med Leonardo får vi inte detta problem, då den har en dedikerad UART som inte används som nedladdning av kod). Inkopplingen ovan är enkel och bygger på samma inkoppling för LCD som i denna lektion, sedan använder vi även 5VDC och GND att mata vår GPS modul samt vi har kopplat TX från GPS till RX på Arduino Uno (låt denna vara urkopplad när du laddar ner ny kod, annars får man upp felmeddelande då GPS data och programkod krockar (GPS modulen spottar ut info kontinuerligt och på 9600baud). Vi använder inte RX på GPSen (vilket man kan göra för att ställa in GPS att skicka mer information, mindre information, skicka data oftare och mycket mer). Genom att göra så här, friar vi upp TX på Arduino Uno, så vi kan skicka debug-information upp till den inbyggda seriella monitorn i Arduino IDE (dock måste vi ha samma hastighet som GPSen är inställd på, dvs. 9600 baud).

Förklaring till hur programmet fungerar kommer, men det finns en hel del dokumenterat i koden så ni får hålla tillgodo med detta tills vi förklarat det mer i detalj.

Är inte GPS ansluten rätt kommer LCD endast att visa “GPS Demo” och “Waiting for NMEA”, detta så man vet att programmet snurrar och LCD är rätt inkopplad. Om GPS är ansluten men är precis påslagen och inte har ställt in sig mot satelliter så får man upp “NMEA Error” på LCD. Detta fel får man upp om den inte har fix mot satelliter eller om det är något annat fel i överföringen. Röd LED blinkar på GPS och när man väl har fått FIX så blinkar blå LED och då kommer data upp på LCD. LCD informationen ändras var femte sekund så att all information får plats. Notera att v ändrat om tid och datum så det visas på Svenskt sätt, men tiden stämmer inte då det är GMT tid (krävs lite rutiner för att kompensera detta), vi har även lagt till och delat upp latitud och longitud i grader och minuter så att det är mer läsbart. Hastigheten är dock rå som den kommer från GPS i Knop.

Koden för vårt projekt hittar du här.

Adafruit har även tagit fram ett LIB för Arduino för att ta emot GPS data, parsa och lägga i variabler mer avancerat än vad vår kod visar, notera dock att detta LIB kräver lite kodutrymme då de använder sig av flyttal. Du hittar deras LIB här. Deras LIB passar den GPS vi använder oss av här i detta exempel men även för Adafruits egen modul eller deras GPS Logger Shield.