Помогите разобраться с разбором строки
- Войдите на сайт для отправки комментариев
Пнд, 11/06/2018 - 05:51
Добрый день!
Есть ардуино нано и модуль gps+glonass.
Модуль отправляет координаты и т.д. в таком виде:
$GPGGA,013306.40,5553.95206,N,03734.64397,E,1,08,1.16,243.9,M,13.3,M,,*5E
$GPRMC,013306.50,A,5553.95206,N,03734.64397,E,0.041,,110618,,,A*7A
$GPVTG,,T,,M,0.041,N,0.075,K,A*24
$GPRMC,013306.70,A,5553.95207,N,03734.64396,E,0.071,,110618,,,A*7B
$GPVTG,,T,,M,0.071,N,0.132,K,A*25
$GPRMC,013306.80,A,5553.95207,N,03734.64396,E,0.058,,110618,,,A*7F
$GPVTG,,T,,M,0.058,N,0.108,K,A*27
$GPRMC,013306.90,A,5553.95207,N,03734.64395,E,0.121,,110618,,,A*72
$GPVTG,,T,,M,0.121,N,0.223,K,A*22
Необходимо вытащить из строки $GPGGA, содержащиеся в ней координаты и время.
Пробовал использовать вот такой код
#include <SoftwareSerial.h> SoftwareSerial mySerial(4, 5); // RX, TX char st = '0'; String time; String lat; char lat_s; String lon; char lon_s; char qual; String sats; String alt; boolean renew = false; void setup() { Serial.begin(9600); mySerial.begin(9600); } String readVal() { boolean rot = true; String buffer; while (rot) { int b = mySerial.read(); if ( (('0' <= (char)b) && ((char)b <= '9')) || ((char)b == '.') || (('A' <= (char)b) && ((char)b <= 'Z')) ) { // считываем значения, содержащие цифры, буквы и точку buffer += (char)b; } if ( (char)b == ',' ) rot = false; // заканчиваем читать, когда встречаем запятую } return buffer; } void loop() // run over and over { int b = mySerial.read(); // Serial.write(b); //Serial.write(st); switch ( st ) { // перебираем состояния case '0': if ('&' == b) st = '1'; else st = '0'; break; case '1': if ('G' == b) st = '2'; else st = '0'; break; case '2': if ('P' == b) st = '3'; else st = '0'; break; case '3': if ('G' == b) st = '4'; else st = '0'; break; case '4': if ('G' == b) st = '5'; else st = '0'; break; case '5': if ('A' == b) st = '6'; else st = '0'; break; case '6': if ('.' == b) { // распознали $GPGGA { time = readVal(); lat = readVal(); lat.replace('.', ','); lat_s = (char)readVal()[0]; lon = readVal(); lon.replace('.', ','); lon_s = (char)readVal()[0]; qual = (char)readVal()[0]; sats = readVal(); readVal(); // skip empty alt = readVal(); } renew = true; st = '0'; } else st = '0'; break; } //if (renew) { // Serial.print("Time: " + time + " Lat/Lon: " + lat_s + lat + " " + lon_s + lon + "\r\n"); // renew = false; //} delay(10); }
При просмотре переменной b вижу такую ерунду, данные искажаются и соответственно распозновать нечего.
Подправьте пожалуйста где и что не так.
b должно быть типа char для такого сравнения.
Строки начинаются на $, а ты ищешь &
b должно быть типа char для такого сравнения.
26
int
b = mySerial.read();
Правильно понимаю, что эту строку надо поменять так
26
(char)
b = mySerial.read();
Строки начинаются на $, а ты ищешь &
Опечатался, когда код возвращал в исходное состояние. Я пробовал начинать искать не с $, а сразу с буквы G
И Главное, что я не понимаю почему так искажаются данные в переменной B.
Что-то я невнимательно посмотрел. Вы еще и не проверяете перед чтением имеется ли что-то в буфере mySerial , что не очень правильно. Вот стандартный пример работы с Serial/SoftSerial:
Конечно, чтение значения прямо в char - это дискуссионный момент, но я предпочитаю делать так, чтобы потом чесать в голове, раздумывая чего это у меня println() хренотень выводит вместо символа.
Суть этого когда в том, чтобы "на лету" читать данные из сериала.
И все равно не понимаю, почему оно не работает.
На интуитивном уровне мне кажется, что у парсера проблемы с опознаванием конца старой / начала новой строки. И вообще он подозрительный. Например, вот это: case '6': if ('.' == b) - после $GPGGA нет точки.
Так же не знаю, насколько правомерно возвращать указатель на локальную (уничтожаемую при завершении) строку в функции readVal(). С классом String не работал, но нормальные функции работы с памятью так не делают.
Словом, тут в каждой строчке мина заложена. Так что начните с простого - правильной работы с mySerial и четкого определения начала новой строки. При отладочной печати как-нибудь их выделяйте что ли... Я вот, к примеру, не понимаю, что вы считаете неправильным выводом. Как написана программа - так и выводится.
Так же не знаю, насколько правомерно возвращать указатель на локальную (уничтожаемую при завершении) строку в функции readVal(). С классом String не работал, но нормальные функции работы с памятью так не делают.
Там не указатель возвращается, а экземпляр класса. С точки зрения памяти там всё норм - внутри класса всё обрабатывается, есть конструкторы копирования, оператор присваивания и т.п. - так что всё норм.
А чего не пользуетесь готовыми библиотеками для разбора Какая-нибудь TinyGPS распарсит всё за милую душу.
Это малая часть задач, а в ардуино мини не так много памяти
Так можно же взять библиотеку и просто выбросить их неё лишнее. Сама-то по себе она работает и всё нормально парсит.
Это малая часть задач, а в ардуино мини не так много памяти
Ну надо прямо заметить, что Ардуино Мини отнюдь не любая задача по плечу.
И, даже если некая задача можект быть реализована на Ардуино Мини, то это отнюдь не означает, что любым программистом.