#include <TinyGPSPlus.h>
#include <WiFi.h>
#include <time.h>
#define GPS_SERIAL Serial2
const char* ssid = "Wokwi-GUEST";
const char* password = "";
TinyGPSPlus gps;
char time_buf[32];
void setup() {
Serial.begin(9600);
Serial2.begin(9600, SERIAL_8N1, 16, 17);
// Łączenie z Wi-Fi
Serial.println("Łączenie z Wi-Fi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("\nPołączono z Wi-Fi");
// Konfiguracja NTP (UTC+2)
configTime(7200, 0, "pool.ntp.org");
time_t now = time(NULL);
while (now < 100000) {
delay(100);
now = time(NULL);
}
// Nagłówki kolumn jak w TinyGPSPlus FullExample
Serial.println(F("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum"));
Serial.println(F(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail"));
Serial.println(F("-------------------------------------------------------------------------------------------------------------------------------------"));
}
void loop() {
static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
// Pobranie aktualnego czasu NTP do wysyłki na UART (chip parsuje YYYY/MM/DD HH:MM:SS\n)
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
strftime(time_buf, sizeof(time_buf), "%Y/%m/%d %H:%M:%S\n", tm_info);
// Wysyłamy aktualny czas przez UART do chipa
Serial2.print(time_buf);
// Przetwarzanie danych z GPS
while (GPS_SERIAL.available())
gps.encode(GPS_SERIAL.read());
// Liczba satelitów
printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
// HDOP
printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
// Szerokość geograficzna
printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
// Długość geograficzna
printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
// Wiek fixu
printInt(gps.location.age(), gps.location.isValid(), 5);
// Kolumna Date (MM/DD/YYYY⎵)
char dateCol[16]; strftime(dateCol, sizeof(dateCol), "%m/%d/%Y ", tm_info);
Serial.print(dateCol);
// Kolumna Time (HH:MM:SS⎵)
char timeCol[16]; strftime(timeCol, sizeof(timeCol), "%H:%M:%S ", tm_info);
Serial.print(timeCol);
// Kolumna Date Age (zastępujemy age=0)
printInt(0, true, 5);
// Wysokość
printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
// Kurs
printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
// Prędkość
printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
// Kierunek kardynalny
printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);
// Odległość do Londynu [km]
unsigned long distanceKmToLondon = (unsigned long)TinyGPSPlus::distanceBetween(gps.location.lat(), gps.location.lng(), LONDON_LAT, LONDON_LON) / 1000;
printInt(distanceKmToLondon, gps.location.isValid(), 9);
// Kurs do Londynu [deg]
double courseToLondon = TinyGPSPlus::courseTo(gps.location.lat(), gps.location.lng(), LONDON_LAT, LONDON_LON);
printFloat(courseToLondon, gps.location.isValid(), 7, 2);
// Kierunek do Londynu
const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);
printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);
// Statystyki parsera
printInt(gps.charsProcessed(), true, 6);
printInt(gps.sentencesWithFix(), true, 10);
printInt(gps.failedChecksum(), true, 9);
Serial.println();
// Utrzymuje karmienie parsera w trakcie opóźnienia
smartDelay(1000);
// Komunikat diagnostyczny gdy brak danych
if (millis() > 5000 && gps.charsProcessed() < 10)
Serial.println(F("No GPS data received: check wiring"));
}
// Custom delay dla TinyGPSPlus (karmienie parsera podczas czekania)
static void smartDelay(unsigned long ms) {
unsigned long start = millis();
do {
while (GPS_SERIAL.available())
gps.encode(GPS_SERIAL.read());
} while (millis() - start < ms);
}
// Wydruk liczby zmiennoprzecinkowej w kolumnie stałej szerokości
static void printFloat(float val, bool valid, int len, int prec) {
if (!valid) {
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);
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i = flen; i < len; ++i)
Serial.print(' ');
}
smartDelay(0);
}
// Wydruk liczby całkowitej w kolumnie stałej szerokości
static void printInt(unsigned long val, bool valid, int len) {
char sz[32] = "*****************";
if (valid) sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i = (int)strlen(sz); i < len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len - 1] = ' ';
Serial.print(sz);
smartDelay(0);
}
// Wydruk łańcucha w kolumnie stałej szerokości
static void printStr(const char *str, int len) {
int slen = (int)strlen(str);
for (int i = 0; i < len; ++i)
Serial.print(i < slen ? str[i] : ' ');
smartDelay(0);
}