В предыдущих статьях на нашем сайте мы уже рассматривали создание системы определения местоположения автомобиля на основе платы Arduino, GSM и GPS и отслеживание местоположения автомобиля на Google Maps с помощью Arduino. Также мы рассматривали систему предупреждения об авариях автомобиля на основе Arduino и акселерометра. В этой же статье мы постараемся объединить эти три проекта на основе платы MSP430G2 launchpad, GPS модуля и датчика вибрации, который будет использоваться для обнаружения аварии автомобиля.
Модуль датчика вибрации будет обнаруживать вибрацию автомобиля и передавать соответствующий сигнал на плату MSP430G2 Launchpad. Затем плата MSP430G2 будет считывать информацию с GPS модуля, обрабатывать ее и передавать на мобильный телефон пользователя с помощью GSM модуля. Также при обнаружении аварии автомобиля будет загораться светодиод. Местоположение аварии будет передаваться пользователю в виде ссылки на Google Map с указанием широты и долготы места аварии, полученных с GPS модуля. Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Необходимые компоненты
- Плата MSP430G2 LaunchPad (купить на AliExpress).
- GSM модуль SIM900 (купить на AliExpress).
- GPS модуль Ublox NEO-6M (купить на AliExpress).
- Модуль датчика вибрации (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- Макетная или перфорированная плата.
- Соединительные провода.
- Светодиод.
- Источники питания 3.3v, 5v и 12v.
Основные принципы работы с GPS модулем
GPS представляет собой глобальную систему навигации и определения положения (Global Positioning System) и используется для определения широты и долготы точки земного шара, а также определения всеобщего скоординированного времени (Universal Time Coordinated, UTC time). GPS модуль в нашем проекте будет использоваться для определения местоположения произошедшей аварии автомобиля. Он будет получать со спутников GPS каждую секунду координаты, время и дату. Он передает много различных строк, мы для извлечения необходимой нам информации будем использовать строку $GPGGA. Ранее на нашем сайте мы уже рассматривали извлечение координат из данной строки в аналогичном проекте на основе платы Arduino.
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 | Данные контрольной суммы |
Как видите, информации в строке $GPGGA достаточно много.
GSM модуль
SIM900 представляет собой GSM/GPRS модуль, способный работать в четырех диапазонах частот: 850/900/1800/1900MHz. Находит широкое применение среди энтузиастов электроники. Способен передавать голос, данные, SMS и отличается малым энергопотреблением.
Особенности модуля SIM900:
- построен на однокристальном процессоре с интегрированным ядром AMR926EJ-S;
- отличается малым размером;
- поддерживает технологии GSM/GPRS;
- способен работать в 4-х диапазонах частот.
Для использования GSM модулем используются AT команды.
С примерами использования подобных команд для управления GSM модулем вы можете ознакомиться в проектах по следующей ссылке. Для теста GSM модуля мы отправляем ему AT команду. Если с модулем все нормально, он нам ответит OK. Далее приведены некоторые из наиболее часто используемых AT команд.
ATE0 For echo off – отключение режима "эхо", то есть чтобы модуль не повторял в ответ команды, которые мы ему передаем
AT+CNMI=2,2,0,0,0 <ENTER> включение режима автоматического приема команд
ATD<Mobile Number>; <ENTER> осуществление вызова (ATD+919610126059;\r\n)
AT+CMGF=1 <ENTER> выбор текстового режима
AT+CMGS=”Mobile Number” <ENTER> назначение мобильного номера адресата
>>После этого мы можем писать наше сообщение
>>После написания сообщения
Ctrl+Z передаем команду сообщения (26 в десятичном формате).
ENTER=0x0d in HEX
Модуль датчика вибрации
В нашей системе обнаружения аварий автомобилей мы будем использовать модуль датчика вибрации, который будет обнаруживать вибрации и неожиданные "движения". На выходе датчика вибрации может использоваться логика HIGH или LOW в зависимости от типа данного модуля. В нашем проекте мы будем использовать датчик вибрации с выходной логикой HIGH. То есть всегда, когда данный датчик будет обнаруживать вибрацию, он будет подавать уровень HIGH на вход микроконтроллера.
Схема проекта
Схема устройства для обнаружения аварий и положения автомобиля на основе платы MSP430G2 представлена на следующем рисунке.
В данной схеме передающий контакт (Tx pin) GPS модуля непосредственно подключен к цифровому контакту P1_1 платы MSP430G2 Launchpad. Для питания GPS модуля используется напряжение 5v. С помощью библиотеки Software Serial мы будем использовать последовательную связь на контактах P_6 и P1_7 платы, то есть делать их контакты Rx и Tx – их мы будем использовать для связи с GSM модулем. Для питания GSM модуля будет использоваться напряжение 12 В.
Датчик вибрации подключен к контакту P1_3 платы. Для сигнализации об авариях в нашем проекте также используется светодиод.
Внешний вид собранной конструкции проекта показан на следующем рисунке.
Объяснение кода программы
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты. Для написания программы мы будем использовать среду Energia IDE, которая фактически является аналогом Arduino IDE.
Первым делом в коде программы подключим необходимые библиотеки и объявим используемые переменные.
1 2 3 4 5 6 7 8 9 |
#include <SoftwareSerial.h> SoftwareSerial GSM(P1_6, P1_7); // RX, TX float latitude=0; float logitude=0; #define led P1_0 const int vibrationSensor=PUSH2; int i=0; |
Функция SensorRead будет использоваться для считывания сигнала с датчика вибрации, она будет фильтровать незначительные и ложные вибрации.
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 |
#define count_max 25 char SensorRead(int pin) // read sw with debounce { char count_low=0,count_high = 0; do { delay(1); if (digitalRead(pin) == HIGH) { count_high++; count_low = 0; } else { count_high = 0; count_low++; } }while(count_low< count_max && count_high < count_max); if (count_low >= count_max) return LOW; else return HIGH; } |
В функции void loop() мы будем считывать сигнал с датчика вибрации, вызывать функцию gpsEvent() для считывания GPS координат и функцию Send() для передачи SMS с помощью GSM модуля.
1 2 3 4 5 6 7 8 9 10 11 |
void loop() { if(SensorRead(vibrationSensor) == HIGH) { digitalWrite(led, HIGH); gpsEvent(); Send(); digitalWrite(led, LOW); delay(2000); } } |
Функция gpsEvent() используется для считывания GPS строки с GPS модуля, извлечения из нее координат и преобразования их в десятичный формат.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void gpsEvent() { char gpsString[55]; char test[]="RMC"; i=0; while(1) { while (Serial.available()) //Serial incomming data from GPS { char inChar = (char)Serial.read(); gpsString[i]=inChar; //store incomming data from GPS to temparary string str[] i++; if (i < 4) { if(gpsString[i-1] != test[i-1]) //check for right string i=0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
int degree=0; degree=gpsString[16]-48; degree*=10; degree+=gpsString[17]-48; int minut_int=0; minut_int=gpsString[18]-48; minut_int*=10; minut_int+=gpsString[19]-48; int minut_dec=0; minut_dec+= (gpsString[21]-48)*10000; minut_dec+= (gpsString[22]-48)*1000; minut_dec+= (gpsString[23]-48)*100; minut_dec+= (gpsString[24]-48)*10; minut_dec+= (gpsString[25]-48); float minut= ((float)minut_int + ((float)minut_dec/100000.0))/60.0; latitude= ((float)degree + minut); |
И, наконец, функция Send() используется для передачи SMS на указанный номер пользователя.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void Send() { GSM.print("AT+CMGS="); GSM.print('"'); GSM.print("961****059"); // enter your Mobile number GSM.println('"'); delay(500); // GSM.print("Latitude:"); // GSM.println(latitude); GSM.println("Accident Happned"); delay(500); // GSM.print(" longitude:"); // GSM.println(logitude); GSM.println("Click On link to see Location"); GSM.print("http://maps.google.com/maps?&z=15&mrt=yp&t=k&q="); GSM.print(latitude,6); GSM.print("+"); GSM.print(logitude,6); GSM.write(26); delay(4000); } |
Исходный код программы
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 |
#include <SoftwareSerial.h> SoftwareSerial GSM(P1_6, P1_7); // RX, TX float latitude=0; float logitude=0; #define led P1_0 const int vibrationSensor=PUSH2; int i=0; #define count_max 25 char SensorRead(int pin) // read sw with debounce { char count_low=0,count_high = 0; do { delay(1); if (digitalRead(pin) == HIGH) { count_high++; count_low = 0; } else { count_high = 0; count_low++; } }while(count_low< count_max && count_high < count_max); if (count_low >= count_max) return LOW; else return HIGH; } void setup() { GSM.begin(9600); Serial.begin(9600); GSM.println("AT"); delay(1000); GSM.println("ATE0"); delay(1000); GSM.println("AT+CMGF=1"); pinMode(led , OUTPUT); digitalWrite(led, LOW); pinMode(vibrationSensor, INPUT_PULLUP); } void loop() { if(SensorRead(vibrationSensor) == HIGH) { digitalWrite(led, HIGH); gpsEvent(); Send(); digitalWrite(led, LOW); delay(2000); } } void gpsEvent() { char gpsString[55]; char test[]="RMC"; i=0; while(1) { while (Serial.available()) //если есть на входе GPS данные { char inChar = (char)Serial.read(); gpsString[i]=inChar; //сохраняем поступающие данные GPS во временную строку str[] i++; if (i < 4) { if(gpsString[i-1] != test[i-1]) //проверяем правильная ли строка i=0; } if(i>50) { int degree=0; degree=gpsString[16]-48; degree*=10; degree+=gpsString[17]-48; int minut_int=0; minut_int=gpsString[18]-48; minut_int*=10; minut_int+=gpsString[19]-48; int minut_dec=0; minut_dec+= (gpsString[21]-48)*10000; minut_dec+= (gpsString[22]-48)*1000; minut_dec+= (gpsString[23]-48)*100; minut_dec+= (gpsString[24]-48)*10; minut_dec+= (gpsString[25]-48); float minut= ((float)minut_int + ((float)minut_dec/100000.0))/60.0; latitude= ((float)degree + minut); degree=0; degree=gpsString[30]-48; degree*=10; degree+=gpsString[31]-48; minut_int=0; minut_int=gpsString[32]-48; minut_int*=10; minut_int+=gpsString[33]-48; minut_dec=0; minut_dec+= (gpsString[35]-48)*10000; minut_dec+= (gpsString[36]-48)*1000; minut_dec+= (gpsString[37]-48)*100; minut_dec+= (gpsString[38]-48)*10; minut_dec+= (gpsString[39]-48); minut= ((float)minut_int + ((float)minut_dec/100000.0))/60.0; logitude= ((float)degree + minut); i=0; Serial.flush(); return; } } } } void Send() { GSM.print("AT+CMGS="); GSM.print('"'); GSM.print("961****059"); // введите ваш номер мобильного телефона GSM.println('"'); delay(500); // GSM.print("Latitude:"); // GSM.println(latitude); GSM.println("Accident Happned"); delay(500); // GSM.print(" longitude:"); // GSM.println(logitude); GSM.println("Click On link to see Location"); GSM.print("http://maps.google.com/maps?&z=15&mrt=yp&t=k&q="); GSM.print(latitude,6); GSM.print("+"); GSM.print(logitude,6); GSM.write(26); delay(4000); } |