Projekte - GPS-Position verbessern...
Noch in Arbeit...Seit kurzem fährt im Garten ein "automatischer Rasenmäher" - dieser verwendet sowohl die bekannten Drähte als auch angeblich GPS für die Bestimmung seiner Position auf dem Grundstück.... Da mich speziell die GPS-Funktion natürlich interessiert, habe ich einige Versuche gestartet....
Übersicht: Einführung...Hardware...ein erster Versuch...differentielles GPS und RTKLIB...ein zweiter Versuch..............ESP1 (fester Empfänger)..............ESP2 (mobiler Empfänger)...............ESP3 (zentrales Auswertemodul)...............Resultate...............Fehlersuche und -minimierung....ein dritter Versuch...FAZIT bisher...Einführung...
GPS (Global Positioning System) nutzen wir alle fast täglich - oft ohne es zu merken. So ermitteln z.B. unsere Mobiltelefone unseren Standort und zeigen uns in der "Sprit-Preis-App" immer die nächstgelegene günstigste Tankstelle. Auch würden wir ohne unsere Navigations-Systeme alle wieder "Karten wälzen", wenn wir eine unbekannte Adresse suchen.
Und normalerweise nutzen wir dieses System, ohne uns Gedanken zur Funktionsweise und den technischen Hintergründen zu machen - dies wollen wir hier aber "als Nutzer" auch erst mal so beibehalten - für weitergehende Informationen verweise ich auf das WEB....
Die frei verfügbaren (und bezahlbaren) GPS-Empfänger-Module sind leider oft nur begrenzt für genauere Standortermittlung geeignet (gelegentlich auch aus militärischen Gründen hinsichtlich begrenzter oder verfälschter Daten, aber meist aufgrund der Leistungsfähigkeit der verfügbaren GPS-Empfänger-Module).
Daher gleichen unsere Systeme z.B. im Mobiltelefon zusätzlich noch Daten mit z.B. Mobilfunktürmen etc. ab - diese Möglichkeiten haben wir hier leider nicht.
Ist mir zu kompliziert..... =>.... zurück zur Startseite
Hardware...
Wie immer ist der Markt verfügbarer GPS-Empfänger riesig und die Preise reichen von ca. 4,50 € (s.u.) bis hin zu mehreren hundert bzw. auch tausend Euro für Profi-Geräte. Für meine Versuche nutze ich anfangs eher günstige Modelle wie aktuell das Neo-6-Modul...

Allerdings habe ich mir kürzlich bereits aus "FernOst" noch die hoffentlich genaueren Neo-8-Module geordert - diese sind aber wesentlich teurer.
Als Empfänger für die GPS-Daten nutze ich jeweils ein ESP32-Development-Board, der hardwareseitige Anschluss ist recht simpel
VCC | + 3,3 bis 5.0 Volt (je nach Modell - kann vom ESP abgenommen werden) |
RX...TX | serielle Kommunikationsverbindung zum ESP... |
GND | - der GND-Pol am ESP... |
Hinweis:.... Die RX-/TX-Pins verbindet Ihr mit Eurem ESP32, dabei gibt es mehrere Möglichkeiten, siehe dazu in den folgenden Angaben...
Ist mir zu kompliziert..... =>.... zurück zur Startseite
ein erster Versuch....
Bei meinem ersten Versuch habe ich einen ESP32 mit einem GPS-Empfänger über RX/TX (GPIO 1 und GPIO3) verbunden und die Daten über Bluetooth an meinen RasPi gesendet...
ACHTUNG: Wenn Ihr - wie in vielen Arduino-Beispielen dargestellt - die GPIO1 und GPIO3 am ESP32 verwendet, benötigt Ihr eine "Software-Serial-Bibliothek" und es funktioniert dann weder "Serial.print" noch "WiFi", auch zur Aktualisierung Eurer Software auf dem ESP müsst Ihr dann den GPS-Empfänger immer abziehen..... Bluetooth allerdings funktioniert problemlos - wie ich festgestellt habe. Die später nachfolgenden Versuche habe ich dann aber mit "HardwareSerial" und Anschluss des GPS-Empfängers auf anderen GPIO's ausgeführt...s.u..
Auf dem RasPi jedenfalls hatte ich mir mit Lazarus eine kleine Auswertesoftware gebastelt.....

