GY-NEO6MV2 ESP32 GPS Tutorial (English Version) 1

Dieses Tutorial gibt’s auch in Deutsch: https://shopofthings.ch/gy-neo6mv2-esp32-gps-beispiel/

The following tutorial will show you how to determine the position with an ESP32 development module and a GPS GY-NEO6MV2 module (type: U-Blox NEO-6M, u-Blox is a Swiss company, by the way).

The following material was used (available in our shop):

The code has been extensively documented so hopefully you can understand why each step is required.

As an additional function, the last position is stored in the non-volatile EEPROM memory. This has the advantage that the last postition is read when the module is restarted. This is an advantage if you make a recording and want to prevent the position from landing somewhere in the Atlantic at the start (position 0.0). A step-by-step tutorial on EEPROM can be found here: https://randomnerdtutorials.com/esp32-flash-memory/.

Connection: In the example, the GPS-Rx was connected to the Tx2 pin (yellow) and the GPS-Tx to the Rx2 (green) of the ESP32 module.

The code is also available via our gist here:
https://gist.github.com/janhajk/e54128867e1c695b6151e57f658234bc

Code

Achtung: wenn Du diesen Code hier kopierst, musst Du noch via Suchen/Ersetzen & mit & ersetzen. Der Code-Darsteller scheint da ein Problem zu haben. Oder nimm den Code vom Gist-github-Link oben, der geht Fehlerfrei.

/*
   (c) 2019 by shopofthings.ch
   Beispiel zum Verbinden des GPS Modules mit
   einem ESP32 Modul

   Pinverbindung:
   ESP 3.3V > GPS VCC
   ESP GND  > GPS GND
   ESP RX   > GPS TX
   ESP TX   > GPS RX

   Achtung: RX wird mit TX bzw. TX mit RX verbunden!

   Das GPS Modul hat eine blaue LED. Diese blinkt, wenn Satelliten erreichbar sind. Sind
   keine Satelliten im Sichtfeld, bleibt sie dunkel. Ein Zustand, wo sie immer leuchtet 
   gibt es nicht.

  Troubleshooting:
  - Arduino IDE gibt bei Upload Fehler aus: Boot Taste vor dem Upload gedrückt halten, bis Upload beginnt.
  - 

*/

#include <TinyGPS++.h> // Library über http://arduiniana.org/libraries/tinygpsplus/ downloaden und installieren
#include <HardwareSerial.h> // sollte bereits mit Arduino IDE installiert sein
#include "EEPROM.h" // sollte bereits mit Arduino IDE installiert sein

/*
   mit EEPROM können Daten zwischengespeichert werden,
   ein kleiner Speicher sozusagen. Daten sind auch nach einem
   Reset noch da, wo sie hingeschrieben wurden. Um in den
   Speicher schreiben zu können, muss eine Speichergrösse
   angegeben werden. Diese wird in Bytes angegeben.
   Wir verwenden diese, um den letzten GPS-Fix abzuspeichern
   damit er beim neustart als erstes eingelesen wird. Damit
   wird verhindert, dass z.B. bei einer Aufnahme unsere Position
   als erstes auf den 0,0 Punkt springt, der irgendwo im Atlantischen
   Ozean liegt.

   Der Speicher bei ESP32 kann zwischen 4 und maximum 1984 bytes liegen
*/
#define EEPROM_SIZE 128

/*
   Als nächstes wird das Programmobjekt für das GPS erstellt, wir nennen
   die Variable die darauf zeigt einfach "gps"
*/
TinyGPSPlus gps;

/*
   Nun müssen wir eine serielle Verbindung zum GPS Modul erstellen
   ESP32 unterstützt bis zu 3 Hardware Serielle Verbndungen. Deshalb
   müssen wir auch nicht die Softwareserial-Library verwenden.
   Die Zahl in der Klammer ist die uart_nr. Damit werden die drei möglichen
   Verbindungen unterschieden. Für ESP32 kann dieser Wert also 0, 1 oder 2 sein
*/
HardwareSerial SerialGPS(1);

/*
   Als nächstes erstellen wir ein Template-Object, wo wir die ganzen Daten
   in einer Variable abspeichern können, die vom GPS Modul gelesen werden
   Im Anschluss erstellen wir gleich so eine neue Variable, "gpsState"
*/
struct GpsDataState_t {
  double originLat = 0;
  double originLon = 0;
  double originAlt = 0;
  double distMax = 0;
  double dist = 0;
  double altMax = -999999;
  double altMin = 999999;
  double spdMax = 0;
  double prevDist = 0;
};
GpsDataState_t gpsState = {};

/*
   Mit der nachfolgenden Konstante definieren wir die Ausgabegeschwindigkeit
   im Serial Monitor. Diese wird in Millisekunden angegeben.
   Darunter die dazugehörigen Variablen, um diese Beschränkung zu erreichen
*/
#define TASK_SERIAL_RATE 1000 // ms
uint32_t nextSerialTaskTs = 0;
uint32_t nextOledTaskTs = 0;

