GPS Modul ansteuern mit GPS Libary Problem

Hallo,

Ich versuche jetzt schon eine ganze Weile dieses GPS Modul:

http://www.ebay.de/itm/370815006897?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649

mit einem Arduino Uno und der TinyGPS Libary:

http://arduiniana.org/libraries/tinygps/

anzusteuern.
Eigentlich habe ich alles so gemacht wie in diesem Tutorial:

Wenn ich den Scetch aber laufen lasse bekomme ich nichts auf den Seriellen Monitor geschrieben.

Hier mein Code:

#include <SoftwareSerial.h>
#include <TinyGPS.h>
 
long lat,lon; // create variable for latitude and longitude object
 
SoftwareSerial gpsSerial(2, 3); // create gps sensor connection
TinyGPS gps; // create gps object
 
void setup(){
  Serial.begin(9600); // connect serial
  gpsSerial.begin(4800); // connect gps sensor
}
 
void loop(){
  while(gpsSerial.available()){ // check for gps data
   if(gps.encode(gpsSerial.read())){ // encode gps data
    gps.get_position(&lat,&lon); // get latitude and longitude
    // display position
    Serial.print("Position: ");
    Serial.print("lat: ");Serial.print(lat);Serial.print(" ");// print latitude
    Serial.print("lon: ");Serial.println(lon); // print longitude
   }
  }
}

GND des Arduino habe ich mit GND des GPS Moduls verbunden
5V des Arduinos mit Vcc des GPS Moduls
Pin 2 des Arduinos mit RX des Moduls und
Pin 3 des Arduinos mit TX des Moduls

Kann mir jemand sagen was ich falsch mache?
Danke schon mal im Vorraus.

Epijano:
Pin 2 des Arduinos mit RX des Moduls und
Pin 3 des Arduinos mit TX des Moduls

Kann mir jemand sagen was ich falsch mache?

Du bist ein RX/TX-Vertauscher!

Serielle Kommunikation geht in beide Richtungen, und was der eine sendet (über sein TX), das empfängt der andere (über sein RX). Und umgekehrt.

Die Reihenfolge beim Deklarieren von SoftwareSerial ist erst RX, dann TX beim Arduino:
SoftwareSerial gpsSerial(2, 3); // RX, TX

D.h. an Pin-2 ist beim Arduino "R" wie "Receive" für SoftwareSerial geschaltet.

Und bei der seriellen Datenkommunikation mußt Du RX/TX zwischen "Sender" und "Empfänger" immer überkreuz vertauschen. D.h. was dem Arduino sein "RX" (Receive) ist dem GPS sein "TX" (Transmit).

Wenn Du das GPS-Modul nicht umkonfigurieren, sondern mit der Standardkonfiguration betreiben möchtest, braucht "RX" (Empfangsdaten) beim GPS-Modul nicht angeschlossen zu werden. Dann kannst Du auch nicht aus Versehen die Standardkonfiguration zerschießen.

Verbinde also nur Pin-2 Arduino-RX Empfangsdaten mit GPS-TX-Sendedaten!
(Und natürlich VCC und GND)

Oder stelle es bei Beibehaltung Deiner derzeitigen Verkabelung im Sketch um auf:
SoftwareSerial gpsSerial(3,2 ); // RX, TX

P.S.: Wenn am Board des GPS-Moduls die grüne LED im Sekundentakt aufblinkt, sendet das Modul Daten. Das kann bei einem Kaltstart bis zu zwei Minuten dauern.

Ah, danke das war aufschlussreich.
Ich hab jetzt an Datenübertragung nur noch TX vom Modul an Pin 2 des Arduinos angeschlossen.
Die LED blitzt auch aber auf dem Seriellen Monitor bekomme ich trotzdem nichts angezeigt :~...

Epijano:
Ah, danke das war aufschlussreich.
Ich hab jetzt an Datenübertragung nur noch TX vom Modul an Pin 2 des Arduinos angeschlossen.
Die LED blitzt auch aber auf dem Seriellen Monitor bekomme ich trotzdem nichts angezeigt :~...

Weiterhin würde ich mal vermuten, dass Dein GPS-Modul standardmäßig auf 9600 und nicht auf 4800 sendet, so dass Du die Serial.Initialisierung besser so machst:

void setup(){
  Serial.begin(38400); // connect serial
  gpsSerial.begin(9600); // connect gps sensor
  Serial.println("Good night and good luck!");
}

Nicht vergessen, den Seriellen Monitor auf 38400 einzustellen!
Den am Anfang zu Kontrollzwecken ausgegebenen Text kannst Du natürlich ändern, der dient nur für Dich zur Kontrolle, ob Du am seriellen Monitor die richtige Serial-Geschwindigkeit eingestellt hast. Ist sie falsch eingestellt, siehst Du den Text nicht. Und dann kannst Du ggf. auch lange warten, bis irgendwelche Daten im Seriellen Monitor angezeigt werden.

Vielen Dank, das war der Fehler.

Ich hab doch noch eine Frage.
Kann man mit der Libary auch die Höhe (über dem Meeresspiegel) auslesen? Und wenn ja, wie?
Dazu hab ich bisher leider nichts gefunden...

Epijano:
Ich hab doch noch eine Frage.
Kann man mit der Libary auch die Höhe (über dem Meeresspiegel) auslesen? Und wenn ja, wie?
Dazu hab ich bisher leider nichts gefunden...

Wenn ich mals kurz google, müßte das so gehen:

float altitude=gps.f_altitude(); // +/- altitude in meters

