Создаем GPS часы на Arduino

Добавлено 28 июня 2016 в 09:20

Вам необходим источник точного времени от GPS? Данная статья покажет вам, как использовать модуль GPS для получения времени, даты и координат, и как показать их на LCD индикаторе с помощью Arduino.

Что необходимо?

Введение

Создание системы глобального позиционирования, или 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 модуля:

gps модуль
GPS модуль EM-411

Модуль отправляет то, что известно как NMEA сообщения. Здесь вы можете увидеть пример одного NMEA сообщения и его разъяснение (выдержка из технического описания):

$GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M,,,,0000*18
Формат данных GGA
НазваниеПримерЕдиницыОписание
ID сообщения$GPGGA Заголовок протокола GGA
Время UTC161229.487 hhmmss.sss (две цифры часы, две цифры минуты, затем секунды с точностью до тысячных)
Широта3723.2475 ddmm.mmmm (первые две цифры градусы, затем минуты с точностью до десятитысячных)
Флаг N/SN N – север, S – юг
Долгота12158.3416 ddmm.mmmm (первые две цифры градусы, затем минуты с точностью до десятитысячных)
Флаг E/WW E – восток, W – запад
Индикатор местоположения1 
  • 0 – местоположение недоступно или некорректно;
  • 1 – режим GPS SPS, местоположение корректно;
  • 2 – дифференциальный GPS, режим SPS, местоположение корректно;
  • 3 – режим GPS PPS, местоположение корректно.
Количество используемых спутников07 В диапазоне от 0 до 12
HDOP1.0 Ухудшение точности по горизонтали
Высота относительно уровня моря9.0метры 
Единицы измеренияMметры 
Геоидальное различие  Различие между земным эллипсоидом WGS-84 и уровнем моря (геноидом)
Единицы измеренияMметры 
Возраст дифференциальных данных GPS секундыНулевые поля, когда DGPS не используется
ID станции, передающей дифференциальные поправки0000  
Контрольная сумма*18  
<CR><LF>  Конец сообщения

Все эти данные принимаются Arduino через вывод 10. Библиотека TinyGPS читает сообщения GPGGA и GPRMC (для подробной информации о GPRMC смотрите техническое описание).

Arduino на схеме не показан. Подключите периферийные устройства согласно подписанным соединениям.

схема gps часов на arduino
Схема GPS часов на 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);

}

Загрузки

Здесь все файлы, которые вам могут понадобиться:

Комплектующие: технические описания и ссылки на магазины (aliexpress и пр.)

Фото и видео

На фотографиях и видео я добавил смещение широты и долготы. Чтобы улучшить прием, я подключил GPS модуль через длинный кабель и высунул его в окно.

gps часы на arduino дата и время
Дата и время
gps часы на arduino широта и долгота
Широта и долгота
gps часы на arduino подключение
Подключение

Заключение

В данной статье мы рассмотрели, как получить дату, время и координаты от GPS модуля, а затем как их отобразить на LCD индикаторе. Теперь вы знаете, где находитесь!

Надеюсь статья оказалась полезной. Оставляйте комментарии!


На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.


  • 2016-08-07zuka bash

    Очень понравилась статья, несколько дней пытался сделать похожее а здесь как угадали мои мысли.
    Широту-долготу и время показывает после инициализации модуля, с датой приходится подождать.
    Часовой пояс просто прибавляют и может появиться 25 часов, 26, и даже отрицательное.
    При выводе дня пропущена команда вывода "0" если меньше 10.

Сообщить об ошибке