GPS-модуль NEO-6M и Arduino: подключение, NMEA и TinyGPSPlus
Как использовать GPS-модуль NEO-6M с Arduino: подключение TX/RX, время до первой фиксации, предложения $GPGGA и $GPRMC, код с TinyGPSPlus, OLED на ESP32 и MicroPython на Pico.
GPS-модуль NEO-6M — дешёвый и очень популярный GPS-приёмник, который добавляет в проект на Arduino, ESP32 или Raspberry Pi Pico широту, долготу, скорость, высоту и сверхточное время UTC со спутников. Для работы с Arduino нужны всего четыре провода (VCC, GND, TX, RX): раз в секунду модуль на скорости 9600 бод отправляет текстовые строки — предложения NMEA, а библиотека TinyGPSPlus превращает их в числа, которые можно сразу использовать.
В этом руководстве шаг за шагом разберём, как работает модуль, как подключить его к Arduino Uno, ESP32 и Pico, почему первое определение координат иногда занимает минуты, что означает каждое поле предложений $GPGGA и $GPRMC, как превратить широту и долготу в ссылку на Google Maps и как показать координаты на OLED-дисплее. В конце — таблица с причинами и решениями двух самых частых проблем: «нет данных» и «нет фиксации».

Что такое GPS-модуль NEO-6M и как он работает?
GPS (Global Positioning System, глобальная система позиционирования) — это больше 30 спутников на орбите высотой около 20 200 км. Каждый спутник постоянно передаёт время своих бортовых атомных часов и данные собственной орбиты. NEO-6M измеряет разницу между моментом, когда сигнал покинул спутник, и моментом его прихода и по ней вычисляет расстояние до каждого спутника; увидев хотя бы 4 спутника, он может найти широту, долготу, высоту и ошибку собственных часов. Только с 3 спутниками он вычисляет двумерное (2D) положение без высоты. Сигналы спутников доходят до земли крайне слабыми (около -130 dBm), а бетон, металлические крыши и даже густые кроны деревьев гасят большую их часть. Поэтому золотое правило GPS простое: антенна должна видеть небо.
| Параметр | Значение |
|---|---|
| Чип приёмника | u-blox NEO-6M (навигационное ядро u-blox 6) |
| Каналы и сигнал | 50 каналов, GPS L1 C/A (1575,42 MHz), SBAS: EGNOS, WAAS, MSAS |
| Точность по горизонтали | 2,5 м CEP (2,0 м с SBAS) |
| Точность скорости и курса | 0,1 м/с и 0,5 градуса |
| Время до первой фиксации (TTFF) | Холодный старт 27 с, тёплый 27 с, горячий 1 с |
| Чувствительность | Слежение -161 dBm, холодный старт -147 dBm |
| Частота обновления | 1 Hz по умолчанию, до 5 Hz |
| Интерфейс | UART, по умолчанию 9600 бод 8N1, NMEA 0183 |
| Питание | Плата: 3,3–5 V (со стабилизатором); чип: 2,7–3,6 V |
| Ток | ~47 mA при поиске, ~39 mA при слежении |
| Рабочая температура | От -40 до +85 °C |
Покупная плата — это больше, чем чип NEO-6M размером 16×12 мм. Распространённые платы GY-NEO6MV2 добавляют керамическую патч-антенну 25×25 мм, стабилизатор, позволяющий питать модуль от 3,3–5 V, небольшую EEPROM для хранения настроек, перезаряжаемую резервную батарейку, которая хранит время и данные спутников, и светодиод, который мигает после фиксации. На некоторых платах, как на фото выше, есть ещё разъём SMA или крошечный u.FL для внешней антенны и порт micro USB для прямого подключения к компьютеру.
Подключение NEO-6M: Arduino Uno, ESP32 и Raspberry Pi Pico
NEO-6M общается по UART, который работает как последовательный порт компьютера и использует две линии данных. Правило простое: линии данных перекрещиваются. Пин TX (передача) модуля идёт на пин RX (приём) платы, а пин RX модуля — на пин TX платы. Единственный аппаратный последовательный порт Arduino Uno (пины 0 и 1) занят загрузкой по USB и монитором порта, поэтому GPS подключаем к пинам D4 и D3 через SoftwareSerial. Подробности о последовательной связи — в статье Последовательная связь UART.
| Пин NEO-6M | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | VIN (5V) или 3V3 | VBUS (5V) или 3V3(OUT) |
| GND | GND | GND | GND |
| TX | D4 (RX для SoftwareSerial) | GPIO 16 (RX2) | GP1 (UART0 RX) |
| RX | D3, через делитель 1 kΩ / 2 kΩ | GPIO 17 (TX2) | GP0 (UART0 TX) |
| PPS (если есть) | Можно не подключать | Можно не подключать | Можно не подключать |
Первое определение координат: холодный, тёплый и горячий старт
Совершенно нормально, что GPS-модуль не сообщает координаты в первый же момент после первого включения. Чтобы вычислить положение, модулю нужны точные данные орбит видимых спутников (эфемериды), и каждый спутник передаёт их примерно раз в 30 секунд; загрузка полного альманаха — грубого списка орбит всех спутников — занимает 12,5 минуты. В зависимости от того, что модуль сохранил до выключения, он стартует одним из трёх способов. Время из даташита измерено в тестовых условиях с сильными сигналами от всех спутников; с маленькой керамической антенной из комплекта подождать несколько минут — нормально.
| Тип старта | Данные, хранящиеся в модуле | Даташит | На практике (на улице) |
|---|---|---|---|
| Холодный старт | Нет ни времени, ни положения, ни данных спутников (первое включение или севшая резервная батарейка) | 27 с | 1–5 минут; при слабых сигналах может превысить 10 минут |
| Тёплый старт | Альманах, примерное время и положение; эфемериды устарели (выключен дольше примерно 4 часов) | 27 с | 30 секунд – 1 минута |
| Горячий старт | Актуальные эфемериды и время (выключен совсем недавно, резервная батарейка заряжена) | 1 с | Несколько секунд |
- Выйди на улицу: в помещении, особенно в бетонных зданиях, модуль часто вообще не находит координаты. Для проверки подойдут балкон, сад или хотя бы место у открытого окна.
- Правильно направь антенну: плоская светлая сторона керамической антенны должна смотреть в небо; если перевернуть её или закрыть рукой, сигнал сильно ослабнет.
- Держи антенну подальше от электроники: антенна Wi-Fi у ESP32, импульсные стабилизаторы и длинные USB-кабели излучают помехи; размести антенну в нескольких сантиметрах от плат.
- Наберись терпения и не двигай модуль: не отключай питание во время первой фиксации: каждый перезапуск начинает поиск с нуля.
- Следи за светодиодом: светодиод на плате не горит, пока не найдена фиксация, а потом начинает мигать раз в секунду.
- Заряди резервную батарейку: если батарейка села, каждое включение — холодный старт. Если оставить модуль включённым на несколько часов, она зарядится, и последующие старты займут секунды.
Предложения NMEA: как читать $GPGGA и $GPRMC
NEO-6M отправляет всё, что находит, простыми текстовыми строками через запятую в стандарте NMEA 0183. С настройками по умолчанию каждую секунду приходят шесть видов предложений: GGA, GLL, GSA, GSV, RMC и VTG; предложения TXT обычно появляются только при включении и несут информационные сообщения вроде версии прошивки. Каждое предложение начинается с $; префикс GP означает, что данные от GPS, а следующие три буквы — тип предложения. Два символа после * в конце строки — контрольная сумма, вычисляемая XOR всех символов между $ и *, по ней отсеиваются повреждённые строки. Два самых важных для координат предложения: $GPGGA,092750.00,4100.82500,N,02858.74000,E,1,08,1.01,39.2,M,36.9,M,,*67 и $GPRMC,092750.00,A,4100.82500,N,02858.74000,E,0.512,,281026,,,A*7E
| Поле $GPGGA | Пример | Значение |
|---|---|---|
| Время (UTC) | 092750.00 | 09:27:50 UTC |
| Широта | 4100.82500,N | 41 градус 00,825 минуты северной широты |
| Долгота | 02858.74000,E | 28 градусов 58,74 минуты восточной долготы |
| Качество фиксации | 1 | 0 = нет фиксации, 1 = GPS, 2 = с дифференциальной поправкой (SBAS) |
| Спутники | 08 | Спутники, использованные в решении |
| HDOP | 1.01 | Горизонтальный геометрический фактор точности; ниже 2 — очень хорошо |
| Высота | 39.2,M | 39,2 м над средним уровнем моря |
| Высота геоида | 36.9,M | Разница между уровнем моря и эллипсоидом WGS84 |
| Поле $GPRMC | Пример | Значение |
|---|---|---|
| Время (UTC) | 092750.00 | Часы, минуты, секунды |
| Статус | A | A = положение достоверно, V = нет фиксации |
| Широта / долгота | 4100.82500,N / 02858.74000,E | Тот же формат, что в GGA |
| Скорость | 0.512 | В узлах (0,512 × 1,852 ≈ 0,95 км/ч) |
| Курс | (пусто) | Направление движения в градусах; на месте может быть пустым |
| Дата | 281026 | Формат ddmmyy: 28 октября 2026 |
| Режим | A | A = автономный, D = дифференциальный, N = нет данных |
Широта и долгота в NMEA записаны не в десятичных градусах, а в градусах и минутах (ddmm.mmmm), тогда как Google Maps и большинство программ ждут десятичные градусы. Чтобы перевести, возьми первые две цифры широты (первые три у долготы) как градусы, затем раздели оставшиеся минуты на 60 и прибавь: 4100.82500 → 41 + 0.825 / 60 = 41.013750; 02858.74000 → 28 + 58.74 / 60 = 28.979000. Значения южной (S) и западной (W) координаты записываются отрицательными числами. Шестой знак после запятой соответствует примерно 11 см, а пятый — 1,1 м; поскольку точность NEO-6M — 2,5 м, шести знаков более чем достаточно.
Шаг за шагом: смотрим сырые данные GPS на Arduino Uno
- Подключи NEO-6M по таблице: VCC → 5V, GND → GND, GPS TX → D4, GPS RX → D3 через делитель.
- Загрузи код ниже; дополнительная библиотека не нужна, SoftwareSerial входит в Arduino IDE.
- Открой монитор порта и выставь скорость 115200 бод.
- Вынеси модуль на улицу или к окну и смотри, как бегут строки, начинающиеся с $GP.
- Когда второе поле строки $GPRMC меняется с V на A, а светодиод начинает мигать, модуль нашёл координаты.
1#include <SoftwareSerial.h>
2
3SoftwareSerial gpsSerial(4, 3); // RX, TX → GPS TX D4'e, GPS RX D3'e / GPS TX to D4, GPS RX to D3
4
5void setup() {
6 Serial.begin(115200); // Seri Monitör hızı / Serial Monitor speed
7 gpsSerial.begin(9600); // NEO-6M varsayılan hızı / NEO-6M default baud rate
8 Serial.println(F("NEO-6M ham NMEA / raw NMEA"));
9}
10
11void loop() {
12 while (gpsSerial.available()) {
13 Serial.write(gpsSerial.read()); // gelen her baytı aynen aktar / pass every byte through
14 }
15}В мониторе порта каждую секунду появляется блок из шести-девяти строк (чем больше спутников в зоне видимости, тем на большее число строк делится предложение GSV). Если модуль ещё не нашёл спутников, строки полны пустых запятых, например $GPRMC,,V,,,,,,,,,,N*53 и $GPGGA,,,,,,0,00,99.99,,,,,,*48; это не ошибка, а признак того, что модуль работает, но пока не может вычислить положение. В строках $GPGSV видно число видимых спутников и уровень сигнала (dB-Hz) каждого; значения выше 30 dB-Hz означают хороший сигнал. Если строки не приходят вовсе, проверь подключение; если приходят непонятные символы — скорость.
Читаем широту, долготу, скорость и время через TinyGPSPlus
Вместо того чтобы разбирать строки NMEA вручную, гораздо удобнее использовать библиотеку TinyGPSPlus от Mikal Hart. Найди «TinyGPSPlus» в Менеджере библиотек и установи; шаги объяснены в статье Как добавить библиотеку Arduino. Внимание: в примерах библиотеки стоит 4800 бод, а NEO-6M работает на 9600 бод. Если запустить пример, не поменяв скорость, местоположение всегда будет INVALID (недействительно): из искажённых символов библиотека не может расшифровать ни одного предложения. Код ниже раз в секунду выводит координаты, скорость, высоту, число спутников, дату и время и превращает координаты в ссылку на Google Maps, которую можно открыть в браузере:
1#include <TinyGPSPlus.h>
2#include <SoftwareSerial.h>
3
4const int RX_PIN = 4; // GPS TX → D4
5const int TX_PIN = 3; // GPS RX ← D3 (bölücü üzerinden / through a divider)
6const uint32_t GPS_BAUD = 9600; // NEO-6M varsayılanı / NEO-6M default
7
8TinyGPSPlus gps;
9SoftwareSerial gpsSerial(RX_PIN, TX_PIN);
10unsigned long lastPrint = 0;
11
12void setup() {
13 Serial.begin(115200);
14 gpsSerial.begin(GPS_BAUD);
15 Serial.println(F("NEO-6M + TinyGPSPlus"));
16}
17
18void loop() {
19 while (gpsSerial.available()) {
20 gps.encode(gpsSerial.read()); // her baytı ayrıştırıcıya ver / feed every byte to the parser
21 }
22 if (millis() - lastPrint >= 1000) { // delay() yok, saniyede bir yaz / no delay(), print once per second
23 lastPrint = millis();
24 printInfo();
25 }
26}
27
28void printInfo() {
29 if (gps.charsProcessed() < 10) {
30 Serial.println(F("GPS verisi yok: kablolari ve baud hizini kontrol et / No GPS data: check wiring and baud"));
31 return;
32 }
33 Serial.print(F("Uydu / Sats: "));
34 Serial.println(gps.satellites.value());
35
36 if (gps.location.isValid()) {
37 Serial.print(F("Enlem / Lat: "));
38 Serial.println(gps.location.lat(), 6);
39 Serial.print(F("Boylam / Lng: "));
40 Serial.println(gps.location.lng(), 6);
41 Serial.print(F("Hiz / Speed: "));
42 Serial.print(gps.speed.kmph(), 1);
43 Serial.println(F(" km/h"));
44 Serial.print(F("Yukseklik / Alt: "));
45 Serial.print(gps.altitude.meters(), 1);
46 Serial.println(F(" m"));
47 // Google Haritalar bağlantısı / Google Maps link
48 Serial.print(F("https://www.google.com/maps/search/?api=1&query="));
49 Serial.print(gps.location.lat(), 6);
50 Serial.print(',');
51 Serial.println(gps.location.lng(), 6);
52 } else {
53 Serial.println(F("Konum yok, uydu araniyor / No fix yet, searching"));
54 }
55
56 if (gps.date.isValid() && gps.time.isValid()) {
57 char buf[32];
58 snprintf(buf, sizeof(buf), "%02d.%02d.%04d %02d:%02d:%02d UTC",
59 gps.date.day(), gps.date.month(), (int)gps.date.year(),
60 gps.time.hour(), gps.time.minute(), gps.time.second());
61 Serial.println(buf); // saat UTC'dir / time is UTC
62 }
63 Serial.println();
64}| Функция | Что возвращает |
|---|---|
| gps.encode(c) | Вызывается с каждым пришедшим байтом; возвращает true, когда достоверное предложение закончено |
| gps.location.lat() / lng() (широта / долгота) | Широта и долгота в десятичных градусах |
| gps.location.isValid() / age() (достоверность / возраст) | Есть ли достоверное положение / миллисекунды с последнего обновления |
| gps.speed.kmph() (скорость) | Путевая скорость в км/ч (есть ещё mps() и knots()) |
| gps.course.deg() (курс) | Направление движения в градусах (0 = север, 90 = восток) |
| gps.altitude.meters() (высота) | Высота над уровнем моря в метрах |
| gps.satellites.value() (спутники) | Число спутников, использованных для положения |
| gps.hdop.hdop() (точность) | Горизонтальный геометрический фактор точности (меньше — лучше) |
| gps.date.day() / gps.time.hour() (дата / время) | Поля даты и времени UTC |
| TinyGPSPlus::distanceBetween(...) | Расстояние между двумя координатами в метрах |
| gps.failedChecksum() | Число повреждённых предложений; если оно всё время растёт, данные теряются |
Главное правило этого кода — никогда не использовать delay() внутри loop(). GPS отправляет около 500 байт в секунду, а приёмный буфер SoftwareSerial — всего 64 байта; во время долгой delay() буфер переполняется, предложения обрезаются, и TinyGPSPlus выбрасывает их с ошибкой контрольной суммы. Поэтому вывод раз в секунду сделан через millis(); подробности — в статье millis() и delay(). Время GPS всегда UTC, так что прибавляй смещение своего часового пояса (например, +1 час для центральноевропейского зимнего времени или +3 для Турции и Москвы). На Arduino Uno double на самом деле 32-битный float, поэтому последняя цифра широты и долготы округляется примерно до полуметра; на фоне точности модуля в 2,5 м эта разница не важна.
ESP32 и Serial2: показываем координаты на OLED-дисплее
На ESP32 SoftwareSerial не нужен: у чипа три аппаратных UART, и Serial2 можно назначить на любые пины. В примере ниже GPS подключён к GPIO 16 (RX2) и GPIO 17 (TX2); поскольку ESP32 работает на 3,3 V, делитель тоже не нужен. Координаты, скорость и местное время выводятся на OLED-дисплей SSD1306 0,96 дюйма, подключённый по I2C к GPIO 21 (SDA) и GPIO 22 (SCL). Помимо TinyGPSPlus коду нужны библиотеки Adafruit SSD1306 и Adafruit GFX.
1#include <TinyGPSPlus.h>
2#include <Wire.h>
3#include <Adafruit_GFX.h>
4#include <Adafruit_SSD1306.h>
5
6#define GPS_RX 16 // ESP32 RX2 ← GPS TX
7#define GPS_TX 17 // ESP32 TX2 → GPS RX
8const int UTC_OFFSET = 3; // Türkiye UTC+3, kendi saat dilimini yaz / set your own time zone
9
10TinyGPSPlus gps;
11Adafruit_SSD1306 display(128, 64, &Wire, -1); // OLED: SDA 21, SCL 22
12unsigned long lastDraw = 0;
13
14String mapsLink() {
15 // Google Haritalar bağlantısı üret / build a Google Maps link
16 return "https://www.google.com/maps/search/?api=1&query=" +
17 String(gps.location.lat(), 6) + "," + String(gps.location.lng(), 6);
18}
19
20void drawScreen() {
21 display.clearDisplay();
22 display.setTextSize(1);
23 display.setCursor(0, 0);
24 display.print(F("Uydu/Sat: "));
25 display.print(gps.satellites.value());
26
27 if (gps.time.isValid()) {
28 int h = (gps.time.hour() + UTC_OFFSET + 24) % 24; // yerel saat / local time
29 char t[12];
30 snprintf(t, sizeof(t), "%02d:%02d:%02d", h, gps.time.minute(), gps.time.second());
31 display.setCursor(80, 0);
32 display.print(t);
33 }
34
35 if (gps.location.isValid()) {
36 display.setCursor(0, 16);
37 display.print(F("Lat: "));
38 display.println(gps.location.lat(), 6);
39 display.print(F("Lng: "));
40 display.println(gps.location.lng(), 6);
41 display.setTextSize(2); // hız büyük yazılsın / speed in large digits
42 display.setCursor(0, 44);
43 display.print(gps.speed.kmph(), 1);
44 display.print(F(" km/h"));
45 } else {
46 display.setCursor(0, 24);
47 display.println(F("Uydu araniyor..."));
48 display.println(F("Searching for fix"));
49 }
50 display.display();
51}
52
53void setup() {
54 Serial.begin(115200);
55 Serial2.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX); // donanım UART2 / hardware UART2
56 if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
57 Serial.println(F("OLED bulunamadi / OLED not found"));
58 while (true) delay(10);
59 }
60 display.setTextColor(SSD1306_WHITE);
61}
62
63void loop() {
64 while (Serial2.available()) {
65 gps.encode(Serial2.read()); // NMEA baytlarını çöz / decode NMEA bytes
66 }
67 if (millis() - lastDraw >= 1000) { // saniyede bir güncelle / refresh once per second
68 lastDraw = millis();
69 drawScreen();
70 if (gps.location.isValid()) {
71 Serial.println(mapsLink()); // Telegram ya da SMS ile gönderilebilir / can be sent via Telegram or SMS
72 }
73 }
74}Переменная UTC_OFFSET переводит время GPS в местное; для Турции это 3, для центральноевропейского зимнего времени — 1. Функция mapsLink() превращает координаты в адрес Google Maps с параметром query=широта,долгота. Эту ссылку можно скопировать из монитора порта и открыть в браузере, отправить на телефон через Telegram-бота или переслать SMS через GSM-модуль SIM800L. На платах ESP32-WROVER с PSRAM GPIO 16 и 17 заняты памятью, так что подключай GPS, например, к GPIO 26 и 27; на ESP32-C3, где всего два UART, используй Serial1 вместо Serial2.
Чтение GPS на Raspberry Pi Pico и MicroPython
На Raspberry Pi Pico GPS подключаем к UART0: TX модуля идёт на GP1, а RX — на GP0. В MicroPython строки NMEA можно разобрать самостоятельно, без установки библиотек, и это ещё и отличное упражнение, чтобы понять устройство предложений. Код проверяет контрольную сумму каждой строки, берёт число спутников из GGA, а координаты, скорость и время — из RMC и переводит градусы с минутами в десятичные градусы. Настройка timeout=200 заставляет readline() ждать конца строки до 200 мс; если при запуске всё же проскочит половина строки, проверка контрольной суммы её отбросит. Поскольку тип предложения берётся через f[0][3:], код распознаёт и строки $GNRMC и $GNGGA, которые отправляют модули, работающие с несколькими спутниковыми системами. Если ещё не умеешь запускать код через Thonny, сначала загляни в статью Основы MicroPython.
1from machine import UART, Pin
2
3# GP0 (TX) → GPS RX, GP1 (RX) ← GPS TX
4gps = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1), timeout=200, rxbuf=1024)
5
6def checksum_ok(line):
7 # $ ile * arasındaki karakterlerin XOR'u / XOR of the characters between $ and *
8 try:
9 body, cs = line[1:].split('*')
10 x = 0
11 for ch in body:
12 x ^= ord(ch)
13 return x == int(cs[:2], 16)
14 except ValueError:
15 return False
16
17def to_deg(value, hemi):
18 # ddmm.mmmm → ondalık derece / decimal degrees
19 dot = value.index('.')
20 deg = int(value[:dot - 2]) + float(value[dot - 2:]) / 60
21 return -deg if hemi in ('S', 'W') else deg
22
23sats = '0'
24while True:
25 raw = gps.readline() # bir NMEA satırı / one NMEA line
26 if not raw:
27 continue
28 try:
29 line = raw.decode().strip()
30 except UnicodeError:
31 continue # bozuk bayt / corrupted byte
32 if not line.startswith('$') or not checksum_ok(line):
33 continue
34 f = line.split('*')[0].split(',')
35 kind = f[0][3:] # GPRMC ya da GNRMC → RMC / GPRMC or GNRMC → RMC
36 if kind == 'GGA':
37 sats = f[7] # kullanılan uydu sayısı / satellites in use
38 elif kind == 'RMC':
39 if f[2] != 'A':
40 print('Uydu araniyor / searching, uydu/sats:', sats)
41 continue
42 lat = to_deg(f[3], f[4])
43 lon = to_deg(f[5], f[6])
44 kmh = float(f[7] or 0) * 1.852 # knot → km/sa / knots → km/h
45 t = f[1]
46 print('UTC {}:{}:{} uydu/sats: {}'.format(t[0:2], t[2:4], t[4:6], sats))
47 print('Konum / position: {:.6f}, {:.6f} {:.1f} km/h'.format(lat, lon, kmh))
48 print('https://www.google.com/maps/search/?api=1&query={:.6f},{:.6f}'.format(lat, lon))Идеи проектов с NEO-6M
- Трекер, присылающий координаты по SMS: с NEO-6M и SIM800L собери трекер для машины или велосипеда, который на SMS с текстом «LOCATION» отвечает ссылкой на Google Maps.
- GPS-регистратор: каждую секунду сохраняй маршрут в CSV на модуль SD-карты, а потом отображай его на карте на компьютере.
- Велоспидометр: показывай на OLED-дисплее текущую и максимальную скорость и общее расстояние; расстояние между соседними точками суммируй через TinyGPSPlus::distanceBetween().
- Часы, синхронизированные со спутниками: бери время с GPS и выставляй модуль часов RTC с точностью до секунды без интернета.
- Сигнализация геозоны: система, которая включает зуммер или отправляет уведомление, когда что-то удаляется больше чем на 100 метров от выбранной точки.
- Слежение на большой дальности: передавай координаты на приёмник за несколько километров через модуль LoRa и экономь заряд батареи с помощью глубокого сна ESP32.
Нет данных или нет фиксации: частые проблемы и решения
| Симптом | Вероятная причина | Решение |
|---|---|---|
| Монитор порта совсем пустой | Перепутаны TX и RX, нет общей GND или нет питания модуля | Подключи GPS TX к пину RX платы (D4 на Uno), соедини земли, измерь VCC |
| «No GPS detected: check wiring.» (GPS не обнаружен) | За 5 секунд до библиотеки не дошло даже 10 символов | Проверь подключение и номера пинов в коде; попробуй поменять TX и RX |
| Непонятные символы | Не совпадает скорость | Для GPS используй 9600, а в мониторе порта — скорость из кода; если не помогает, попробуй 4800 и 38400 |
| Строки приходят, но поля пустые (,V,) | Модуль работает, но спутников не нашёл | Выйди на улицу, направь антенну в небо, подожди 5–15 минут |
| Число спутников застряло на 0–3 | Слабый сигнал, перевёрнутая антенна, плохо сидящий разъём u.FL или источник помех рядом | Проверь антенну, плотно вставь разъём, отодвинь антенну от ESP32 и стабилизаторов |
| В сырых данных есть координаты, а TinyGPSPlus пишет INVALID | delay() в loop() переполняет буфер; failedChecksum() всё время растёт | Убери delay(), используй millis(), вызывай encode() постоянно |
| Время сдвинуто на несколько часов | Время GPS — это UTC | Прибавь смещение своего часового пояса |
| На месте координаты гуляют на несколько метров, а скорость не 0 | Обычный шум GPS и отражённые от зданий сигналы | Считай скорость ниже 2 км/ч равной 0, пропускай показания с большим HDOP, усредняй их |
| При каждом включении снова ждёт несколько минут | Резервная батарейка села или отсутствует | Оставь модуль включённым на несколько часов, чтобы зарядить батарейку |
NEO-6M за очень небольшие деньги добавляет в проекты ответы на вопросы «где я, с какой скоростью еду и который час»; весь секрет — показать антенне небо и дать первой фиксации нужное время. Чтобы лучше понять последовательную связь, загляни в статью UART. В приложении BlueGrays есть проекты, которые пригодятся и для GPS-поделок: последовательная связь между двумя Arduino, OLED-дисплеи, запись данных на microSD, глубокий сон ESP32 и сигнализация с уведомлениями в Telegram — каждый со схемами и пошаговым кодом.
Частые вопросы
Работает ли GPS-модуль NEO-6M в помещении?
Обычно нет. Сигналы спутников доходят до земли очень слабыми, а бетон и металлические крыши гасят большую их часть. У открытого окна он может поймать несколько спутников, но для надёжной фиксации антенне нужен прямой вид на небо; если координаты нужны в помещении, используй внешнюю активную антенну на крыше или у окна.
Сколько NEO-6M ищет координаты в первый раз?
По даташиту холодный старт занимает 27 секунд, а горячий — 1 секунду. На практике с маленькой керамической антенной на улице первая фиксация обычно занимает 1–5 минут, а при первом включении или с севшей резервной батарейкой — 10–15 минут. Если модуль выключили совсем недавно, он снова ловит координаты за несколько секунд.
Насколько точен GPS-модуль NEO-6M?
Производитель указывает точность по горизонтали 2,5 м CEP при открытом небе или 2,0 м с поправкой SBAS; это значит, что половина показаний ближе 2,5 м к истинной точке. В городе отражённые от зданий сигналы могут увеличить ошибку до 5–10 метров. Высота определяется менее точно, чем положение по горизонтали.
Работает ли NEO-6M от 5V и можно ли подключить его прямо к Arduino?
У распространённых плат GY-NEO6MV2 есть стабилизатор, так что VCC можно питать от 5 V. Но пин RX чипа выдерживает не больше 3,6 V, поэтому понизь сигнал TX Arduino Uno на 5 V делителем напряжения из 1 kΩ и 2 kΩ. Выход TX модуля — 3,3 V, и Uno читает его без проблем.
Нужен ли GPS-модулю интернет или SIM-карта?
Нет. NEO-6M вычисляет положение напрямую по сигналам спутников, бесплатно и без интернета. Интернет или SIM-карта нужны, только если координаты нужно куда-то отправить — через Wi-Fi у ESP32 или GSM-модуль вроде SIM800L.
Чем отличаются NEO-6M и NEO-M8N?
NEO-6M использует только спутники GPS. Более новый NEO-M8N может одновременно с GPS использовать спутники ГЛОНАСС, Galileo или BeiDou; поскольку он видит больше спутников, в городе он быстрее и стабильнее определяет координаты. Предложения M8N обычно начинаются с $GN, но TinyGPSPlus читает оба одним и тем же кодом.
Что собрать после прочтения
Все проекты
Односторонняя связь между двумя Arduino
Ты заставляешь две Arduino разговаривать по одному проводу: нажми кнопку на одной, и на другой загорится светодиод, нажми снова — погаснет. Плата-передатчик сообщает о нажатии кнопки коротким сообщени

