Существует немало GPS-модулей и шилдов для Arduino, но многие из них довольно недешевы. Если вам в вашем проекте по каким-то причинам нужен GPS, самым дешевым (не в ущерб качеству!) из известных мне вариантов будет модуль на базе чипа NEO-6M. На AliExpress такие модули продаются за 230 рублей (4 $) с учетом доставки в Россию. Давайте же попробуем разобраться, как с ними работать.
Примечание: Как правило, GPS не работает в доме. Чтобы поймать сигнал от спутников, с модулем нужно выйти на улицу или на балкон, или хотя бы положить его рядом с окном. Кроме того, GPS может плохо ловить в облачную погоду. Учтите также, что даже на открытом воздухе и в хорошую погоду при первом включении модулю может потребоваться несколько минут на инициализацию.
К Arduino модуль подключается не сложно, так как питается он от 5 В, а данные передает по UART на скорости 9600 бод. Когда модуль находит достаточное количество спутников для определения своего местоположения, он начинает мигать синим светодиодом и передавать по UART раз в секунду что-то вроде:
$GPVTG,228.26,T,,M,2.578,N,4.774,K,A*39
$GPGGA,160709.00,5546.792,N,03749.475,E,1,07,4.00,172.3,M,13.3,M,,*5C
$GPGSA,A,3,13,20,18,30,21,15,,,,,,,6.45,3.95,5.11*02
Тут на глаз несложно найти текущие координаты (5546.79229,N и 03749.47557,E), а также дату (170617) и время в UTC (160709). Цифры в конце строк после звездочки — это контрольные суммы. Стоит отметить, что если модуль еще не определил свои GPS-координаты, он передает по UART немного другие данные. Подробное описание того, как декодировать все эти данные можно найти в документе под названием U-blox 6 Receiver Description Including Protocol Specification [PDF] .
Несмотря на то, что написать свой парсер достаточно просто, их написано и отлажено уже достаточно, чтобы не тратить на это свое время. Лично я воспользовался библиотекой TinyGPSPlus . Код прошивки:
#include <SoftwareSerial.h>
#include «LiquidCrystal_I2C.h»
#include «TinyGPS++.h»
const int DELAY = 100 ;
const int SWITCH_TIME = 5000 ;
LiquidCrystal_I2C lcd ( 0x3F , 16 , 2 ) ;
SoftwareSerial gps_serial ( A3, A2 ) ; /* RX, TX */
TinyGPSPlus gps_parser ;
void setup ( )
{
Serial. begin ( 9600 ) ;
gps_serial. begin ( 9600 ) ;
lcd. begin ( ) ;
}
String twoDigits ( int x ) {
if ( x < 10 ) return «0» + String ( x ) ;
else return String ( x ) ;
}
int currentModeTime = 0 ;
bool showLocation = false ;
void loop ( ) {
while ( gps_serial. available ( ) > 0 ) {
char temp = gps_serial. read ( ) ;
Serial. write ( temp ) ;
gps_parser. encode ( temp ) ;
}
String lat = «Unknown » ;
String lng = «location » ;
if ( gps_parser. location . isValid ( ) ) {
lat = «Lat: » + String ( gps_parser. location . lat ( ) , 6 ) ;
lng = «Lng: » + String ( gps_parser. location . lng ( ) , 6 ) ;
}
String date = «Unknown date » ;
if ( gps_parser. date . isValid ( ) ) {
date = twoDigits ( gps_parser. date . day ( ) ) + «/» +
twoDigits ( gps_parser. date . month ( ) ) + «/» +
String ( gps_parser. date . year ( ) ) + » » ;
}
String time = «Unknown time » ;
if ( gps_parser. time . isValid ( ) ) {
time = twoDigits ( gps_parser. time . hour ( ) ) + «:» +
twoDigits ( gps_parser. time . minute ( ) ) + «:» +
twoDigits ( gps_parser. time . second ( ) ) + » UTC » ;
}
if ( showLocation ) {
lcd. setCursor ( 0 , 0 ) ;
lcd. print ( lat ) ;
lcd. setCursor ( 0 , 1 ) ;
lcd. print ( lng ) ;
} else { // show date and time
lcd. setCursor ( 0 , 0 ) ;
lcd. print ( date ) ;
lcd. setCursor ( 0 , 1 ) ;
lcd. print ( time ) ;
}
delay ( DELAY ) ;
currentModeTime + = DELAY ;
if ( currentModeTime >= SWITCH_TIME ) {
lcd. clear ( ) ;
showLocation = ! showLocation ;
currentModeTime = 0 ;
}
}
Соответствующее устройство в действии:
Работа с использованным здесь экранчиком ранее была подробно описана в заметке Об использовании экранчиков 1602 с I2C-адаптером .
В общем, к обычно, ничего супер сложного. Полную версию исходников к этой заметке вы найдете на GitHub .