/*
   Setup Funktion.
   Diese wird einmal beim Systemstart ausgeführt
   Enthält alle Initialisierungen
*/
void setup() {

  // Serial ist die Ausgabe im Serial Monitor
  Serial.begin(115200);

  /*
      Die Verbindung mit dem GPS Modul. Wir
      void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL);
      baud: baudrate gemäss Spzifikation des GPS Moduls, in diesem Fall 9600
      config: default Wert
      rxPin: ein RX-Pin z.B. 16
      txPin: ein RX-Pin z.B. 17
  */
  SerialGPS.begin(9600, SERIAL_8N1, 16, 17);

  /*
     EEPROM Speicher initialisieren, wenn noch nicht existent
  */
  while (!EEPROM.begin(EEPROM_SIZE)) {
    true;
  }

  /*
     Die drei Achsrichtungen x, y, z aus dem Speicher
     lesen und hinterlegen
  */
  long readValue;
  EEPROM_readAnything(0, readValue);
  gpsState.originLat = (double)readValue / 1000000;

  EEPROM_readAnything(4, readValue);
  gpsState.originLon = (double)readValue / 1000000;

  EEPROM_readAnything(8, readValue);
  gpsState.originAlt = (double)readValue / 1000000;

}

/*
   Hilfsfunktionen um vereinfacht Speicher zu lesen und schreiben
*/
template <class T> int EEPROM_writeAnything(int ee, const T&amp; value)
{
  const byte* p = (const byte*)(const void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++)
    EEPROM.write(ee++, *p++);
  return i;
}

template <class T> int EEPROM_readAnything(int ee, T&amp; value)
{
  byte* p = (byte*)(void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++)
    *p++ = EEPROM.read(ee++);
  return i;
}


/*
   Loop Funktion
   Diese wird bei jedem Systemtakt ausgeführt
*/
void loop() {

  static int p0 = 0;

  // GPS Koordinaten von Modul lesen
  gpsState.originLat = gps.location.lat();
  gpsState.originLon = gps.location.lng();
  gpsState.originAlt = gps.altitude.meters();

  // Aktuelle Position in nichtflüchtigen ESP32-Speicher schreiben
  long writeValue;
  writeValue = gpsState.originLat * 1000000;
  EEPROM_writeAnything(0, writeValue);
  writeValue = gpsState.originLon * 1000000;
  EEPROM_writeAnything(4, writeValue);
  writeValue = gpsState.originAlt * 1000000;
  EEPROM_writeAnything(8, writeValue);
  EEPROM.commit(); // erst mit commit() werden die Daten geschrieben

  gpsState.distMax = 0;
  gpsState.altMax = -999999;
  gpsState.spdMax = 0;
  gpsState.altMin = 999999;

  /*
   * Rohdaten von Serieller Verbndung zum GPS-Modul
   * einlesen. Die Daten werden mittels TinyGPS++ verarbeitet
   * Die Daten werden bewusst erst nach der Zuweisung der Variablen
   * gelesen, damit wir noch im nachfolgenden vereinfacht 
   * Berechnungen anstellen können.
   */
  while (SerialGPS.available() > 0) {
    gps.encode(SerialGPS.read());
  }

  /*
    Various calculations of maximum and minimum values and distance traveled
    These are only made if at least one fix with 4 satellites is available,
    at most the accuracy would not be given and incorrect values would be calculated.
   */
  if (gps.satellites.value() > 4) {
    gpsState.dist = TinyGPSPlus::distanceBetween(gps.location.lat(), gps.location.lng(), gpsState.originLat, gpsState.originLon);

    if (gpsState.dist > gpsState.distMax &amp;&amp; abs(gpsState.prevDist - gpsState.dist) < 50) {
      gpsState.distMax = gpsState.dist;
    }
    gpsState.prevDist = gpsState.dist;

    if (gps.altitude.meters() > gpsState.altMax) {
      gpsState.altMax = gps.altitude.meters();
    }

    if (gps.speed.kmph() > gpsState.spdMax) {
      gpsState.spdMax = gps.speed.kmph();
    }

    if (gps.altitude.meters() < gpsState.altMin) {
      gpsState.altMin = gps.altitude.meters();
    }
  }

  /*
    So that not too much data is output in the serial monitor,
    we limit the output to the number of milliseconds that we have
    stored in the constant "TASK_SERIAL_RATE"...
  */
  if (nextSerialTaskTs < millis()) {
    Serial.print("LAT=");  Serial.println(gps.location.lat(), 6);
    Serial.print("LONG="); Serial.println(gps.location.lng(), 6);
    Serial.print("ALT=");  Serial.println(gps.altitude.meters());
    Serial.print("Sats=");  Serial.println(gps.satellites.value());
    Serial.print("DST: ");
    Serial.println(gpsState.dist, 1);
    nextSerialTaskTs = millis() + TASK_SERIAL_RATE;
  }
}

One Comment

    Trackbacks and Pingbacks

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.