Точные GPS-часы на Arduino: доступная точность и надёжность
Компоненты и материалы
| Arduino UNO | × | 1 |
| LCD-дисплей (20×4 с I2C-адаптером, либо 16×2) | × | 1 |
| Breadboard | × | 1 |
| Перемыжки | × | 1 |
| GPS-приёмник (GY-GPS6MV2 с u-blox NEO-6M) | × | 1 |
Программное обеспечение
- Arduino IDE
Ранее использовал RTC-модули или NTP. Здесь — время из NMEA-строк GPS-спутников.
GPS-приёмники сегодня очень дешёвы (GY-GPS6MV2).
Тестирование приёмника
- На Windows (опционально): установите u-center от u-blox. Через FTDI-адаптер подключите приёмник к COM-порту. Через ~1 мин получите фиксацию (красный светодиод мигает). В меню View → F8 Text Console — NMEA-строки.
- Онлайн-декодер: https://rl.se/gprmc — вставьте строку, получите расшифровку.
Убедившись в работоспособности (нужен обзор неба), извлечём нужные данные.
Схема подключения
- Arduino A4 (SDA) → LCD SDA
- Arduino A5 (SCL) → LCD SCL
- GPS VCC → 5V, GND → GND
- GPS TX → Arduino D8, GPS RX → Arduino D7 (SoftwareSerial)
GPS-толерантен к 3.3/5В.
Библиотеки
Adafruit_GPS(через Library Manager)SoftwareSerial(встроена)Wire+LiquidCrystal_I2Cдля дисплея
Часы: время, дата, скорость ветра, высота
NMEA даёт время в UTC. Перевод в локальную зону — наша задача. Для Европы/Берлина: int timezone = +1;
int hour = GPS.hour + timezone;
if (hour < 10) lcd.print('0');
lcd.print(hour); lcd.print(':');
// аналогично минуты, секунды
Скорость в узлах → км/ч: float speed = GPS.speed * 1.852;
Оценка по шкале Бофорта (Википедия):
if (speed <= 1) lcd.print(" Windstille");
else if (speed <= 9) lcd.print(" leiser Zug");
else if (speed <= 46) lcd.print(" Brise");
else if (speed <= 56) lcd.print(" starker Wind");
else if (speed <= 74) lcd.print(" stuerm. Wind");
else if (speed <= 83) lcd.print(" Sturm");
else if (speed <= 102) lcd.print(" schwerer Sturm");
else lcd.print(" Orkan");
Высота: GPS.altitude (метры).
Результат на дисплее (20×4):
- Строка 1: время HH:MM:SS
- Строка 2: дата DD.MM.YY
- Строка 3: скорость км/ч + вербальная оценка ветра
- Строка 4: высота
Обновление каждые 2 секунды. Можно убрать секунды и высоту для 16×2 дисплея.
В Европе также есть DCF77 (радиосигнал), но он дороже и капризнее.
Код (GPS_SoftwareSerial_Parsing_ilo)
// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver
// Modified 01.02.2020 - Ingo Lohs
// GPRMC & GPGGA decoder: https://rl.se/gprmc
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4); // адрес 0x27 или 0x3F
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(8, 7); // RX=8, TX=7
Adafruit_GPS GPS(&mySerial);
#define GPSECHO true
int timezone = +1; // Europe/Berlin (UTC+0100)
void setup() {
lcd.init(); lcd.backlight();
Serial.begin(115200);
delay(5000);
Serial.println("Adafruit GPS library basic test!");
GPS.begin(9600); // UBLOX 6M default
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // RMC + GGA (fix + altitude)
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update
GPS.sendCommand(PGCMD_ANTENNA); // antenna status
delay(1000);
mySerial.println(PMTK_Q_RELEASE); // firmware version
}
uint32_t timer = millis();
void loop() {
char c = GPS.read();
if (c && GPSECHO) Serial.write(c);
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA())) return;
}
if (timer > millis()) timer = millis();
if (millis() - timer > 2000) {
timer = millis();
// Serial output
Serial.print("\nTime: ");
if (GPS.hour < 10) Serial.print('0');
Serial.print(GPS.hour, DEC); Serial.print(':');
if (GPS.minute < 10) Serial.print('0');
Serial.print(GPS.minute, DEC); Serial.print(':');
if (GPS.seconds < 10) Serial.print('0');
Serial.print(GPS.seconds, DEC); Serial.print('.');
if (GPS.milliseconds < 10) Serial.print("00");
else if (GPS.milliseconds < 100) Serial.print("0");
Serial.println(GPS.milliseconds);
Serial.print("Date: ");
Serial.print(GPS.day, DEC); Serial.print('/');
Serial.print(GPS.month, DEC); Serial.print("/20");
Serial.println(GPS.year, DEC);
Serial.print("Fix: "); Serial.print((int)GPS.fix);
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
// LCD output
lcd.setCursor(5, 0);
int hour = GPS.hour + timezone;
if (hour < 10) lcd.print('0');
lcd.print(hour, DEC); lcd.print(':');
if (GPS.minute < 10) lcd.print('0');
lcd.print(GPS.minute, DEC); lcd.print(':');
if (GPS.seconds < 10) lcd.print('0');
lcd.print(GPS.seconds, DEC);
lcd.setCursor(5, 1);
if (GPS.day < 10) lcd.print('0');
lcd.print(GPS.day, DEC); lcd.print('.');
if (GPS.month < 10) lcd.print('0');
lcd.print(GPS.month, DEC); lcd.print('.');
lcd.print(GPS.year, DEC);
if (GPS.fix) {
Serial.print("Location: ");
Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
Serial.print(", "); Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
Serial.print("Speed (knots): "); Serial.println(GPS.speed);
Serial.print("Angle: "); Serial.println(GPS.angle);
Serial.print("Altitude: "); Serial.println(GPS.altitude);
Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
lcd.setCursor(0, 2);
float speed = GPS.speed * 1.852; // knots → km/h
lcd.print(speed);
// Wind scale
if (speed <= 1) lcd.print(" Windstille");
else if (speed <= 9) lcd.print(" leiser Zug");
else if (speed <= 46) lcd.print(" Brise");
else if (speed <= 56) lcd.print(" starker Wind");
else if (speed <= 74) lcd.print(" stuerm. Wind");
else if (speed <= 83) lcd.print(" Sturm");
else if (speed <= 102) lcd.print(" schwerer Sturm");
else lcd.print(" Orkan");
lcd.setCursor(0, 3);
lcd.print("Hoehe: "); lcd.print(GPS.altitude);
}
}
}
Приятного изучения возможностей GPS!
Производственный процесс
- DIY бюджетный перчаточный контроллер и пропеллер-машинка — соберите свой Arduino ручной контроллер
- Проект с датчиком DHT11: индикация температуры светодиодами и пьезо-динамиком на Arduino
- GPS-трекер с пространственным анализом на Azure IoT Hub
- Логгер температуры и влажности на Arduino с DHT11 и Ethernet Shield
- Монитор температуры и реальные часы на Arduino Due с TFT-дисплеем 3.2"
- Аналоговые POV-часы на Arduino Nano: персистенция зрения с 17 светодиодами
- Празднуем со светом и звуком: DIY-проект «С днём рождения» на Arduino
- Модуль GPS u-blox LEA-6H 02: Интеграция с Arduino и Python
- Клеточный автомат «Жизнь» Конвея на Arduino Nano с OLED 128x64
- DIY Guitar Speed Pick & Stomp Pedal — моторизированный медиатор на Arduino