Wie zu erkennen ist, "driftet" unser ESP-Empfänger wesentlich um den Nullpunkt, teilweise ist der Fehler über die Zeit mehrere Meter groß......ohne das der Empfänger selbst bewegt worden ist.
Zu einem späteren Zeitpunkt habe ich auch am RasPi ein GPS angeschlossen, mangels einer Auswerte-Bibliothek (wie TinyGPS auf dem ESP32) habe ich mir hier anhand von Info's aus dem WEB eigene Formeln abgeleitet und verwendet. Auch diese Ergebnisse zeigten ein analoges Verhalten....
Damit ist also erst mal nicht viel anzufangen - ich habe diese Programme daher auch nicht dokumentiert.
Ist mir zu kompliziert..... =>.... zurück zur Startseite
Differentielles GPS und RTKLIB...
Da aufgrund der "Drift" eines einzelnen GPS-Empfängers mit den Positionsdaten ja nicht viel anzufangen ist, entstand die Idee einen GPS-Empfänger als Festpunkt anzusetzen und einen zweiten GPS-Empfänger dann mit den "Drift"-Werten des ersten Empfängers zu "korrigieren".
Die Theorie ist, das zwei baugleiche (möglichst auch aus der selben Produktionscharge stammende ) GPS-Empfänger ja theoretisch auch gleich "driften" sollten (zumindest im für mich relevanten Nahbereich bis ca. max. 50m) - da sie ja die analogen Empfangs- und Umweltbedingungen haben.
Damit ist dann zwar die Position der Empfänger "auf der Weltkugel" immer noch nicht unbedingt genau - aber die Position des mobilen Empfängers zum stationären Empfänger wäre berechenbar. Und kennt man die genaue Position des stationären Empfängers...
Dieses Verfahren nennt sich "differentielles GPS" und bei WEB-Recherchen trifft man schnell auf das Projekt/Verfahren "RTKLIB".... Angeblich sollen hier Genauigkeiten im Bereich bis auf wenige Zentimeter möglich sein.
Allerdings ist dieses Verfahren nicht ganz simpel und basiert auch auf recht kostenintensiven GPS-Modulen.
Aber ich will versuchen, mir etwas "Ähnliches" mit begrenzten technischen (und finanziellen) Mitteln aufzubauen..... mir würde eine Genauigkeit von ca. 1m (+/- 0.5m Drift) mehr als ausreichen...
Ist mir zu kompliziert..... =>.... zurück zur Startseite
ein zweiter Versuch...
Ursprünglich wollte ich wieder das o.g. System mit Bluetooth und dem RasPi einsetzen, habe mich dann aber entschieden 2x ESP32 als "GPS-Empfänger" einzusetzen und einen dritten ESP32 als "Rechenknecht" für die GPS-Berechnungen zu verwenden.
Somit würde mein RasPi in einer weiteren "Ausbaustufe" dann nur noch die Differenzen zwischen den beiden GPS-ESP32 in "Metern auf der x-/y-Achse" gesendet bekommen und hätte den "Kopf frei" für andere Aufgaben. Auch kann ich so "Fehler" infolge meiner eigenen - ggf. nicht ganz korrekten - "Auswerte-Software (s.o.)" auf dem RasPi eliminieren.
Zur Verbindung der 3 Minirechner habe ich auf WiFi gesetzt und hier die Funktionalität "ESP-Now" verwendet - auf diese Weise können recht einfach mehrere Sender und Empfänger untereinander gekoppelt werden.
Hinweis: Für die Nutzung von "ESP-Now" müsst Ihr die MAC-Adresse des Empfänger-ESP32 ermitteln (an den Ihr dann ja senden wollt). Dafür gibt es im WEB kleine Arduino-Programmsketche - da müsst Ihr mal suchen.... Falls Ihr den ESP32 schon mal für andere WLAN-Projekte genutzt habt, findet Ihr ggf. auch die MAC-Adresse bereits in Eurem WLAN-Netzwerk (z.B. Fritz-Box-Einstellungen). Die Nutzung von "ESP-Now" ist z.B. in "Wolles-Elektronikkiste" oder bei "RandomNerdTutorials" sehr ausführlich und mit vielen Hintergrundinformationen beschrieben...

