GPS dla Arduino, Raspberry i innych

GPS powoli wchodzi pod strzechy. Ceny tych modułów nadal nie są niskie, ale sytuacja zdecydowanie idzie ku lepszemu.

GPS dla uC
GPS dla uC

Opisywany przeze mnie moduł składa się z 2 części: płytki układu oraz połączonej z nią krótkim przewodem anteny ceramicznej. Koszt to około 90 PLN. Jako wielbiciel budowania z niczego i za jak najmniej, musiałem znaleźć bardzo dobry powód, żeby go zakupić. I znalazłem!

Instalacja

Moduł komunikuje się za pomocą interfejsu szeregowego.

Pin modułu Funkcja Podłącz do
Tx UART: Nadawanie Rx odbiornika
Rx UART: Odbiór Tx odbiornika
Vcc Zasilanie +3.3V lub +5V
Gnd Masa Masa

Wystarczy odpowiednio podłączyć piny komunikacyjne Rx/Tx, dodać zasilanie i już powinniście zobaczyć dane (o ich formacie -NMEA – poniżej).

Moduł nie ma wlutowanych pinów. Będziecie to musieli zrobić sami. Możecie przylutować kabelki bezpośrednio do otworów na płytce. Pozwoli to na obniżenie profilu. Ja jednak wolę 'demontowalne’ rozwiązania – dlatego zdecydowałem się na kątowe piny

Nie bójcie się lutowania. To naprawdę nie jest skomplikowane. Wystarczy zwykła lutownica kolbowa za kilkanaście złotych (transformatorowe są trochę nieporęczne; moc nie jest tu kluczowym elementem), jakaś cyna lutownicza i same goldpiny 2.54mm – do dostania w każdym sklepie z elementami elektronicznymi. Operacja zajmuje chwilę:

  • Przełóżcie piny przez dziurki na krawędzi modułu
  • Unieruchomcie moduł tak, żeby wygodniej się lutowało (np. taśmą klejącą)
  • (opcja) Nałóżcie flux na punkty lutowania
  • Podgrzejcie piny lutownicą przykładając cynę
Moduł GPS - dolutowane piny
Moduł GPS – dolutowane piny

I to wszystko. Pamiętajcie o zabezpieczeniu miejsca gdzie pracujecie oraz o własnym bezpieczeństwie – lutownica jest gorąca.

Instalacja pod Raspberry

Moduł działa z napięciami zarówno 3,3 jak i 5V. Nie ma więc problemu, żeby podłączyć go do Raspberry. Patrząc na GPIO od góry:

Podłączenie do GPIO Raspberry
Pin GPS Pin RPi Pin GPS
Podłącz do vcc 1:3.3V 2:5V
3:SDA 4:5V
5:SCL 6:GND Podłącz do masy
7:GPIO4 8:Tx Podłącz do Rx
9:GND 10:Rx Podłącz do Tx

Poniższą konfigurację wykonałem na dystrybucji OSMC (multimedia z Kodi). Dla czystego Raspbiana będziecie musieli wyłączyć konsolę, która domyślnie uruchamia się jako /dev/ttyAMA0. Instrukcje jak to zrobić znajdziecie tutaj.