Двусторонняя связь между двумя Arduino
Две Arduino соединены проводами и разговаривают друг с другом: нажми кнопку на одной, и на другой загорится свет, нажми снова — погаснет. На обеих платах одна и та же программа, поэтому каждая и отпра

Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
Собери на ESP32 регистратор температуры с отметками времени! Каждую минуту читай температуру и влажность с DHT22, бери реальное время из DS1307 RTC и записывай всё на карту microSD в формате CSV. OLED показывает текущую температуру (крупным шрифтом), влажность в процентах, время и счётчик записей. Файл /temp_log.csv на SD-карте открывается в Excel, Google Sheets или Python pandas — идеально для теплиц, комнат, лабораторий и хранения продуктов.

ESP32 HTTPClient + API погоды (с OLED-дисплеем SSD1306)
В этом проекте ESP32 через HTTPClient.h делает вызов REST API к сервису погоды (wttr.in). В отличие от прошлой версии с I2C LCD, здесь используется OLED SSD1306 (128×64), который позволяет крупные шрифты, векторные значки и богатую картинку на одном экране. Семь векторных значков погоды (солнечно, переменная облачность, облачно, дождь, снег, гроза, туман) рисуются во время работы (растровые файлы не нужны). Температура выводится крупными цифрами.

Глубокий сон ESP32: экономия батареи (OLED + счётчик в RTC RAM)
Режим глубокого сна (Deep Sleep) у ESP32 снижает потребление до ~10 µA, выключая процессор и большую часть периферии, — это важно для IoT-устройств на батарейках. В этом проекте используются три источника пробуждения: таймер (15 секунд), внешний пин (EXT0 — кнопка GPIO 33) и касание (T0/GPIO 4). Переменные с RTC_DATA_ATTR сохраняются во время глубокого сна — счётчики загрузок, пробуждений по таймеру и по кнопке ведутся непрерывно.