Es ist sicher auch möglich, den ESP2 als GPS-Datenempänger und "Rechenknecht" zu verwenden (und somit einen ESP einzusparen), da ich aber die Daten dann noch an den RasPi weiterleiten will - habe ich mich vorerst für das 3x ESP32-Modell entschieden.
ESP1 - GPS-Empfänger
Der ESP1 empfängt die Daten vom GPS-Modul und decodiert diese mittels der TinyGPS-Bibliothek. Da dieser ESP den Festpunkt darstellen soll, ermittelt er am Anfang eine "feste Koordinate" und im weiteren Verlauf dann immer die "Drift" auf der Latitude (x-Achse: Ost-West) und Longitude (y-Achse: Nord-Süd).
Diese Informationen sendet er alle 1 Sekunde an den ESP3 (Empfänger).....
(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)
[code]
/*
* Bastel-Version mit GY-GPS6MV2 Modul Stand 22.08.2024
* Zugriff über HardwareSerial RX/TX = GPIO 16/17....
* Baudrate 9600
*
* GPS-Parser von TinyGPS...
*
* sendet die Daten über ESP_NOW an den RECIEVER-ESP
*
* ALLE lokalen Meldungen/Fehlermeldungen über Serial sind deaktiviert,
* da der Sender ohnehin alleinstehend arbeitet....
*
* Dieses Programm empfängt die GPS-Daten, ermittelt einen NULLPUNKT
* als Bezug und die Drift-Abstände bezogen auf diesen Nullpunkt...
*
*/
#include <TinyGPSPlus.h>
#include "HardwareSerial.h"
#include <esp_now.h>
#include <WiFi.h>
TinyGPSPlus gps;
HardwareSerial SerialGPS(1);
// **************************
// Name des Senders...
char ESP_Name[] = "ESP_1";
// **************************
// die ESP_Now_Einstellungen als SENDER
// Empfänger - MAC Addresse einstellen...
uint8_t broadcastAddress[] = {0xA0, 0xA3, 0xB3, 0x2B, 0xEB, 0xB8};
// ESP-NOW - Sende - Datenblock Struktur
// MUSS BEIM EMPFÄNGER ANALOG DEFINIERT WERDEN !!!
typedef struct struct_message {
char a[32]; // Identifikation und Meldungen
float b; // Latitude
float delta_b; // Korrekturwert zum Vorwert
float c; // Longitude
float delta_c; // Korrekturwert zum Vorwert
float d; // Höhe über NN
int e; // Anzahl Satelliten
int f; // Sendezeit Stunden
int g; // Sendezeit Minuten
int h; // Sendezeit Sekunden
} struct_message;
// Struktur zum Zeiger myData zuweisen...
struct_message myData;
// ????....
esp_now_peer_info_t peerInfo;
// eigene Korrekturwerte LAT/LON ( Annahme ESP_1 ist fest )
// float: Anzahl Stellen definiert Auflösung...
float b0=0.00000000;
float c0=0.00000000;
bool gesetzt=false;
// 1x durchlaufend bei Start...
void setup(){
// Serial.begin(115200); // verbindung zum seriellen Monitor am PC starten
SerialGPS.begin(9600, SERIAL_8N1, 17, 16); // GPS starten
delay(5000); // 5 sek warten nach Neustart, damit GPS läuft
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
//Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Transmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
//Serial.println("Failed to add peer");
return;
}
} // end void setup...
// immer wieder durchlaufend
void loop(){
// zuerst Sendewerte zurücksetzen/definieren...
// damit sie überhaupt einen Wert haben...
strcpy(myData.a, ESP_Name);
// strcat(myData.a,": kein Empfang..."); // char-text summieren...
myData.b = 0;
myData.delta_b = 0;
myData.c = 0;
myData.delta_c = 0;
myData.d = 0;
myData.e = 0;
myData.f = 0;
myData.g = 0;
myData.h = 0;
// wenn GPS-Empfang vorhanden...
while (SerialGPS.available() >0) {
gps.encode(SerialGPS.read());
// strcpy(myData.a, ESP_Name);
// strcat(myData.a,": Empfang...");
myData.b= gps.location.lat();
myData.c=gps.location.lng();
myData.d=gps.altitude.meters();
myData.e=gps.satellites.value();
myData.f=gps.time.hour();
myData.g=gps.time.minute();
myData.h=gps.time.second();
// Korrekturwert für die Abweichung (Drift) des ESP1_Senders
// wenn er zum ersten Mal 4 Satelliten hat, dann sind alle Werte
// bereits etabliert...
if (myData.e > 3) {
if (gesetzt==false){ // ERSTWERT als NULLPOSITION FESTLEGEN
b0=myData.b;
c0=myData.c;
gesetzt = true;
}
// aktuelle Drift zur NULLPOSITION - ist zuerst natürlich NULL...
myData.delta_b = myData.b - b0; // Ermittlung Driftwert
myData.delta_c = myData.c - c0; // Ermittlung Driftwert
} // Ende myData.e > 3...
} // end while
/*
if (millis() > 5000 && gps.charsProcessed() < 10){
strcpy(myData.a, ESP_Name);
strcat(myData.a,": No GPS detected...");
//Serial.println(F("No GPS detected: check wiring."));
while(true);
}// millis
*/
// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
/*
if (result == ESP_OK) {
//Serial.println("Sent with success");
}
else {
//Serial.println("Error sending the data");
}
*/
// 1 sekunde warten
delay(1000);
} // end void loop
// VOID-Funktion callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
//Serial.print("\r\nLast Packet Send Status:\t");
//Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
[/code]
Ist mir zu kompliziert..... =>.... zurück zur Startseite
ESP2 - GPS-Empfänger
Der ESP2 empfängt ebenfalls die Daten vom GPS-Modul und decodiert diese mittels der TinyGPS-Bibliothek. Da dieser ESP aber der "mobile ESP" ist, sendet er einfach die ermittelten Daten unverändert an den ESP3 (Empfänger).....
(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)
[code]
/*
* Bastel-Version mit GY-GPS6MV2 Modul Stand 22.08.2024
* Zugriff über HardwareSerial RX/TX = GPIO 16/17....
* Baudrate 9600
*
* GPS-Parser von TinyGPS...
*
* sendet die Daten über ESP_NOW an den RECIEVER-ESP
*
* ALLE lokalen Meldungen/Fehlermeldungen über Serial sind deaktiviert,
* da der Sender ohnehin alleinstehend arbeitet....
*
* Dieses Programm empfängt lediglich die GPS-Daten....
*
*/
#include <TinyGPSPlus.h>
#include "HardwareSerial.h"
#include <esp_now.h>
#include <WiFi.h>
TinyGPSPlus gps;
HardwareSerial SerialGPS(1);
// **************************
// Name des Senders...
char ESP_Name[] = "ESP_2";
// **************************
// die ESP_Now_Einstellungen als SENDER
// Empfänger - MAC Addresse einstellen...
uint8_t broadcastAddress[] = {0xA0, 0xA3, 0xB3, 0x2B, 0xEB, 0xB8};
// ESP-NOW - Sende - Datenblock Struktur
// MUSS BEIM EMPFÄNGER ANALOG DEFINIERT WERDEN !!!
typedef struct struct_message {
char a[32]; // Identifikation und Meldungen
float b; // Latitude
float delta_b; // Korrekturwert zum Vorwert (hier NULL)
float c; // Longitude
float delta_c; // Korrekturwert zum Vorwert (hier NULL)
float d; // Höhe über NN
int e; // Anzahl Satelliten
int f; // Sendezeit Stunden
int g; // Sendezeit Minuten
int h; // Sendezeit Sekunden
} struct_message;
// Struktur zum Zeiger myData zuweisen...
struct_message myData;
// ????....
esp_now_peer_info_t peerInfo;
// nur 1x durchlaufend bei Start...
void setup(){
//Serial.begin(115200); // verbindung zum seriellen Monitor am PC starten
SerialGPS.begin(9600, SERIAL_8N1, 17, 16); // GPS starten
delay(5000); // 5 sek warten nach Neustart, damit GPS läuft
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
//Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Transmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
//Serial.println("Failed to add peer");
return;
}
// Korrekturwerte Drift auf NULL setzen (für ESP2)
// wir müssen sie ja senden, da in structure definiert....
myData.delta_b=0.00000000;;
myData.delta_c=0.00000000;;
} // end setup...
// immer wieder durchlaufend...
void loop(){
// zuerst Sendewerte zurücksetzen/definieren...
// damit sie überhaupt einen Wert haben...
strcpy(myData.a, ESP_Name);
// strcat(myData.a,": kein Empfang...");
myData.b = 0;
myData.c = 0;
myData.d = 0;
myData.e = 0;
myData.f = 0;
myData.g = 0;
myData.h = 0;
while (SerialGPS.available() >0) {
gps.encode(SerialGPS.read());
strcpy(myData.a, ESP_Name);
strcat(myData.a,": Empfang...");
myData.b= gps.location.lat();
myData.c=gps.location.lng();
myData.d=gps.altitude.meters();
myData.e=gps.satellites.value();
myData.f=gps.time.hour();
myData.g=gps.time.minute();
myData.h=gps.time.second();
}
/*
if (millis() > 5000 && gps.charsProcessed() < 10){
strcpy(myData.a, ESP_Name);
strcat(myData.a,": No GPS detected...");
//Serial.println(F("No GPS detected: check wiring."));
while(true);
}// millis
*/
// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
/*
if (result == ESP_OK) {
//Serial.println("Sent with success");
}
else {
//Serial.println("Error sending the data");
}
*/
// 1 sek warten
delay(1000);
} // end loop
// VOID-Funktion callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
//Serial.print("\r\nLast Packet Send Status:\t");
//Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
[/code]
Ist mir zu kompliziert..... =>.... zurück zur Startseite
ESP3 - zentrales Auswertemodul
Der ESP3 empfängt die beiden Datenpakete vom ESP1/ESP2 und ermittelt aus den Daten den Abstand beider GPS-Empfänger voneinander auf der Latitude (x-Achse: Ost-West) und Longitude (y-Achse: Nord-Süd).
Dabei korrigiert er die Werte beider ESP mit den "Driften" des ESP1 (Festpunkt) und ermittelt dann die Abstände.
Um zu verhindern, das "alte Daten" miteinander verrechnet werden, werden die vom GPS-Satelliten mitgesendeten Zeitstempel (hier reichen eigentlich die Sekundenwerte, aus technischen Gründen muss aber mit Zeitformaten gerechnet werden s.u.) verglichen und nur Werte innerhalb eines gewissen Zeitraums (im Listing 10 Sekunden, ich hab es später auf 3 Sekunden verkürzt..) miteinander in Beziehung gesetzt.
Hinweis: Die Bluetooth-Bibliothek belegt sehr viel Speicher auf dem ESP32, daher sind hier die bisherigen Grundeinstellungen "ESP mit SPIFFS etc." nicht möglich, da sonst das Hochladen mit Verweis auf fehlenden Speicher abbricht....Aktuell zumindest nutze ich sie aber noch nicht, da ich mir vorerst die Daten auf dem angeschlossenem PC mittels Seriellem Monitor/-Plotter ansehe.
(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)
[code]
/* Stand 22.08.2024...
*
* Einstellung esp32 HughApp 3MB no OTA ( wegen Bluetooth.h Bibliothek )
*
* kann mehrere Sender automatisch empfangen... Senderkennung ist in CHAR -
* Variable myData.a enthalten ( ESP_1 / ESP_2 )
*
* Original-Version zu ESP-NOW von Rui Santos auf
* https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
*
* Original-Version zu Bluetooth von.....?
*
*
*
*/
//Bibliotheken
#include <esp_now.h>
#include <WiFi.h>
#include <TinyGPSPlus.h>
#include <ctime>
#include "BluetoothSerial.h"
// TinyGPSPlus hier nur als "Rechenknecht"...
TinyGPSPlus gps;
// ESP-NOW - Sende - Datenblock Struktur
// MUSS BEIM SENDER ANALOG DEFINIERT WERDEN !!!
typedef struct struct_message {
char a[32];
float b; // Latitude-Wert
float delta_b; // Korrekturwert Drift von ESP_1
float c; // Longitude-Wert
float delta_c; // Korrekturwert Drift von ESP_1
float d; // Höhe über NN
int e; // Anzahl Satelliten
int f; // Sendezeit Stunden
int g; // Sendezeit Minuten
int h; // Sendezeit Sekunden
} struct_message;
// ESP-NOW - Struktur zum Zeiger myData zuweisen...
struct_message myData;
// die Bluetooth-Einstellungen
BluetoothSerial SerialBT;
// eigene Initialisierung für die Positions-Auswertungen...
// float !! Anzahl Nullen definiert die "Auflösung"
// des Zahlenwertes...
float b0 = 0.00000000; // LAT alt
float c0 = 0.00000000; // LON alt
float b1 = 0.00000000; // LAT neu
float c1 = 0.00000000; // LON neu
int e0 = 0; // Anz Satelliten alt
int e1 = 0; // Anz Satelliten neu
time_t ESP1_Zeit; // fürZeitberechnung
time_t ESP2_Zeit;
struct tm datetime; // Array für Zeitroutinen
// wird nur 1x beim Start durchlaufen...
void setup() {
// Initialize Serial Monitor - am PC
Serial.begin(115200);
// Bluetooth starten
SerialBT.begin("ESP32_GPS"); // Bluetooth starten
// ESP-NOW - Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// ESP-NOW - Initialisieren ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
// für die Auswertung des Alters der GPS-Informationen werden jeweils die
// Stunden/Minuten/Sekunden des Datensatzes als Var f/g/h von den Sender-ESP
// übertragen, für die Berechnung muss das Zeitformat genutzt werden, da 52-5 sek
// grösser als das Intervall wäre (Sekundenstand) wir wandeln also die Daten
// in ein Zeitformat um und nutzen die automatischen Zeitroutinen...
// wir setzen pauschal die "globalen" Zeitwerte des Arrays "datetime" für
// für einen beliebigen Tag im Sommer 2024...
datetime.tm_year = 2024 - 1900; // Number of years since 1900
datetime.tm_mon = 12 - 6; // Number of months since January
datetime.tm_mday = 15;
datetime.tm_hour = 00; // später die Stundenwerte
datetime.tm_min = 00; // später die Minutenwerte
datetime.tm_sec = 00; // später die Sekundenwerte
// Daylight Savings must be specified
// -1 uses the computer's timezone setting
datetime.tm_isdst = -1;
} // ende Setup
// Schleife wird immer wieder durchlaufen...
void loop() {
// keine Einträge, die relevante Funktion s.u. wird vom System aufgerufen
} // ende loop
// Funktion wird vom System aufgerufen, wenn Daten kommen...
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
/*
// erst Mal nur Ausgabe empfangene Daten auf dem Seriellen Monitor
Serial.print("Bytes empfangen: ");
Serial.println(len);
Serial.print("Sender ");
Serial.println(myData.a);
Serial.print("Latitude: ");
Serial.println(myData.b,8);
Serial.print("Longitude: ");
Serial.println(myData.c,8);
Serial.print("Höhe über NN: ");
Serial.println(myData.d,2);
Serial.print("Anzahl Satelliten: ");
Serial.println(myData.e);
Serial.print("Sendezeit Datensatz ");
Serial.print(myData.f);
Serial.print(":");
Serial.print(myData.g);
Serial.print(":");
Serial.println(myData.h);
Serial.println();
*/
/*
* mein Auswertemodell ( für DEUTSCHLAND !!)
* unsere (positive) x-Achse geht nach OSTEN und die y-Achse geht nach NORDEN (+ x/y)
* da wir östlich des NullMeridians (Greenwich) sind, ist eine höherer LAT-Wert
* auf der x-Achse positiv...
* da wir nördlich des Äquators sind, ist ein höherer LON-Wert auf der y-Achse
* positiv...
*
* wir definieren ESP1 als NULLPUNKT und ermitteln die Entfernung x/y von ESP2
* auf x-/y-Achse...
*
* die aktuelle Position des ESP1 wird mit den Korrekturwerten delta_b/delta_c
* verrechnet, um die Drift auszugleichen (ESP1-Wert bleibt also immer gleich)..
*
* die aktuelle Position des ESP2 wird mit den Korrekturwerten delta_b/delta_c
* VOM ESP1 verrechnet, um die Drift auch am ESP2 auszugleichen und somit genaue
* Positionswerte bezogen auf den ESP1 zu erhalten...
*/
//aktuelle neue empfangene Daten LAT/LON/SatAnz etc.
b1 = myData.b - myData.delta_b; // ESP1 ist nach "Osten" gedriftet hier wieder abziehen
c1 = myData.c - myData.delta_c; // entsprechend...
e1 = myData.e; // Satellitenanzahl
// ESP1-Daten erst mal einfach pauschal als Vergleichsdaten übernehmen...
// der ESP1 sendet ohnehin erst, wenn er 4 Satelliten hat...
if (strstr(myData.a,"ESP_1")){
b0 = b1; // Drift ist in b1 bereits abgezogen => ESP_1 bleibt immer gleich...
c0 = c1;
// b0=52.07373047; // zwischenzeitlich mal testweise als Festwert für ESP1
// c0=11.84110451;
e0 = e1; // Anz Satelliten
// Zeitwerte im Array datetime übernehmen und ESP1-Zeit setzen
datetime.tm_hour = myData.f;
datetime.tm_min = myData.g;
datetime.tm_sec = myData.h;
ESP1_Zeit = mktime(&datetime);
} // Ende ESP1
// NUR AUSWERTEN WENN MIND 4 Satelliten bei BEIDEN ESP vorhanden sind...
// 3 für Triangulierung und 1 für Zeitberechnung im GPS-Modul
// siehe Erklärungen bei z.B. Wikipedia...
// und dann sind auch die Werte beider ESP mittlerweile stabil...
// und wir riskieren keinen Abstutz etc. infolge fehlender Daten
if ( ( e0 > 3 ) && ( e1 > 3 )) {
// HIER NUR AUSWERTEN WENN Daten vom ESP2 (mobiles Gerät)
if (strstr(myData.a,"ESP_2")){
// Zeitwerte im Array datetime übernehmen und ESP2-Zeit setzen
datetime.tm_hour = myData.f;
datetime.tm_min = myData.g;
datetime.tm_sec = myData.h;
ESP2_Zeit = mktime(&datetime);
// Zeitdifferenz ESP1 / ESP2 ausrechnen und als Kriterium verwenden
// NUR AUSWERTEN wenn DATEN nicht älter als Kriterium...
// difftime ergibt einen Integer Sekundenwert...
if ( (difftime(ESP1_Zeit,ESP2_Zeit)) < 10){
// Entfernung auf der x-Achse (LON-Werte sind gleich)
float distanceLAT = 0.00;
distanceLAT = (float)TinyGPSPlus::distanceBetween(
b0,
c0,
b1,
c0);// in m sonst => / 1000;
// wenn der alte wert > neuer wert ist...westlich von...
if ( b0 > b1 ){ distanceLAT = -1 * distanceLAT;}
// Entfernung auf der y-Achse (LAT-Werte sind gleich)
float distanceLON = 0.00;
distanceLON = (float)TinyGPSPlus::distanceBetween(
b0,
c0,
b0,
c1);// in m sonst => / 1000;
// wenn der alte wert > neuer wert ist...südlich von...
if ( c0 > c1 ){ distanceLON = -1 * distanceLON;}
// AUSGABE...auf seriellem Monitor am PC
//Serial.print("LAT: ");
Serial.println(distanceLAT,2);
//Serial.print("LON: ");
//Serial.println(distanceLON,2);
Serial.println();
/*
// SPÄTER SENDEN.... WIRD NOCH ANGEPASST -
// zukünftig nur noch x-/y-Wert in Meter relevant...
//if (!strlen(myData.a)> 6){
SerialBT.print(myData.a);
SerialBT.print(" , ");
SerialBT.print(myData.b, 8);
SerialBT.print(" , ");
SerialBT.print(myData.c, 8);
SerialBT.print(" , ");
SerialBT.print(myData.d, 2);
SerialBT.print(" , ");
SerialBT.print(myData.e);
SerialBT.print(" , ");
SerialBT.print(myData.f);
SerialBT.print(" , ");
SerialBT.print(myData.g);
SerialBT.print(" , ");
SerialBT.print(myData.h);
SerialBT.println(" // "); // als Zeichen Ende der Zeichenkette für den RasPi
}
*/
} // nur wenn difftime < Kriterium
} // nur wenn vom ESP2
} // nur wenn beide ESP > 3 Satelliten
} // end callback
[/code]
Ist mir zu kompliziert..... =>.... zurück zur Startseite
Resultate...
Tja, meine Theorie besagte ja, das 2 GPS-Module (in Nähe zueinander) auch die gleiche "Drift" haben sollten - so war eigentlich die Annahme...
Hier aber mal die Auswertung der Entfernungen der beiden Module auf der x-Achse (Latitude) - beide Module liegen dabei etwa 1.50m auseinander (im Gebäudeinneren unter Holzdachstuhl)....
Hinweis: die x-Skala ist immer in Sekunden ab Aufzeichnungs-Start....