Zgodnie z instrukcjami, które możecie znaleźć na Adafruit i blogu Wenzlaff.de:

  • $ sudo cat /dev/ttyAMA0
    …i już po chwili powinniście widzieć namiary z GPSu w oknie konsoli. [CTRL]+[Z] zatrzyma wydruk.
  • Zainstalowanie usługi gps wymaga kilku dodatkowych zabiegów. Zacznijcie od dodania zestawu wymaganych narzędzi:
    $ sudo apt-get -y install gpsd gpsd-clients python-gps
  • Możecie teraz uruchomić demona (czasami trzeba go zabić i uruchomić ponownie):
    $ sudo gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock
    A następnie mały, tekstowy interfejs:
    $ cgps -s
  • Jeżeli chcecie, żeby usługa gps była dostępna dla systemu po starcie (na podstawie tego i tego):
    • Zmieńcie zawartość /etc/default/gpsd na:
      $ sudo nano /etc/default/gpsd
      START_DAEMON="true"
      USBAUTO="false"
      DEVICES=""
      GPSD_OPTIONS="/dev/ttyAMA0"
      GPSD_SOCKET="/var/run/gpsd.sock"
    • Zainstalujcie usługę i zrestartujcie system:
      $ sudo dpkg-reconfigure gpsd
      $ sudo reboot
    • Po restarcie:
      $ service gpsd status
      * gpsd.service - GPS (Global Positioning System) Daemon
      Loaded: loaded (/lib/systemd/system/gpsd.service; static)
      Active: inactive (dead)
      …widać stąd, że usługa niechętnie startuje. Ja rozwiązałem to poprzez uzupełnienia skryptu rc.local:
      $ sudo nano /etc/rc.local
      ...
      service gpsd start &
      exit 0

      Teraz po restarcie Maliny:
      $ service gpsd status
      * gpsd.service - GPS (Global Positioning System) Daemon
      Loaded: loaded (/lib/systemd/system/gpsd.service; static)
      Active: active (running) since Sun 2015-04-26 07:06:55 UTC; 1min 12s ago
      Main PID: 300 (gpsd)
      CGroup: /system.slice/gpsd.service
      `-300 /usr/sbin/gpsd -N /dev/ttyAMA0
      $ cgps -s

Ekran cgps -s powinien wyglądać mniej więcej tak:

Raspberry - gps
Raspberry – gps

gpsd to usługa systemowa, która instaluje się na porcie 2947. Odbiera komendy i zwraca wskazane dane. W razie, gdybyście widzieli w cgps ciągle NO FIX, zrestartujcie usługę gpsd.

A teraz kawałek kodu w Pythonie (tylko nie nazywajcie pliku gps.py):

#na podstawie: http://stackoverflow.com/questions/15167434/gps-daemon-on-raspberry-pi
#na podstawie: http://www.catb.org/gpsd/client-howto.html
import gps
session = gps.gps("localhost", "2947")
session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE )
while True:
  report = session.next()
  #klasa TPV zawiera kilka ciekawych informacji
  if report['class'] == 'TPV':
    if hasattr(report, 'time'):
      print "czas:",report.time
    if hasattr(report, 'lat'):
      print "\tszerokosc:\t",report.lat
    if hasattr(report, 'lon'):
      print "\tdlugosc:\t",report.lon
    if hasattr(report, 'speed'):
      print "\tszybkosc:\t",report.speed
  #tu znajdują się satelity i parametry transmisji
  if report['class'] == 'SKY':
    if hasattr(report, 'satellites'):
       print "\tsatelity:\t", len(report.satellites),
       satsUsed = 0
       for st in report.satellites:
         if hasattr(st, 'used'):
            if st.used==True:satsUsed+=1
       print "(uzywane: ", satsUsed, ")"
    if hasattr(report, 'hdop'):
       print "\thdop:\t\t", report.hdop

Wydruk na ekranie:
czas: 2015-04-26T10:56:12.000Z
szerokosc: 51.xxxxxxx
dlugosc: 17.xxxxxxx
szybkosc: 0.11

satelity: 12 (uzywane: 8 )
hdop: 1.65

Kilka słów o klasach:

  • TPV: atrybuty: epx, epy, epv, ept, lon, eps, lat, tag, GBS, track, mode, time, device, climb, alt, speed
  • SKY: gdop, tdop, vdop, hdop, pdop, ydop, tag, xdop, device
  • SKY: satellites: lista satelitów, a każdy: ss, el, PRN, az, used

Instalacja pod Arduino

Podłączenie modułu GPS do Arduino również nie powinno nastręczyć Wam żadnych trudności. Wiele poradników w sieci ogranicza się do wykorzystania pinów 0 i 1. Upraszcza to przykłady użycia, ale jednocześnie sprawia, że dalsza komunikacja z komputerem przez kabel USB nie będzie możliwa. GPS przejmie ten kanał i nie będziecie mogli wgrywać swoich programów tą drogą. Pozostanie programator ICSP lub odłączanie modułu na czas programowania.
Proponuję więc użyć (dostarczanej z Arduino IDE) biblioteki SoftwareSerial i podłączyć piny TX/RX modułu GPS np. odpowiednio do portów 2 i 3.

Podłączenie do Arduino
Pin modułu GPS Pin Arduino
TX 2
RX 3
VCC 3,3 lub 5v
GND GND

Otwórzcie nowy projekt, dodajcie biblitekę 'SoftwareSerial’ (Szkic-Importuj Biblioteki-SoftwareSerial) i wpiszcie przykładowy kod:

//Dodane automatycznie
#include <SoftwareSerial.h>
SoftwareSerial gps = SoftwareSerial(2, 3); //tx, rx

void setup(){
  Serial.begin(9600);
  gps.begin(9600);
}

void loop(){
  char line[250], c;
  int pos;
  if( gps.available() > 0 ){
     pos = 0;
     while( gps.available() > 0 && pos < (sizeof(line)-1)){
       c = gps.read();
       if( c == '$' || pos > 0 )line[pos++]=c;
       if( c == '\n')break;
     }
     if( pos > 0 ){
       line[pos]='\0';
       Serial.println(line);
     }
  }
  delay(50);
}

Załadujcie kod, uruchomcie monitor portu; na ekranie powinny pojawić się namiary z GPS. Oczywiście odbierane dane są w formacie NMEA (poniżej więcej o NMEA). Ich parsowanie może nastręczyć Wam wiele problemów – lepiej więc użyć gotowca. Możecie w tym celu wykorzystać na przykład bibliotekę TinyGPS. Pobierzcie ją spod tego adresu. Plik 'zip’ rozpakujcie do katalogu z bibliotekami Arduino IDE, np. 'C:\Program Files (x86)\Arduino\libraries’. Otwórzcie nowy projekt, dodajcie bibliotekę 'Szkic-Importuj bibliotekę-TinyGPS-13′ i SoftwareSerial (jak powyżej). Poniższy kod powinien na ekranie wyświetlić długość i szerokość:

//Dodane automatycznie
#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial nss(2, 3);
void setup(){
  nss.begin(9600);
  Serial.begin(9600);
}
void loop()
{
  while (nss.available())
  {
    int c = nss.read();
    if (gps.encode(c))
    {
      long lat, lon;
      unsigned long fix_age;
      gps.get_position(&lat, &lon, &fix_age);

      Serial.print("Szerokosc:");Serial.println(lat);
      Serial.print("Dlugosc:");Serial.println(lon);

    }
  }
}

Instalacja pod PC

PC-ety nie są aż tak sprytne i nie mają GPIO. Żeby skomunikować z nimi moduł GPS będziecie potrzebować przejściówki UART-USB. Ja używam takiej z chipem FTDI – nigdy nie sprawiała mi kłopotów.

GPS+Windows
GPS+przejściówka FTDI UART-ISB+Windows

Na przejściówce ustawiłem zworką zasilanie na 5v. Następnie połączyłem piny zasilania, masy i danych (TxD:Rx i RxD:Tx) kabelkami żeńsko-żeńskimi. Pozostało podłączyć całość do USB laptopa,  uruchomić Putty na porcie przejściówki (szybkość 9600) i sycić się danymi w formacie NMEA.

NMEA bez tajemnic

Przyda się Wam wiedzieć kilka rzeczy na temat protokołu NMEA. Protokół ten określa m.in. format danych, jakie zwracane są przez urządzenia GPS. W użyciu możecie spotkać dwie wersje tego protokołu.:

  • NMEA 0183
  • NMEA 2000

Różnice kryją się w szybkości transmisji danych (0183:38,6k, 250kbitów/sekundę), NMEA2000 jest protokołem binarnym itp. Mój moduł używa tego pierwszego, na nim się więc skoncentruję.
Dane transmitowane są w postaci znaków. Każda sekwencja danych umieszczana jest w nowej linijce, zaczyna się symbolem '$’ a kończy znakiem końca linii <cr><lf>(carriage return, line feed; 0x10, 0x13). Kolejne rekordy oddzielane są przecinkami. Ten protokół działa w 2 strony – służy do pozyskiwania danych, ale i konfiguracji odbiornika. Przykładowa ramka wygląda następująco:
$GPGGA,161034.00,4100.0000,N,01700.00000,E,1,07,0.99,157.1,M,40.5,M,,*5C
gdzie:

  • GPGGA: polecenie: Global Positioning System Fix Data
  • 161034.00: namiar pobrany o 16:10 GMT
  • 4100.0000,N,: Szerokość geograficzna: 41 deg 00 N
  • 01700.0000,E: Długość geograficzna: 17 st 00 E
  • 1:Jakość namiaru:
    • 0 = błąd
    • 1 = GPS fix (SPS)
    • 2 = DGPS fix
    • 3 = PPS fix
    • 4 = Real Time Kinematic
    • 5 = Float RTK
    • 6 = estymowany
    • 7 = Podany ręcznie
    • 8 = Tryb symulacji
  • 07:Ilość śledzonych satelitów
  • 0.99: (GDOP) poziom błędów wprowadzonych przez satelitę
  • 157.1,M: wysokość nad poziomem morza

Słowo o chipset’cie

Sam układ napędzany jest przez chip firmy u-blox nazywany NEO-6M. Karta katalogowa NEO-6M jest pod tym adresem. Znajdziecie w niej kilka ciekawych danych:

Ilość kanałów 50 Maksymalna liczba satelitów, jaką może jednocześnie śledzić odbiornik. Do prawidłowego namiaru teoretycznie wystarczą 3 satelity a w każdym punkcie Ziemi na raz widać ich… maks. 12
Time-To-First-Fix: cold 27 sekund Czas do uzyskania pierwszego namiaru: cold (zimny) – bez poprzednich namiarów i bez jakichkolwiek załadowanych danych np. dopiero co włączony, nieaktywny dłużej niż kilka godzin.
Time-To-First-Fix:Hot 1 sekund Czas do uzyskania pierwszego namiaru: hot (gorący) – ostanio włączony nie dawniej niż 2 godziny – niektóre z poprawek na położenie satelit mogą być jeszcze w miarę poprawne
Time-To-First-Fix: warm 27 sekund Czas do uzyskania pierwszego namiaru: warm (ciepły) – nieaktyny dłużej niż 2 godziny, ale dane nadal w pamięci
Częstotliwość wysyłania danych (max) 5Hz czyli 5 razy na sekundę

Dane podane przez producenta:

Nazwa produktu APM2,5 GY-NEO6MV2
Model NEO-6MGY-GPS6MV2
Zasilanie 3v-5v
Wymiary anteny 25 * 25mm
Wymiary modułu 25mm * 35mm
Domyślna szybkość UART 9600
Uwagi: Antena ceramiczna, mocny sygnał, zapisuje konfigurację danych w EEPROM, bateria do podtrzymywania bamiaró satelitów (pomaga w starcie hot/warm), dioda sygnalizacyjna LED

Testy

Co Pierwszy czas Pierwsze satelity Pierwszy namiar Gdzie
Po 6h od ostatniego włączenia 38[s] 264[s], hdop=3.13, 6/3 satelitów 325[s] (7/4 satelitów) Pod telewizorem, w półce
Po 15m od ostatniego włączenia 2[s] (12/0 satelitów) 10[s], hdop=4.05, 12/4 22[s] (12/6) Pod telewizorem, w półce
Po 1h od ostatniego włączenia 4[s] (12/7) 3[s], hdop=2.02, 3/5 satelitów 4[s] (12/7 satelitów, hdop=2.14) Pod telewizorem, w półce
Po 7 od ostatniego włączenia 30[s] (6/0) 65[s], hdop=6.79, 5/3 satelitów 65[s] (5/3 satelitów) Pod telewizorem, w półce

Podsumowanie

Podczas testowania moduł zachowywał się rewelacyjnie. Uzyskanie fixa w domu zajmowało mu nie więcej niż 15 sekund. Jest bardzo mały, uniwersalny i elastyczny – zmieści się w wielu projektach. Zwraca uwagę minimalny pobór prądu chipa <70mA.
Moduł jest dostępny w sklepie electropia.pl

Źródła

  • http://arduiniana.org/libraries/tinygps/
  • https://learn.sparkfun.com/tutorials/gps-basics
  • http://www.gpsinformation.org/dale/nmea.htm
  • http://www.benchmark.pl/testy_i_recenzje/Poradnik_jak_wybrac_nawigacje_GPS-2116/strona/5964.html

…a – miało być o POWODZIE zakupu

oto on, idealny do przeróbki na r/c:

Berlin SAR - idealny dla GPS
Berlin SAR – idealny dla GPS

4 komentarze do “GPS dla Arduino, Raspberry i innych”

  1. Czy możesz opisać coś więcej o dokładności tego modułu. Pytam się bo mam taki sam i niestety u mnie nie ma szans na parapecie złapać fixa, a i na zewnątrz łapie dość słabo. Zdziwiłem się, jak piszesz, że u Ciebie w domy łapie do15sekund. Czy to był zimny start? Ile satelitów łapie Ci na parapecie powiedzmy po 1 minucie, a ile po minucie na zewnątrz. Ile czasu zajmuje mu złapanie fixa 3d? Oczywiście zakładając, że niebo jest bezchmurne.
    Pozdrawiam,

    1. sam byłem zaskoczony szybkością fixa. Mieszkam w bloku a testy robiłem zdala od okna i w samochodzie przy dość pochmurnej pogodzie. Nie miałem problemów, może trafiłem w dobrą konfigurację satelitów.
      Możesz coś napisać o konfiguracji? Może miałeś za słabe zasilanie?
      Jak tylko będę miał okazję to powtórzę testy i uzupełnię posta.
      Pozdrawiam,
      Arek

      1. To był mój drugi moduł. Pierwsze przyszedł jakieś noname, zamiast ubloxa, który nawet nie przedstawiał się prawidłowo (dobrze, że Chińczyk oddał pieniądze). Drugi właśnie neo-6m na powyższej płytce i tu jest właśnie słabo. Zasilałem go 5V z interfajsów na USB (CP2102). Teraz zakupiłem Neo-M8N i ten łapie fixa wszędzie. Do dziś myślałem, że NEO-6M jest po prostu dużo słabszy i tak ma być. Trochę mi się to kłóciło z jego popularnością. Jeżeli możesz sprawdzić w wolnym czasie ile satelitów widzi po 1 minucie i z jaką dokładnością (HDOP), ale na zimnym starcie i dać info na maila.
        Z góry dzięki.
        Przemek

        1. Witam,
          uzupełniłem opis i dodałem kilka testów. Moduł leżał w głębi stolika rtv, około 2m od najbliższego okna. Myślę, że wiele zależy od konfiguracji satelitów. Jak widzisz raz fixa po 15 minutach od wyłączenia szukał 22s – innym razem po godzinie pierwszy namiar dostałem po … 4s.
          Pozdrawiam,
          A

Dodaj komentarz