Создаем GPS часы на Arduino
Вам необходим источник точного времени от GPS? Данная статья покажет вам, как использовать модуль GPS для получения времени, даты и координат, и как показать их на LCD индикаторе с помощью Arduino.
Что необходимо?
- компьютер с установленной Arduino IDE;
- Arduino (мы используем Arduino Mega);
- LCD индикатор;
- GPS модуль (мы используем EM-411, возможны и другие, поддерживающие протокол NMEA, например, VK2828U7G5LF или GY-NEO6MV2);
- макетная плата, перемычки и потенциометр 5 кОм;
- библиотека TinyGPS (ссылка ниже).
Введение
Создание системы глобального позиционирования, или GPS, началось в начале 1970-х годов. Каждая страна (Россия, США, Китай и т.д.) обладают своей собственной системой, но большинство средств спутниковой навигации в мире используют систему США.
Каждый спутник системы имеет атомные часы, которые непрерывно контролируются и корректируются NORAD (командованием воздушно-космической обороны Северной Америки) каждый день.
По сути, приемник по своим часам измеряет TOA (время получения сигнала, time of arrival) четырех спутниковых сигналов. Исходя из TOA и TOT (времени отправки сигнала, time of transmission), приемник вычисляет четыре значения времени «пролета» сигнала (TOF, time of flight), которые отличаются друг от друга в зависимости от расстояния спутник-приемник. Затем, исходя из четырех значений TOF, приемник вычисляет свое положение в трехмерном пространстве и отклонение своих часов.
Самые недорогие GPS приемники обладают точностью около 20 метров для большинства мест на Земле. Теперь посмотрим, как изготовить свои собственные часы GPS с помощью Arduino.
Аппаратная часть
Мой GPS модуль имеет 6 контактов: GND, Vin, Tx, Rx и снова GND. Шестой вывод никуда не подключен. Контакт GND соединен с корпусом на Arduino, Vin подключаем к шине +5В на Arduino, Tx подключен к выводу 10 на Arduino, а вывод Rx никуда не подключаем, так как не будем посылать на GPS модуль никаких сообщений. Мой модуль передает спутниковые данные, используя интерфейс RS-232, со скоростью 4800 бит/сек, которые принимаются Arduino на выводе 10.
Ниже показана фотография GPS модуля:
Модуль отправляет то, что известно как NMEA сообщения. Здесь вы можете увидеть пример одного NMEA сообщения и его разъяснение (выдержка из технического описания):
$GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M,,,,0000*18
Название | Пример | Единицы | Описание |
---|---|---|---|
ID сообщения | $GPGGA | Заголовок протокола GGA | |
Время UTC | 161229.487 | hhmmss.sss (две цифры часы, две цифры минуты, затем секунды с точностью до тысячных) | |
Широта | 3723.2475 | ddmm.mmmm (первые две цифры градусы, затем минуты с точностью до десятитысячных) | |
Флаг N/S | N | N – север, S – юг | |
Долгота | 12158.3416 | ddmm.mmmm (первые две цифры градусы, затем минуты с точностью до десятитысячных) | |
Флаг E/W | W | E – восток, W – запад | |
Индикатор местоположения | 1 |
| |
Количество используемых спутников | 07 | В диапазоне от 0 до 12 | |
HDOP | 1.0 | Ухудшение точности по горизонтали | |
Высота относительно уровня моря | 9.0 | метры | |
Единицы измерения | M | метры | |
Геоидальное различие | Различие между земным эллипсоидом WGS-84 и уровнем моря (геноидом) | ||
Единицы измерения | M | метры | |
Возраст дифференциальных данных GPS | секунды | Нулевые поля, когда DGPS не используется | |
ID станции, передающей дифференциальные поправки | 0000 | ||
Контрольная сумма | *18 | ||
<CR><LF> | Конец сообщения |
Все эти данные принимаются Arduino через вывод 10. Библиотека TinyGPS читает сообщения GPGGA и GPRMC (для подробной информации о GPRMC смотрите техническое описание).
Arduino на схеме не показан. Подключите периферийные устройства согласно подписанным соединениям.
Программное обеспечение
При подаче питания GPS модуль затрачивает некоторое время, чтобы получить правильное местоположения от спутников. Когда местоположение получено, модуль шлет NMEA сообщения на Arduino. Библиотека TinyGPS содержит функцию для получения времени и даты из GPRMC сообщения. Она называется crack_datetime()
и принимает в качестве параметров семь указателей на переменные: год year
, месяц month
, день месяца day
, часы hour
, минуты minute
, секунды second
, и сотые доли секунды hundredths
. Вызов функции выглядит так:
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
Вызов данной функции возвращает вам в переменных правильные значения до тех пор, пока с железом всё в порядке.
Чтобы получить ваше местоположение, можно вызвать функцию f_get_position()
. Данная функция принимает в качестве параметров два указателя на переменные: широта latitude
и долгота longitude
. Вызов данной функции выглядит так:
gps.f_get_position(&latitude, &longitude);
Исходный текст программы:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#define RXPIN 10
#define TXPIN 9
#define GPSBAUD 4800
#define RS 2
#define EN 3
#define D4 4
#define D5 5
#define D6 6
#define D7 7
TinyGPS gps;
SoftwareSerial uart_gps(RXPIN, TXPIN);
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);
// Переменные
int seconds;
int timeoffset = 1; // Пользователь должен изменить единицу на соответствующий часовой пояс. В примере используем сдвиг на +1 час.
// Объявление функций.
void getgps(TinyGPS &gps);
// Функция настройки - запускается только при включении
void setup()
{
Serial.begin(115200); // Запуск последовательного интерфейса для отладки
uart_gps.begin(GPSBAUD); // Запуск приемника UART для GPS
lcd.begin(16,2); // Объявление LCD
lcd.print(" GPS clock"); // Сообщение приветствия
delay(1000); // Ждем одну секунду
lcd.clear(); // Очистить LCD
}
// Цикл главной программы - запущен всегда
void loop()
{
while(uart_gps.available())
{
int c = uart_gps.read();
if(gps.encode(c))
{
getgps(gps);
}
}
}
/*
* Данная функция получает данные от GPS модуля
* и отображает их на LCD
*/
void getgps(TinyGPS &gps)
{
int year;
float latitude, longitude;
byte month, day, hour, minute, second, hundredths;
gps.f_get_position(&latitude, &longitude);
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
hour = hour + timeoffset;
lcd.clear();//lcd.setCursor(0, 0);
lcd.print("Time: ");
if (hour <= 9)
{
lcd.print("0"); lcd.print(hour, DEC);
}
else
{
lcd.print(hour, DEC);
}
lcd.print(":");
if (minute <=9)
{
lcd.print("0"); lcd.print(minute, DEC);
}
else
{
lcd.print(minute, DEC);
}
lcd.print(":");
if (second <= 9)
{
lcd.print("0"); lcd.print(second, DEC);
}
else
{
lcd.print(second, DEC);
}
lcd.setCursor(0,1);
lcd.print("Date: ");
if (day <= 9)
{
lcd.print("0"); lcd.print(day, DEC);
}
else
{
lcd.print(day, DEC);
}
lcd.print("-");
if (month <= 9)
{
lcd.print(month, DEC);
}
else
{
lcd.print(month, DEC);
}
lcd.print("-"); lcd.print(year, DEC);
delay(2000);
lcd.clear();
lcd.print("Lat: "); lcd.print(latitude, DEC);
lcd.setCursor(0,1);
lcd.print("Lon: "); lcd.print(longitude, DEC);
delay(2000);
// Debugging purpose only.
Serial.print(latitude, DEC); Serial.print(" - "); Serial.println(longitude, DEC);
}
Загрузки
Здесь все файлы, которые вам могут понадобиться:
- исходный код скетча;
- библиотека TinyGPS;
- техническое описание на GPS модуль EM-411;
- техническое описание на GPS модуль VK2828U7G5LF;
- техническое описание на GPS модули NEO-6.
Комплектующие: технические описания и ссылки на магазины (aliexpress и пр.)
- Arduino Mega;
- LCD индикатор (или такой же индикатор, но уже с кнопками и потенциометром);
- GPS модули VK2828U7G5LF и GY-NEO6MV2;
- макетная плата;
- перемычки.
Фото и видео
На фотографиях и видео я добавил смещение широты и долготы. Чтобы улучшить прием, я подключил GPS модуль через длинный кабель и высунул его в окно.
Заключение
В данной статье мы рассмотрели, как получить дату, время и координаты от GPS модуля, а затем как их отобразить на LCD индикаторе. Теперь вы знаете, где находитесь!
Надеюсь статья оказалась полезной. Оставляйте комментарии!