Wie wir sehen, ändert sich der ermittelte Abstand mit der Zeit wesentlich, obwohl wir die beiden GPS-Module NICHT bewegt haben und die Daten beider ESP mit der "Drift" des ESP-GPS1 korrigieren.
Ist mir zu kompliziert..... =>.... zurück zur Startseite
Fehlersuche und -minimierung
Um den Einfluss der beschränkten "Sicht auf die Satelliten" zu verringern habe ich die Module im Aussenbereich neu angeordnet und zwecks Minimierung eines möglichen Einflusses des WIFI (ESP-Now) auch an etwas längere Kabel angeschlossen.

In einem Forum habe ich dann einen Versuchsaufbau mit einer "Blechschüssel" zur Verringerung des Einflusses von an Gebäuden und Bäumen etc. "gespiegelten" GPS-Signalen gefunden - dies habe ich auch mal umgesetzt.
Mangels "Blechschüssel" habe ich einen alten Lampenschirm mit Alufolie eingekleidet und den ESP32 ausserhalb der Schüssel angeordnet - nur das GPS-Empfängermodul befindet sich innerhalb der "Abschirmung"...
Der GPS-Empfänger befindet sich dabei etwa 50cm über dem Boden - das wäre auch die realistische Höhe bei einer späteren Anwendung. Eine deutlich höhere Position könnte sich aber durchaus günstig auswirken.
Durch die "Schüssel" sollte sich auch der mögliche Einfluss des Datentransfers über WiFi (ESP-Now) verringern, da diese Strahlung ja auch etwas zum GPS-Modul abgeschirmt wird.

