11#if defined(ESP32)
22#include < WiFi.h>
33#include < ESP32Servo.h>
4+ #include < TinyGPSPlus.h>
45#elif defined(ESP8266)
56#include < ESP8266WiFi.h>
67#include < Servo.h>
@@ -62,6 +63,26 @@ unsigned long lastStepMs = 0;
6263unsigned long lastWifiAttempt = 0 ;
6364unsigned long lastWsAttempt = 0 ;
6465
66+ #if defined(ESP32)
67+ HardwareSerial SerialGPS (1 );
68+ TinyGPSPlus gps;
69+ constexpr int GPS_RX_PIN = 34 ;
70+ constexpr int GPS_TX_PIN = 12 ;
71+ constexpr uint32_t GPS_BAUD_RATE = 9600 ;
72+ constexpr unsigned long GPS_MAX_AGE_MS = 5000 ;
73+ double gpsLastLat = 0.0 ;
74+ double gpsLastLon = 0.0 ;
75+ double gpsLastAlt = 0.0 ;
76+ double gpsLastSpeedMps = 0.0 ;
77+ double gpsLastHdop = 0.0 ;
78+ uint8_t gpsLastSatellites = 0 ;
79+ unsigned long gpsLastFixMs = 0 ;
80+
81+ void beginGps ();
82+ void pollGps ();
83+ bool gpsHasFix ();
84+ #endif
85+
6586void connectToWifi ();
6687void ensureWebsocket ();
6788void publishRadarSample (int angleDeg, float distanceCm, bool valid);
@@ -86,6 +107,10 @@ void setup() {
86107 waitingForServo = true ;
87108 servoCommandMs = millis ();
88109
110+ #if defined(ESP32)
111+ beginGps ();
112+ #endif
113+
89114 connectToWifi ();
90115
91116 radarSocket.onEvent ([](WebsocketsEvent event, String data) {
@@ -107,6 +132,10 @@ void setup() {
107132}
108133
109134void loop () {
135+ #if defined(ESP32)
136+ pollGps ();
137+ #endif
138+
110139 if (WiFi.status () != WL_CONNECTED) {
111140 ensureWebsocket (); // ensures disconnect handling
112141 connectToWifi ();
@@ -198,6 +227,21 @@ void publishRadarSample(int angleDeg, float distanceCm, bool valid) {
198227 payload += RADAR_SOURCE_ID;
199228 payload += " \" ,\" timestamp_ms\" :" ;
200229 payload += millis ();
230+ #if defined(ESP32)
231+ if (gpsHasFix ()) {
232+ payload += " ,\" gps\" :{" ;
233+ payload += " \" lat\" :" ; payload += String (gpsLastLat, 6 );
234+ payload += " ,\" lon\" :" ; payload += String (gpsLastLon, 6 );
235+ payload += " ,\" alt_m\" :" ; payload += String (gpsLastAlt, 1 );
236+ payload += " ,\" speed_mps\" :" ; payload += String (gpsLastSpeedMps, 2 );
237+ payload += " ,\" hdop\" :" ; payload += String (gpsLastHdop, 1 );
238+ payload += " ,\" satellites\" :" ; payload += gpsLastSatellites;
239+ payload += " ,\" fix_age_ms\" :" ; payload += (millis () - gpsLastFixMs);
240+ payload += " }" ;
241+ } else {
242+ payload += " ,\" gps\" :null" ;
243+ }
244+ #endif
201245 payload += " }" ;
202246
203247 if (!radarSocket.send (payload)) {
@@ -274,3 +318,45 @@ void updateSweep() {
274318 waitingForServo = true ;
275319 }
276320}
321+
322+ #if defined(ESP32)
323+ void beginGps () {
324+ SerialGPS.begin (GPS_BAUD_RATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
325+ Serial.println (" [GPS] Serial initialized for TinyGPS++" );
326+ }
327+
328+ void pollGps () {
329+ bool sentenceCompleted = false ;
330+ while (SerialGPS.available ()) {
331+ sentenceCompleted |= gps.encode (SerialGPS.read ());
332+ }
333+
334+ if (!sentenceCompleted) {
335+ return ;
336+ }
337+
338+ const unsigned long now = millis ();
339+ if (gps.location .isValid ()) {
340+ gpsLastLat = gps.location .lat ();
341+ gpsLastLon = gps.location .lng ();
342+ gpsLastFixMs = now;
343+ }
344+ if (gps.altitude .isValid ()) {
345+ gpsLastAlt = gps.altitude .meters ();
346+ }
347+ if (gps.speed .isValid ()) {
348+ gpsLastSpeedMps = gps.speed .mps ();
349+ }
350+ if (gps.hdop .isValid ()) {
351+ gpsLastHdop = gps.hdop .hdop ();
352+ }
353+ if (gps.satellites .isValid ()) {
354+ gpsLastSatellites = static_cast <uint8_t >(gps.satellites .value ());
355+ }
356+ }
357+
358+ bool gpsHasFix () {
359+ const unsigned long age = gps.location .isValid () ? gps.location .age () : GPS_MAX_AGE_MS + 1 ;
360+ return gps.location .isValid () && age <= GPS_MAX_AGE_MS;
361+ }
362+ #endif
0 commit comments