В этой статье мы рассмотрим устройство на основе платы Arduino Uno для отслеживания местоположения автомобиля (транспортного средства) с использованием технологий GPS и GSM.
Отслеживание местоположения автомобиля представляет собой процесс определения его GPS координат: широты (Latitude) и долготы (Longitude). Эта функция находит широкое применение в современном мире: в службах такси, транспортных компаниях, для школьных автобусов, для поиска украденных автомобилей и т.д.
Необходимые компоненты
- Плата Arduino Uno (купить на AliExpress).
- GSM модуль (купить на AliExpress).
- GPS модуль (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- Соединительные провода.
- Источник питания с напряжением 5 В.
Принципы работы GPS модуля
GPS (Global Positioning System) представляет собой систему глобального позиционирования, с помощью которой можно определить широту и долготу любой точки на Земле, а также точное время в этой точке (UTC time - Universal Time Coordinated). GPS модуль будет основным устройством в нашем проекте. Данный модуль принимает координаты от спутников каждую секунду. Вместе с координатами осуществляется прием времени и даты.
GPS передает данные, идентифицирующие местоположение, в реальном времени. Но вместе с этими данными он передает и очень много других данных в формате NMEA – смотрите приведенный ниже рисунок. NMEA содержит несколько строк (предложений) – нам из всей этой совокупности данных будет нужна всего лишь одна строка. Эта строка начинается с $GPGGA и содержит координаты, время и другую полезную информацию. Эти данные относятся к фиксированным данным глобального позиционирования (Global Positioning System Fix Data).
Мы можем извлечь нужные нам данные из строки $GPGGA при помощи подсчета запятых в строке. К примеру, если вы нашли строку $GPGGA и сохранили ее в массиве, то широта может быть найдена в нем после двух запятых, а долгота – после четырех запятых. После извлечения значения широты и долготы можно поместить в другие массивы.
Приведем пример $GPGGA строки с расшифровкой:
$GPGGA,104534.000,7791.0381,N,06727.4434,E,1,08,0.9,510.4,M,43.9,M,,*47
$GPGGA,HHMMSS.SSS,latitude,N,longitude,E,FQ,NOS,HDP,altitude,M,height,M,,checksum data
В следующей таблице представлен перевод (описание) этих данных GPS.
Идентификатор | Описание |
$GPGGA | Фиксированные данные системы глобального позиционирования |
HHMMSS.SSS | Время в формате: час минута секунда и миллисекунда |
Latitude | Широта (координата) |
N | Направление: N=North (север), S=South (юг) |
Longitude | Долгота (координата) |
E | Направление: E= East (восток), W=West (запад) |
FQ | Данные фиксированного качества (Fix Quality Data) |
NOS | Номер использованного спутника |
HPD | Фактор снижения точности при определении положения в горизонтальной плоскости (Horizontal Dilution of Precision) |
Altitude | Высота над уровнем моря |
M | Meter (метр) |
Height | Height (высота) |
Checksum | Данные контрольной суммы |
Работа схемы
Схема устройства представлена на следующем рисунке.
Контакт Tx (передача) GPS модуля непосредственно подсоединен к цифровому контакту 10 Arduino. С использованием специальной библиотеки для последовательной передачи данных мы можем задействовать последовательную связь на контакте 10, благодаря этому стандартный последовательный порт Arduino на контактах 0 и 1 мы можем задействовать для подключения GSM модуля. Напряжение питания 12 Вольт используется для питания GPS и GSM модулей. Контакты данных ЖК дисплея D4, D5, D6 и D7 подключены к контактам 5, 4, 3 и 2 of Arduino. Контакты управления ЖК дисплея RS и EN подключены к контактам 2 и 3 Arduino, а контакт RW замкнут на землю. Потенциометр используется для установки яркости или контрастности ЖК дисплея.
Плата Arduino используется управления всеми процессами в схеме, включая управление GPS приемником и GSM модулем. GPS приемник используется для определения координат автомобиля, GSM модуль – для передачи координат пользователю при помощи SMS. На ЖК дисплее отображается статус текущих операций или координаты. В нашем проекте мы использовали GPS модуль SKG13BL и GSM модуль SIM900A.
Структурная схема работы устройства показана на следующем рисунке.
Когда наше устройство будет собрано мы можем установить его в автомобиль и подать на него питание. Затем нам необходимо передать SMS “Track Vehicle” на устройство, размещенное на нашем автомобиле. Также мы можем использовать префикс (#) или суффикс (*), к примеру, #Track Vehicle* для того чтобы правильно идентифицировать начало и конец строки.
Принятое сообщение принимается GSM модулем, подсоединенным к системе, и передается затем в Arduino. Плата Arduino считывает его и извлекает из него главное (значащее) сообщение. После этого производится сравнение с заранее определенными (хранящимися в программе) сообщениями. Если фиксируется совпадение, то плата Arduino считывает координаты при помощи извлечения строки $GPGGA из данных, передаваемых GPS модулем. Затем эта строка обрабатывается и данные (координаты автомобиля) передаются пользователю с помощью GSM модуля.
Исходный код программы
В программе первым делом следует подключить необходимые библиотеки и инициализировать контакты для последовательной связи и взаимодействия с ЖК дисплеем. Программная библиотека для последовательной связи (Software Serial Library) позволяет задействовать последовательную связь на контактах 10 и 11 Arduino (мы будем использовать только контакт 10).
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
#include <SoftwareSerial.h>
SoftwareSerial gps(10,11); // RX, TX
char str[70];
String gpsString="";
... ....
.... ....
Объявленный массив str[70] будет использоваться для хранения принятого сообщения от GSM модуля, а строка gpsString – для хранения строки с GPS данными. char *test=”$GPGGA” будет использоваться для сравнения "правильной" строки, которая будет нам необходима для координат.
После этого в программе необходимо инициализировать порт последовательной связи (стандартный), ЖК дисплей, GSM и GPS модули и показать приветственное сообщение на ЖК дисплее.
void setup()
{
lcd.begin(16,2);
Serial.begin(9600);
gps.begin(9600);
lcd.print("Vehicle Tracking");
lcd.setCursor(0,1);
... ....
.... ....
В функции loop мы будем осуществлять прием сообщения и GPS строки.
void loop()
{
serialEvent();
if(temp)
{
get_gps();
tracking();
}
}
Функции void init_sms и void send_sms() будут использоваться для инициализации и передачи сообщений. В функции init_sms необходимо использовать правильный 10-значный номер мобильного телефона.
Функция void get_gps() будет использоваться для извлечения координат из принятой строки с данными GPS.
Функция void gpsEvent() будет использоваться для приема GPS данных в Arduino.
Функция serialEvent() будет использоваться для приема сообщений от GSM модуля и сравнения принятого сообщения с заранее определенным сообщением (Track Vehicle).
void serialEvent()
{
while(Serial.available())
{
if(Serial.find("Track Vehicle"))
{
temp=1;
break;
}
... ....
Функция инициализации ‘gsm_init()’ используется для инициализации и конфигурирования GSM модуля, где сначала проверяется работоспособен ли GSM модуль и соединен ли он с сетью с помощью ‘AT’ команд. Если модуль ответил OK значит он готов к работе. Система будет проверять GSM модуль до тех пор пока не получит ответ ‘OK’. Затем выключается режим ECHO при помощи передачи ATE0 команды, иначе GSM модуль будет повторять все принятые команды. Затем проверяется доступность сети при помощи команды ‘AT+CPIN?’, если в модуль вставлена SIM карта и на ней присутствует PIN, то модуль ответит +CPIN: READY. Эта проверка будет осуществляться системой до тех пор пока сеть не будет найдена. Более подробно все эти процессы можно посмотреть в представленном видео. Также более подробно процессы взаимодействия GSM модуля с платой Arduino описаны в статье про беспроводную доску объявлений с использованием GSM и Arduino.
Далее представлен полный текст программы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
#include <LiquidCrystal.h> LiquidCrystal lcd(7, 6, 5, 4, 3, 2); #include <SoftwareSerial.h> SoftwareSerial gps(10,11); // RX, TX на контактах 10 и 11 //String str=""; char str[70]; String gpsString=""; char *test="$GPGGA"; String latitude="No Range "; String longitude="No Range "; int temp=0,i; boolean gps_status=0; void setup() { lcd.begin(16,2); Serial.begin(9600); gps.begin(9600); lcd.print("Vehicle Tracking"); lcd.setCursor(0,1); lcd.print(" System "); delay(2000); gsm_init(); lcd.clear(); Serial.println("AT+CNMI=2,2,0,0,0"); lcd.print("GPS Initializing"); lcd.setCursor(0,1); lcd.print(" No GPS Range "); get_gps(); delay(2000); lcd.clear(); lcd.print("GPS Range Found"); lcd.setCursor(0,1); lcd.print("GPS is Ready"); delay(2000); lcd.clear(); lcd.print("System Ready"); temp=0; } void loop() { serialEvent(); if(temp) { get_gps(); tracking(); } } void serialEvent() { while(Serial.available()) { if(Serial.find("Track Vehicle")) { temp=1; break; } else temp=0; } } void gpsEvent() { gpsString=""; while(1) { while (gps.available()>0) // проверка последовательных данных от GPS { char inChar = (char)gps.read(); gpsString+= inChar; // сохранение данных от GPS в строке gpsString i++; if (i < 7) { if(gpsString[i-1] != test[i-1]) //проверка на фразу $GPGGA { i=0; gpsString=""; } } if(inChar=='\r') { if(i>65) { gps_status=1; break; } else { i=0; } } } if(gps_status) break; } } void gsm_init() { lcd.clear(); lcd.print("Finding Module.."); boolean at_flag=1; while(at_flag) { Serial.println("AT"); while(Serial.available()>0) { if(Serial.find("OK")) at_flag=0; } delay(1000); } lcd.clear(); lcd.print("Module Connected.."); delay(1000); lcd.clear(); lcd.print("Disabling ECHO"); boolean echo_flag=1; while(echo_flag) { Serial.println("ATE0"); while(Serial.available()>0) { if(Serial.find("OK")) echo_flag=0; } delay(1000); } lcd.clear(); lcd.print("Echo OFF"); delay(1000); lcd.clear(); lcd.print("Finding Network.."); boolean net_flag=1; while(net_flag) { Serial.println("AT+CPIN?"); while(Serial.available()>0) { if(Serial.find("+CPIN: READY")) net_flag=0; } delay(1000); } lcd.clear(); lcd.print("Network Found.."); delay(1000); lcd.clear(); } void get_gps() { gps_status=0; int x=0; while(gps_status==0) { gpsEvent(); int str_lenth=i; latitude=""; longitude=""; int comma=0; while(x<str_lenth) { if(gpsString[x]==',') comma++; if(comma==2) // извлечение широты из строки (после второй запятой) latitude+=gpsString[x+1]; else if(comma==4) // извлечение долготы из строки (после четвертой запятой) longitude+=gpsString[x+1]; x++; } int l1=latitude.length(); latitude[l1-1]=' '; l1=longitude.length(); longitude[l1-1]=' '; lcd.clear(); lcd.print("Lat:"); lcd.print(latitude); lcd.setCursor(0,1); lcd.print("Long:"); lcd.print(longitude); i=0;x=0; str_lenth=0; delay(2000); } } void init_sms() { Serial.println("AT+CMGF=1"); delay(400); Serial.println("AT+CMGS=\"+91**********\""); // используйте ваш десятизначный номер телефона здесь delay(400); } void send_data(String message) { Serial.println(message); delay(200); } void send_sms() { Serial.write(26); } void lcd_status() { lcd.clear(); lcd.print("Message Sent"); delay(2000); lcd.clear(); lcd.print("System Ready"); return; } void tracking() { init_sms(); send_data("Vehicle Tracking Alert:"); send_data("Your Vehicle Current Location is:"); Serial.print("Latitude:"); send_data(latitude); Serial.print("Longitude:"); send_data(longitude); send_data("Please take some action soon..\nThankyou"); send_sms(); delay(2000); lcd_status(); } |
Подскажите, пожалуйста, какой gps модуль Вы использовали?
Можно использовать Ublox NEO-6M