Компоненты · 10 мин чтения

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 (u-blox NEO-6M)
GPS-модуль NEO-6M: посередине приёмник u-blox NEO-6M, сверху штырьковые выводы, слева EEPROM для хранения настроек и светодиод PPS; золотистая деталь рядом — разъём SMA для внешней антенны.

Что такое 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-6MArduino UnoESP32Raspberry Pi Pico
VCC5VVIN (5V) или 3V3VBUS (5V) или 3V3(OUT)
GNDGNDGNDGND
TXD4 (RX для SoftwareSerial)GPIO 16 (RX2)GP1 (UART0 RX)
RXD3, через делитель 1 kΩ / 2 kΩGPIO 17 (TX2)GP0 (UART0 TX)
PPS (если есть)Можно не подключатьМожно не подключатьМожно не подключать
Входные пины чипа NEO-6M выдерживают не больше 3,6 V. Пин TX у Arduino Uno выдаёт 5 V, поэтому не подключай D3 прямо к пину RX модуля: поставь делитель напряжения (D3 → 1 kΩ → GPS RX, GPS RX → 2 kΩ → GND) или используй преобразователь логических уровней. Если нужно только читать координаты, пин RX модуля можно не подключать: он нужен лишь для отправки модулю команд настройки. ESP32 и Pico и так работают на 3,3 V, так что делитель им не нужен.
Поскольку на плате есть свой стабилизатор, по возможности питай VCC от 5 V: некоторые платы из-за падения напряжения на стабилизаторе работают от 3,3 V ненадёжно. При поиске спутников модуль потребляет около 47 mA, так что для проектов на батарейках заранее посчитай время работы калькулятором времени работы от батареи.

Первое определение координат: холодный, тёплый и горячий старт

Совершенно нормально, что 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.0009:27:50 UTC
Широта4100.82500,N41 градус 00,825 минуты северной широты
Долгота02858.74000,E28 градусов 58,74 минуты восточной долготы
Качество фиксации10 = нет фиксации, 1 = GPS, 2 = с дифференциальной поправкой (SBAS)
Спутники08Спутники, использованные в решении
HDOP1.01Горизонтальный геометрический фактор точности; ниже 2 — очень хорошо
Высота39.2,M39,2 м над средним уровнем моря
Высота геоида36.9,MРазница между уровнем моря и эллипсоидом WGS84
Поле $GPRMCПримерЗначение
Время (UTC)092750.00Часы, минуты, секунды
СтатусAA = положение достоверно, V = нет фиксации
Широта / долгота4100.82500,N / 02858.74000,EТот же формат, что в GGA
Скорость0.512В узлах (0,512 × 1,852 ≈ 0,95 км/ч)
Курс(пусто)Направление движения в градусах; на месте может быть пустым
Дата281026Формат ddmmyy: 28 октября 2026
РежимAA = автономный, 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

  1. Подключи NEO-6M по таблице: VCC → 5V, GND → GND, GPS TX → D4, GPS RX → D3 через делитель.
  2. Загрузи код ниже; дополнительная библиотека не нужна, SoftwareSerial входит в Arduino IDE.
  3. Открой монитор порта и выставь скорость 115200 бод.
  4. Вынеси модуль на улицу или к окну и смотри, как бегут строки, начинающиеся с $GP.
  5. Когда второе поле строки $GPRMC меняется с V на A, а светодиод начинает мигать, модуль нашёл координаты.
C++ (Arduino IDE)
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, которую можно открыть в браузере:

C++ (Arduino IDE)
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 м эта разница не важна.

SoftwareSerial надёжно работает на 9600 бод, но во время приёма ненадолго блокирует прерывания. Если в проекте есть ещё библиотеки, чувствительные ко времени, например Servo, выбери на Uno библиотеку AltSoftSerial (RX = D8, TX = D9) или аппаратный порт Serial1 на Arduino Mega (RX1 = 19, TX1 = 18).

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.

C++ (Arduino IDE)
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.

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 пишет INVALIDdelay() в loop() переполняет буфер; failedChecksum() всё время растётУбери delay(), используй millis(), вызывай encode() постоянно
Время сдвинуто на несколько часовВремя GPS — это UTCПрибавь смещение своего часового пояса
На месте координаты гуляют на несколько метров, а скорость не 0Обычный шум GPS и отражённые от зданий сигналыСчитай скорость ниже 2 км/ч равной 0, пропускай показания с большим HDOP, усредняй их
При каждом включении снова ждёт несколько минутРезервная батарейка села или отсутствуетОставь модуль включённым на несколько часов, чтобы зарядить батарейку
Чтобы понять, где проблема — в модуле или в коде, подключи модуль прямо к компьютеру через преобразователь USB-TTL и открой его в бесплатной программе u-blox u-center. Она показывает уровень сигнала каждого спутника, статус фиксации и положение на карте; там же можно изменить скорость и частоту обновления (до 5 Hz) и навсегда сохранить настройки в памяти модуля.

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
#57Средний
Premium

Односторонняя связь между двумя Arduino

Ты заставляешь две Arduino разговаривать по одному проводу: нажми кнопку на одной, и на другой загорится светодиод, нажми снова — погаснет. Плата-передатчик сообщает о нажатии кнопки коротким сообщени

4.4(37)
50
Двусторонняя связь между двумя Arduino
#58Средний
Premium

Двусторонняя связь между двумя Arduino

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

4.5(20)
26
Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Продвинутый
Premium

Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

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

4.7(7)
12
ESP32 HTTPClient + API погоды (с OLED-дисплеем SSD1306)
#134Продвинутый
Premium

ESP32 HTTPClient + API погоды (с OLED-дисплеем SSD1306)

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

4.3(10)
19
Глубокий сон ESP32: экономия батареи (OLED + счётчик в RTC RAM)
#135Продвинутый
Premium

Глубокий сон ESP32: экономия батареи (OLED + счётчик в RTC RAM)

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

4.3(10)
16
Точное время из интернета через NTP на ESP32
#128Продвинутый
Premium

Точное время из интернета через NTP на ESP32

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

4.5(13)
21
Сигнализация движения на ESP32 (PIR + зуммер + светодиод + Telegram)
#145Продвинутый
Premium

Сигнализация движения на ESP32 (PIR + зуммер + светодиод + Telegram)

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

0.0(0)
9
Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)
#120Средний
Premium

Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)

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

4.6(26)
40