Глобальная система навигации и определения положения (Global Positioning System, GPS) позволяет определить с высокой точностью широту и долготу любой точки земного шара. Также в сигналах от спутников GPS содержится и информация о всеобщем скоординированном времени (Universal Time Coordinated, UTC).
В данной статье мы рассмотрим подключение GPS модуля к плате STM32F103C8 (Blue Pill) для определения координат местоположения и отображения их на экране ЖК дисплея 16x2.
Ранее на нашем сайте мы рассматривали ряд других проектов, в которых использовались технологии GPS:
- подключение GPS модуля к микроконтроллеру AVR;
- GPS часы на Arduino Uno;
- отслеживание местоположения автомобиля на Google Maps с помощью Arduino, ESP8266 и GPS;
- GPS спидометр на Arduino и OLED дисплее;
- подключение GPS модуля к Raspberry Pi.
Необходимые компоненты
- Плата разработки STM32F103C8 (STM32 Blue Pill) (купить на AliExpress).
- GPS модуль GY-NEO6MV2 XM37-1612 (купить на AliExpress).
- ЖК дисплей 16x2 (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
GPS модуль
В нашем проекте мы будем использовать GPS модуль GY-NEO6MV2 XM37-1612. Данный модуль содержит 4 контакта: +5V, GND, TXD и RXD. Благодаря наличию контактов TXD и RXD его достаточно просто можно подключить к последовательному порту платы STM32F103C8.
Внешний вид модуля GY-NEO6MV2 XM37-1612 показан на следующем рисунке.
GPS модуль передает данные в формате NMEA, который состоит из нескольких строк. Нам из этих строк будет нужна только строка, начинающаяся с $GPGGA (Global Positioning System Fix Data). Она содержит координаты, время и ряд другой полезной информации. Более подробно о структуре данной строки и извлечении из нее координат можно прочитать в этой статье.
Пример данных строки $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 | Данные контрольной суммы |
Ранее, в других проектах на нашем сайте с использованием модуля GPS мы для извлечения координат из строки $GPGGA считали в ней количество запятых, начиная с ее начала, и, таким образом, находили в ее структуре необходимые нам широту и долготу. В этом же проекте мы для извлечения необходимой нам информации из данной строки будем использовать библиотеку TinyGPSPlus.
Контакты STM32F103C8 для подключения GPS модуля
Распиновка платы STM32F103C8 приведена на следующем рисунке.
Подключать GPS модуль к плате мы будем через последовательный порт связи. На представленном рисунке контакты последовательных портов платы STM32F103C8 (Blue Pill) обозначены синим цветом (PA9-TX1,PA10- RX1, PA2-TX2, PA3- RX2, PB10-TX3, PB11- RX3). Всего в плате STM32F103C8 три последовательных канала связи.
Схема проекта
Схема подключения GPS модуля к плате STM32F103C8 (Blue Pill) представлена на следующем рисунке.
Схема соединений между платой STM32F103C8 и GPS модулем приведена в следующей таблице.
GPS модуль | Плата STM32F103C8 |
RXD | PA9 (TX1) |
TXD | PA10 (RX1) |
+5V | +5V |
GND | GND |
Схема соединений между платой STM32F103C8 и ЖК дисплеем 16х2 приведена в следующей таблице.
№ контакта ЖК дисплея | Обозначение контакта ЖК дисплея | Контакт платы STM32 |
1 | Ground (Gnd) | Ground (G) |
2 | VCC | 5V |
3 | VEE | средний контакт потенциометра |
4 | Register Select (RS) | PB11 |
5 | Read/Write (RW) | Ground (G) |
6 | Enable (EN) | PB10 |
7 | Data Bit 0 (DB0) | No Connection (NC) |
8 | Data Bit 1 (DB1) | No Connection (NC) |
9 | Data Bit 2 (DB2) | No Connection (NC) |
10 | Data Bit 3 (DB3) | No Connection (NC) |
11 | Data Bit 4 (DB4) | PB0 |
12 | Data Bit 5 (DB5) | PB1 |
13 | Data Bit 6 (DB6) | PC13 |
14 | Data Bit 7 (DB7) | PC14 |
15 | LED Positive | 5V |
16 | LED Negative | Ground (G) |
Внешний вид собранной конструкции проекта представлен на следующем рисунке.
Объяснение программы для платы STM32
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Плату STM32F103C8 мы будем программировать с помощью Arduino IDE через USB порт. Перед загрузкой кода программы в плату отключите ее контакты TX и RX от GPS модуля, а после завершения загрузки кода заново их подключите.
Перед написанием кода программы необходимо скачать библиотеку TinyGPSPlus по следующей ссылке с GitHub. После этого ее можно установить в Arduino IDE используя пункт меню Sketch -> Include Library-> Add .zip Library.
Первым делом в программе подключим необходимые библиотеки, укажем контакты, к которым подключен ЖК дисплей, и создадим объект для работы с ним.
1 2 3 4 |
#include <LiquidCrystal.h> #include <TinyGPS++.h> const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); |
Затем создадим объект gps класса TinyGPSPlus.
1 |
TinyGPSPlus gps; |
Далее, в функции void setup(), установим последовательную связь с GPS модулем с помощью команды Serial1.begin(9600). В данной команде Serial1 означает, что мы используем последовательный порт Serial 1 (контакты PA9, PA10) платы STM32F103C8.
1 |
Serial1.begin(9600); |
Затем покажем на экране ЖК дисплея приветственное сообщение.
1 2 3 4 5 6 |
lcd.begin(16,2); lcd.print("Circuit Digest"); lcd.setCursor(0,1); lcd.print("STM32 with GPS"); delay(4000); lcd.clear(); |
Далее, в функции void loop (), мы будем принимать значения широты и долготы от GPS модуля и проверять их на корректность. Принятые данные мы будем выводить в окно монитора последовательной связи и на экран ЖК дисплея.
Проверку корректности GPS данных мы будем производить с помощью следующей команды:
1 |
loc_valid = gps.location.isValid(); |
Затем мы будем принимать данные широты.
1 |
lat_val = gps.location.lat(); |
А затем данные долготы.
1 |
lng_val = gps.location.lng(); |
Если будут приниматься неправильные данные, то в окно монитора последовательной связи мы будем выводить “*****”, а на экран ЖК дисплея – “waiting”.
1 2 3 4 5 6 7 8 9 10 |
if (!loc_valid) { lcd.print("Waiting"); Serial.print("Latitude : "); Serial.println("*****"); Serial.print("Longitude : "); Serial.println("*****"); delay(4000); lcd.clear(); } |
Если принятые данные корректны, то мы будем выводить их в окно монитора последовательной связи и на экран ЖК дисплея.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
lcd.clear(); Serial.println("GPS READING: "); Serial.print("Latitude : "); Serial.println(lat_val, 6); lcd.setCursor(0,0); lcd.print("LAT:"); lcd.print(lat_val,6); Serial.print("Longitude : "); Serial.println(lng_val, 6); lcd.setCursor(0,1); lcd.print("LONG:"); lcd.print(lng_val,6); delay(4000); |
В следующей функции мы обеспечиваем задержку, необходимую для корректного считывания данных, и наблюдаем за данными в последовательном порту.
1 2 3 4 5 6 7 8 9 |
static void GPSDelay(unsigned long ms) { unsigned long start = millis(); do { while (Serial1.available()) gps.encode(Serial1.read()); } while (millis() - start < ms); } |
Определение широты и долготы с помощью GPS модуля и платы STM32
После сборки схемы и загрузки программы в плату STM32 поместите GPS модуль на открытое пространство для уверенного приема сигналов. В некоторых случаях необходимо подождать несколько минут для того, чтобы модуль GPS начал устойчивый прием сигналов. Когда модуль GPS начнет прием сигналов ее встроенный светодиод начнет мигать, а принятые координаты будут отображаться на экране ЖК дисплея.
Проверить принятые широту и долготу вы можете с помощью карт Google или Яндекс. Если вы будете делать это с помощью карт Google, то при включенном GPS модуле нажмите в них на синюю точку, в результате чего вам будет показан ваш адрес со значениями широты и долготы как показано на следующем рисунке.
Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Исходный код программы (скетча)
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 |
#include <LiquidCrystal.h> //Library for using LCD display functions #include <TinyGPS++.h> //Library for using GPS functions const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //LCD pins connected with STM32 LiquidCrystal lcd(rs, en, d4, d5, d6, d7); TinyGPSPlus gps; //Object gps for class TinyGPSPlus void setup() { Serial1.begin(9600); //Begins Serial comunication at Serial Port 1 at 9600 baudrate lcd.begin(16,2); //Sets display in 16x2 Mode lcd.print("Circuit Digest"); lcd.setCursor(0,1); lcd.print("STM32 with GPS"); delay(4000); lcd.clear(); } void loop() { GPSDelay(1000); unsigned long start; double lat_val, lng_val; bool loc_valid; lat_val = gps.location.lat(); //Gets the latitude loc_valid = gps.location.isValid(); lng_val = gps.location.lng(); //Gets the longitude if (!loc_valid) //Excecutes when invalid data is received from GPS { lcd.print("Waiting"); Serial.print("Latitude : "); Serial.println("*****"); Serial.print("Longitude : "); Serial.println("*****"); delay(4000); lcd.clear(); } else //Excutes when valid data is received from GPS { lcd.clear(); Serial.println("GPS READING: "); Serial.print("Latitude : "); Serial.println(lat_val, 6); //Prints latitude at Serial Monitor lcd.setCursor(0,0); lcd.print("LAT:"); lcd.print(lat_val,6); //Prints latitude at LCD display Serial.print("Longitude : "); Serial.println(lng_val, 6); //Prints longitude at Serial monitor lcd.setCursor(0,1); lcd.print("LONG:"); lcd.print(lng_val,6); //Prints longitude at LCD display delay(4000); } } static void GPSDelay(unsigned long ms) //Delay for receiving data from GPS { unsigned long start = millis(); do { while (Serial1.available()) gps.encode(Serial1.read()); } while (millis() - start < ms); } |