Dann habe ich mein Script im ESP3 (Empfänger WiFi) so abgeändert, das ich die "Drift" des ESP-GPS2 auf einen "virtuellen regionalen festen Punkt" bezogen angezeigt bekomme....( bisher war der ESP-GPS1 ja auch als "fester Punkt" immer mit seiner eigenen Drift korrigiert worden).

Anscheinend "beruhigt" sich unsere "Drift" im Verhältniss zu den bisherigen Werten, ist aber immer noch im Bereich von +/- 1.5m um den Nullpunkt...
Aber leider laufen diese Werte nach ca. einer halben Stunde Laufzeit dann doch wieder "aus dem Ruder"....

Diese Lösung bringt uns also auch nicht die erwünschten Ergebnisse...
Ist mir zu kompliziert..... =>.... zurück zur Startseite
ein dritter Versuch...
Mittlerweile sind die beiden Neo-8-GPS-Module aus FernOst angekommen und ich habe den vorhergehenden Versuchsaufbau mit diesen wiederholt. Anschluss und Schaltung sind analog der Neo-6-Module s.o..
Aber leider ergeben sich - abgesehen von einem schnelleren Start der Module und mehr verfügbaren Satelliten - leider keine Verbesserungen.
Also habe ich auf beiden ESP ( 1 und 2 ) die Software vom ESP1 (Festpunkt mit "Driftwert"ermittlung zur vorhergehenden Position) aufgespielt und mir dann die "Driftwerte" beider Module ( an den ESP3 übermittelte Variablen delta_b ) anzeigen lassen ( Hinweis: da die Differenz des LAT-Wertes z.B. xx.12345678 ja immer in der Grössenordnung 00.0000xxx als Zahlenwert betrachtet liegt, habe ich sie mit 100.000 multipliziert, um Werte im Bereich 1-10 zu erzielen )...
Dies sieht dann so aus....

Abgesehen von den "Sprüngen" - welche man notfalls per Software glätten kann - zeigt sich eindeutig, das beide ESP völlig unterschiedlich "driften"....
FAZIT bisher...
Auf diese Weise scheine ich nicht zu einem brauchbaren Ergebnis zu kommen - dazu scheint die "Drift" der Einzelempfänger zu sehr von geräteinternen Unterschieden ( z.B. dem eingebauten Quarz zur Zeitbestimmung ) abhängig zu sein.
Nicht umsonst kosten gute GPS-Empfänger auch "einen guten Schein"....
Aber eventuell fällt mir noch etwas ein - oder Euch......
Probiert es doch einfach aus...