Laut Quelltext der TinyGPS Library wertet diese die NMEA Sentences "GPRMC" und "GPGGA" vom GPS-Receiver aus. Daher sollte die Library auch die Daten bereitstellen, die in diesen NMEA Sentences enthalten sind.

Die GPS-Höhenmessung ist allerdings eine sehr unsichere und ungenaue Sache.
In der Tat ist GPS auf die Feststellung der horizontalen Position optimiert und nicht auf die vertikale Position.
Über den Daumen gepeilt würde ich sagen, dass die vertikale Position dreimal ungenauer ist als die horizontale, d.h. wenn Du die horizontale Position bei gutem Empfang auf +/-10m genau ermitteln kannst, dann ist die vertikale Position "über Meereshöhe" vielleicht auf +/-30m genau. Unter optimalen Bedingungen auf völlig freiem Feld in der Ebene vielleicht jeweils die Hälfte davon.

Was damit zusammenhängt, dass die Erde keine Kugel ist und auch kein perfekten Ellipsoid ist. GPS berechnet die Höhe aber in Bezug auf ein gleichmäßiges Ellipsoid, das so in der Realität einfach nicht existiert. Das wird dann "mean sea level" genannt, obwohl das gar nicht stimmt. Es gibt Unregelmäßigkeiten im Gravitationsfeld der Erde - auf Grund dichterer im Erdinneren - die lokal die Oberfläche verändern (um bis zu 100m gegenüber dem Referenz-Ellipsoid an den extremsten Stellen).

Wobei es durch neuere Satellitenmessungen des Gravitationsfelds auch High-End GPS-Empfänger gibt, die mit genaueren Geoiden rechnen.

Okay, mit besonders genauen Angaben kann ich also nicht rechnen.
Wenn ich die Funktion gps.f_altitude(); verwende bekomme ich aber immer nur 10000 zurückgegeben.

Epijano:
Okay, mit besonders genauen Angaben kann ich also nicht rechnen.
Wenn ich die Funktion gps.f_altitude(); verwende bekomme ich aber immer nur 10000 zurückgegeben.

Wenn Du ernsthaft etwas mit einem GPS-Empfänger machen möchtest, müßtest Du davon weggkommen, die "SoftwareSerial" Library zu verwenden, die mit der Arduino-Software mitgeliefert wird. Das Ding ist so grausam, das produziert in praktisch jedem Sketch, den ich damit ausprobiert habe, immer wieder Fehler beim Datenempfang.

Hast Du vielleicht ein Board zur Verfügung, das mehr als eine hardwaremäßig vorhandene serielle Schnittstelle unterstützt, z.B. einen MEGA?

Wenn nicht, dann installiere Dir mal eine "alternative" Library, um eine SoftwareSerial-Schnittstelle bereitzustellen, z.B. diese hier:
http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

Dann schreibe Deinen Sketch um, damit statt SoftwareSerial die Library AltSoftSerial verwendet wird.

Nachtrag: Ich habe selbst gerade mal mit AltSoftSerial auf einem UNO getestet, damit läuft es einwandfrei.

Geänderter Test-Sketch für GPS-Module auf 9600 Baud und den seriellen Monitor auf 38400 Baud laufend:

// #include <SoftwareSerial.h>
#include <AltSoftSerial.h>

#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

TinyGPS gps;
// SoftwareSerial ss(4, 3);
AltSoftSerial ss; // with Uno use RX=8, TX=9 only!

static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(38400);
  
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");

  ss.begin(9600);
}

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  
  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();
  
  smartdelay(1000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartdelay(0);
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("********** ******** ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartdelay(0);
}

Arduino RX-Pin kann mit AltSoftSerial nicht frei ausgewählt werden, sondern mit AltSoftSerial ist beim UNO RX fest auf Pin-8, also TX vom GPS-Modul mit RX Pin-8 am UNO verbinden.

Aber achte mal im Vergleich zu SoftwareSerial auf die Spalte "Checksum Fail". Mit SoftwareSerial kannst Du zusehen, wie "Checksum Fail" von Sekunde zu Sekunde größer wird, so viele Datenfehler verursacht die SoftwareSerial Library. Mit der AltSoftSerial Library bleibt "Checksum Fail" ganz stabil bei "0" stehen.

Höhenangaben werden übrigens nicht immer mitgeliefert, sondern nur dann, wenn kein "2D fix" vom GPS-Modul geliefert wird, sondern ein "3D fix". Das muß man nicht extra umschalten, sondern das Modul liefert einfach: Bei schlechtem Empfang kommen 2D fix Datensätze ohne Höhenangaben, bei besserem Empfang 3D fix Datensätze mit Höhenangaben. Die TinyGPS-Library kann meines Wissens nach nicht auswerten, ob 2D oder 3D Daten kommen. Als Anhalt kann Dir aber die Anzahl der Satelliten dienen, die TinyGPS anzeigt: Mit 0, 1 oder 2 Satelliten bekommst Du überhaupt keine Positionsangaben, mit 3 Satelliten bekommst Du Längen- und Breitengradangaben, und mit 4 oder mehr Satelliten bekommst Du auch Höhenangaben mitgeliefert. So als grober Anhalt "über den Daumen gepeilt", ohne dass man direkten Zugriff auf alle gelieferten Daten hat, sondern nur die paar minimalen Daten, die die TinyGPS-Library von den gelieferten Daten auswerten kann.

Ich bin jetzt auch endlich dazugekommen das GPS Modul mit der AltSoftSerial Libary auszuprobieren.

Damit kann ich die (ungefähre) Höhe jetzt auslesen.

Danke.