Точное время из интернета через NTP на ESP32
ESP32 подключается к Wi-Fi и получает точное время с точностью до миллисекунд от серверов NTP (Network Time Protocol). Благодаря функции configTzTime() автоматически применяется часовой пояс Турции (TRT, UTC+3), а в странах с летним временем переходы обрабатываются автоматически по строке POSIX TZ. Время выводится в монитор порта и на необязательный I2C LCD. configTzTime() запускает службу SNTP, которая периодически пересинхронизирует часы.

Сигнализация движения на ESP32 (PIR + зуммер + светодиод + Telegram)
Умная охранная сигнализация, которая при обнаружении движения PIR-датчиком включает зуммер и светодиод и одновременно сразу отправляет владельцу уведомление в Telegram. В ней есть 30-секундная пауза, ограничивающая частоту повторных тревог; этот механизм не проверяет срабатывания PIR и не устраняет ложные тревоги. Подходит для дома, гаража, склада или мастерской. С ESP32-CAM можно добавить уведомления с фото, а с обычной ESP32 DevKit V1 приходят текстовые.

Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)
В этом проекте время и дата из модуля часов реального времени (RTC) DS1307 выводятся на I2C LCD-экран 16x2. DS1307 — RTC с резервной батарейкой, который хранит время даже при выключенной ESP32. Оба модуля делят одну шину I2C (SDA/SCL), и ты узнаёшь, как управлять несколькими устройствами всего по двум сигнальным проводам. Проект даёт практические знания о протоколе I2C, работе модуля RTC и динамическом выводе данных на LCD-экран.
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

