Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
![]() |
| |||||
Hand tools and fabrication machines | ||||||
![]() |
| |||||
Hi. I built a small and basic GPS tracker. I used an ESP32-S3-N16R8 and an NEO-6M.
NEO-6M takes the GPS information in NMEA, in ESP32 TinyGPS++ library turns it into latitude and longitude, that information sent in interval of 2 seconds to Firebase Realtime Database via WiFi on ESP32, and a pure HTML code shows up the values in a map.
#include <WiFi.h>
#include <FirebaseESP32.h>
#include <TinyGPS++.h>
#define WIFI_SSID ""
#define WIFI_PASSWORD ""
#define FIREBASE_HOST ""
#define FIREBASE_AUTH ""
#define RXD2 18
#define TXD2 17
TinyGPSPlus gps;
FirebaseData firebaseData;
FirebaseAuth auth;
FirebaseConfig config;
void setup() {
Serial.begin(115200);
Serial1.begin(9600, SERIAL_8N1, RXD2, TXD2);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected!");
config.host = FIREBASE_HOST;
config.signer.tokens.legacy_token = FIREBASE_AUTH;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
Serial.println("Waiting for the GPS information");
}
void loop() {
while (Serial1.available() > 0) {
if (gps.encode(Serial1.read())) {
if (gps.location.isValid() && gps.location.isUpdated()) {
FirebaseJson json;
json.set("lat", gps.location.lat());
json.set("lng", gps.location.lng());
json.set("speed", gps.speed.kmph());
json.set("satellite", gps.satellites.value());
if (Firebase.pushJSON(firebaseData, "/travel", json)) {
Serial.print("Location sent: ");
Serial.print(gps.location.lat(), 6);
Serial.print(", ");
Serial.println(gps.location.lng(), 6);
} else {
Serial.print("Firebase Error: ");
Serial.println(firebaseData.errorReason());
}
}
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ESP32-S3 Live GPS Tracker</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<style>
body { margin: 0; padding: 0; }
#map { height: 100vh; width: 100%; }
.gps-marker {
width: 15px;
height: 15px;
background-color: #ff0000;
border: 2px solid white;
border-radius: 50%;
box-shadow: 0 0 10px rgba(255, 0, 0, 0.8);
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { transform: scale(0.9); box-shadow: 0 0 0 0 rgba(255, 0, 0, 0.7); }
70% { transform: scale(1.1); box-shadow: 0 0 0 10px rgba(255, 0, 0, 0); }
100% { transform: scale(0.9); box-shadow: 0 0 0 0 rgba(255, 0, 0, 0); }
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-database.js"></script>
<script>
const firebaseConfig = {
databaseURL: ""
};
firebase.initializeApp(firebaseConfig);
const db = firebase.database().ref('/travel');
const map = L.map('map').setView([;,;], 15);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap'
}).addTo(map);
let path = L.polyline([], {color: 'red', weight: 4, opacity: 0.6}).addTo(map);
let currentMarker = null;
db.limitToLast(50).on('child_added', (snapshot) => {
const data = snapshot.val();
const pos = [data.lat, data.lng];
path.addLatLng(pos);
if (currentMarker) map.removeLayer(currentMarker);
const customIcon = L.divIcon({
className: 'gps-marker',
iconSize: [15, 15]
});
currentMarker = L.marker(pos, {icon: customIcon}).addTo(map);
map.panTo(pos);
});
</script>
</body>
</html>





Comments