парсинг NMEA
- Войдите на сайт для отправки комментариев
Сб, 13/10/2018 - 17:51
Здравствуйте, подскажите, как мне из определенной строки вытащить необходимые мне данные. Есть два сообщения, $GPGGA и $GPRMC, мне нужно из сообщения GPGGA вытащить седьмое число после запятой,т.е кол-во спутников, а из сообщения GPRMC вытащить скорость, что является тоже седьмым числом после запятой.Как распознать тип сообщения я вроде как сообразил.Вот код.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(4, 3); // RX, TX
char st = '0';
char b;
boolean renew = false;
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}
void loop()
{
char b = mySerial.read();
switch ( st ) // перебираем состояния
{
case '0': if('$' == b) st = '1';
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
st = '0';
}
breake;
}
Не знаю правильно так или нет, но работает. А вот дальше загвоздка, как теперь посчитать семь запятых в этих сообщениях?
не мучайтесь
https://github.com/ericbarch/arduino-libraries/blob/master/NMEA/nmea.h
а на каких скоростях работает библиотека? На 9600 слишком медленно, пробовал пделать на библиотеке TINYGPS+, очень медленно информация поступает из ардуины. Мне надо чтобы она принимала с GPS по UART на скорости 57600(5 раз в секунду), а эта библиотека работает на 9600.
она не работает с портом, данные вы читаете сами, она только парсит строку на составляющие.
скорость зависит от приемника, некоторые умеют перенастаиваться.
для приёмника BU-353 GLONASS, ND105C
Команда изменения частоты на 10 ГЦ (десять раз в секунду): $PMTK220,100*2F
Команда изменения частоты на 5 ГЦ (пять раз в секунду): $PMTK220,200*2C
Максимальная частота фиксации координат для данного GPS-чипсета 10 ГЦ.
ясно, спасибо за наводку. Только я не очень понимаю как ею пользоваться. Это же не библиотека, просто скопировать код и вставить в пой скетч, а дальше выбрать необходимые мне параметры для расшифровки?
как включать читайте тут на форуме, мне лень расписывать все это, да хоть что-то вы должны сделать :)
пример про скорость там-же https://github.com/ericbarch/arduino-libraries/blob/master/NMEA/examples/gprmc_speed/gprmc_speed.pde
Не пойму как этим добром пользоваться.Тупо скопировал все, потом ниже ставлю свой код.
#ifndef nmea_h #define nmea_h #include "Arduino.h" #include <SoftwareSerial.h> SoftwareSerial ss(4,3); #define ALL 0 // connect to all datatypes #define GPRMC 1 // connect only to GPRMC datatype #define MTR 1.0 // meters per meter #define KM 0.001 // kilometers per meter #define MI 0.00062137112 // miles per meter #define NM 0.00053995680 // nautical miles per meter #define PARSEC 0.000000000000 // parsecs per meter (approximation) #define MPS 0.51444444 // meters-per-second in one knot #define KMPH 1.852 // kilometers-per-hour in one knot #define MPH 1.1507794 // miles-per-hour in one knot #define KTS 1.0 // knots in one knot #define LIGHTSPEED 0.000000001716 // lightspeeds in one knot class NMEA { public: NMEA(int connect); // constructor for NMEA parser object; parse sentences of GPRMC or all datatypes. int decode(char c); // parse one character received from GPS; returns 1 when full sentence found w/ checksum OK, 0 otherwise float gprmc_utc(); // returns decimal value of UTC term in last full GPRMC sentence char gprmc_status(); // returns status character in last full GPRMC sentence ('A' or 'V') float gprmc_latitude(); // signed degree-decimal value of latitude terms in last full GPRMC sentence float gprmc_longitude(); // signed degree-decimal value of longitude terms in last full GPRMC sentence float gprmc_speed(float unit); // speed-on-ground term in last full GPRMC sentence float gprmc_course(); // track-angle-made-good term in last full GPRMC sentence float gprmc_distance_to(float latitude, float longitude, float unit); // returns distance from last-known GPRMC position to given position float gprmc_course_to(float latitude, float longitude); // returns initial course in degrees from last-known GPRMC position to given position char* sentence(); // returns last received full sentence as zero terminated string int terms(); // returns number of terms (including data type and checksum) in last received full sentence char* term(int t); // returns term t of last received full sentence as zero terminated string float term_decimal(int t); // returns the base-10 converted value of term[t] in last full sentence received int libversion(); // returns software version number of NMEA library private: // properties int _gprmc_only; float _gprmc_utc; char _gprmc_status; float _gprmc_lat; float _gprmc_long; float _gprmc_speed; float _gprmc_angle; char f_sentence[100]; char* f_term[30]; int f_terms; int _terms; char _sentence[100]; char* _term[30]; int n; int _gprmc_tag; int _state; int _parity; int _nt; float _degs; // methods float distance_between (float lat1, float long1, float lat2, float long2, float units_per_meter); float initial_course(float lat1, float long1, float lat2, float long2); int _dehex(char a); float _decimal(char* s); }; #endif void setup() { Serial.begin(9600); // устанавливаем последовательное соединение ss.begin(9600); } void loop() { if(ss.available()) { Serial.print(_gprmc_utc); } }При компиляции выдает ошибку _gprmc_utc was not declareted in this scope.
Мда... Три года на форуме и до сих пор не научились пользоваться гитхабом и подключать библиотеки.
http://arduino.ru/forum/obshchii/kak-postich-nepostizhimoe#comment-388080
Ну библиотеку подключить не сложно если она в ZIP архиве, а в таком виде я даже и не знаю как ее задействовать.
Жесть - это такая холоднокатаная листовая сталь с защитным покрытием, сделаная по ГОСТ Р 52204-2004
Ну библиотеку подключить не сложно если она в ZIP архиве, а в таком виде я даже и не знаю как ее задействовать.
зачем тебе библиотека ??? я тебе нормальную ссылку дал, там человек все разжевал уже дальше некуда...
так, разобрался, выводит то что надо. Но тут выводится информация только из сообщения GPRMC, а мне надо еще кол-во спутников, которое зашифровано в сообщении GPGGA. Как быть?)
так, разобрался, выводит то что надо. Но тут выводится информация только из сообщения GPRMC, а мне надо еще кол-во спутников, которое зашифровано в сообщении GPGGA. Как быть?)
даже НЕ смешно ...
не ну правда, я не спец по работе с GPS,можно извлечь как то кол-во спутников? Оно зашифровано в GPGGA.
не ну ты прикалываешься что-ли? я тоже не спец, по второй ссылке в гугле находится
да это я згаю, как мне применив вот это https://github.com/ericbarch/arduino-libraries/tree/master/NMEA получить кол-во спутников. Как я понял эта библиотека расшифровывает только строку GPRMC, или я не прав?
да это я згаю, как мне применив вот это https://github.com/ericbarch/arduino-libraries/tree/master/NMEA получить кол-во спутников. Как я понял эта библиотека расшифровывает только строку GPRMC, или я не прав?
тоесть ту ссылку, что я дал ты упорно читать не хочешь...
да... это именно сталь с защитным покрытием :(
«Жесть» — дебютный фильм петербургского кинорежиссёра Дениса Нейманда 2006 года по сценарию Константина Мурзенко в жанре психологического триллера.
Вот это ближе к теме и ближе к триллеру
NMEA(int connect); // constructor for NMEA parser object; parse sentences of GPRMC or all datatypes. int decode(char c); // parse one character received from GPS; returns 1 when full sentence found w/ checksum OK, 0 otherwise float gprmc_utc(); // returns decimal value of UTC term in last full GPRMC sentence char gprmc_status(); // returns status character in last full GPRMC sentence ('A' or 'V') float gprmc_latitude(); // signed degree-decimal value of latitude terms in last full GPRMC sentence float gprmc_longitude(); // signed degree-decimal value of longitude terms in last full GPRMC sentence float gprmc_speed(float unit); // speed-on-ground term in last full GPRMC sentence float gprmc_course(); // track-angle-made-good term in last full GPRMC sentence float gprmc_distance_to(float latitude, float longitude, float unit); // returns distance from last-known GPRMC position to given position float gprmc_course_to(float latitude, float longitude); // returns initial course in degrees from last-known GPRMC position to given position char* sentence(); // returns last received full sentence as zero terminated string int terms(); // returns number of terms (including data type and checksum) in last received full sentence char* term(int t); // returns term t of last received full sentence as zero terminated string float term_decimal(int t); // returns the base-10 converted value of term[t] in last full sentence received int libversion(); // returns software version number of NMEA libraryНет тут кол-ва спутников.
И все умники замолчали.
И все умники замолчали.
А, хренли тебе писать когда ты сам с собой болтаешь ...
тебе сюда
http://arduino.ru/forumy/ishchu-ispolnitelya
Как быть?)
Купить хороший аудиопровод из безкислородной меди, и повеситься на нём нахрен от такой жизни.
ИЧСХ, тема называется "парсинг NMEA". А внутри - поиск быдлотек(тм) чужими руками :)
Полазив по форуму, нашел код, переделал неиного, все работает, но слишком медленно, частота обновления информации 1сек, а мне надо выводить 5 раз в секунду. Код такой.
#include <SoftwareSerial.h> static const int RXPin = 4, TXPin = 3; static const uint32_t GPSBaud = 57600; SoftwareSerial ss(RXPin, TXPin); void setup(void) { Serial.begin(9600); ss.begin(GPSBaud); } // // Эта функция принимает символ из Serial и возвращает // указатель на полученную строку или NULL, если строка // ещё не получена. // Строка всегда начинается с $ и заканчивается \r или \n // static const int MAX_LEN = 140; // 120 - максимальная длина строки - надо посмотреть правильное значение в описании протокола! char * getStrFromSerial(void) { static bool waitingForStrBegin = true; // истина, если мы ждём начала строки ($) static char strBuf[MAX_LEN]; // буфер для строки static int ptr = 0; // индекс свободного байта в буфере // // Если буфер переполнился, печатаем сообщение и начинаем ждать новую строку // if (ptr >= MAX_LEN) { Serial.println("*** Error: Too long string!!!"); ptr = 0; waitingForStrBegin = true; return NULL; } // // Если в Serial ничего нет - выходим // А если есть, то читаем 1 символ // if (!ss.available()) return NULL; const char c = ss.read(); // // Если мы ждём начала строки, то сравинваем // прочитанный символ с '$', если равен - начало найдено // if (waitingForStrBegin) { if (c == '$') { ptr = 0; strBuf[ptr++] = c; waitingForStrBegin = false; } return NULL; } // // Если прочитанный символ - перевод строки или возврат каретки // то считаем, что строка закончилась. Возвращаем её, // а сами готовимся ждать новую. // if (c == '\r' || c == '\n') { strBuf[ptr] = '\0'; waitingForStrBegin = true; return strBuf; } // // Просто записываем символ в строку // strBuf[ptr++] = c; return NULL; } // // Читаeм долготу и широту, складывает в lon и lat // Возвращает true, если прочитала и false если нет // bool readLatLon( int & num_sat) { // // getStrFromSerial() вернёт строку, полученную из Serial // или NULL, если строка ещё пока не получена // const char * str = getStrFromSerial(); // // Если строка ещё не получена, выходим // if (str == NULL) return false; // // Если строка не начинается с "$GPGGA", // то она нам не нужна выходим // const char * prefix = "$GPGGA"; if (strncmp(str, prefix, strlen(prefix))) return false; // // Ищем первую запятую в строке str // char * comma = strchr(str, ','); // // Если не нашли (строка кривая пришла?) - выходим // if (!comma) return false; // // со следующего символа просле запятой идёт числоа - широта // // // Ищем вторую запятую после начала числа-широты // comma = strchr(comma+1, ','); // сначала ищем первую запятую 2 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 4 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 5 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 6 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 7 if (!comma) return false; // почему-то не нашли :(((( num_sat = atoi(comma+1); // // Вроде всё // return true; } bool readspeed(int & speed, double & time) { // // getStrFromSerial() вернёт строку, полученную из Serial // или NULL, если строка ещё пока не получена // const char * str = getStrFromSerial(); // // Если строка ещё не получена, выходим // if (str == NULL) return false; // // Если строка не начинается с "$GPRMC", // то она нам не нужна выходим // const char * prefix = "$GPRMC"; if (strncmp(str, prefix, strlen(prefix))) return false; // // Ищем первую запятую в строке str // char * comma = strchr(str, ','); // // Если не нашли (строка кривая пришла?) - выходим // if (!comma) return false; // // со следующего символа просле запятой идёт числоа - широта // time = atof(comma+1); // // Ищем вторую запятую после начала числа-широты // comma = strchr(comma+1, ','); // сначала ищем первую запятую 2 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 4 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 5 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 6 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 7 if (!comma) return false; // почему-то не нашли :(((( speed = atoi(comma+1); // // Вроде всё // return true; } void loop(void) { // // Широта и долгота // int num_sat; int speed; double time; // Читаем широту и долготу и если успешно прочитались, печатаем // if (readLatLon( num_sat)) { //Serial.print("Latitude: "); //Serial.println(lat, 5); Serial.print("num_sat: "); Serial.println(num_sat); } if (readspeed( speed, time)) { Serial.print("time: "); Serial.println(time, 2); Serial.print("speed: "); Serial.println(speed); } }Запуская вот этот код, информация выводится как положено, каждые 200мс.
#include <SoftwareSerial.h> SoftwareSerial ss(4,3); char incomingByte; void setup() { Serial.begin(9600); // устанавливаем последовательное соединение ss.begin(57600); } void loop(){ if(Serial.available())ss.write(Serial.read()); if(ss.available())Serial.write(ss.read()); }Я так понимаю, первый код слишком тяжелый, задача всего то вывести 2 параметра из двух строк от GPS приемника.Может кто что подскажет по оптимизации? Пробовал библиотеку NMEA, она глючит с моим OLED дисплеем, как только прописываю строки #include <nmea.h> и NMEA gps(GPRMC) дисплей не запускается. Поэтому прихожу к тому, что строки эти надо вручную обрабатывать, проверить пришла ли нужная строка и вытаскивать необходимое значение, причем число типа int.
и что - неужели при такой вот передаче параметров последующий принт печатает ненулевые значения num_sat, time и speed? - не верю
if (readLatLon( num_sat)) { //Serial.print("Latitude: "); //Serial.println(lat, 5); Serial.print("num_sat: "); Serial.println(num_sat); } if (readspeed( speed, time)) { Serial.print("time: "); Serial.println(time, 2); Serial.print("speed: "); Serial.println(speed); }может вы ошиблись при выкладывании скетча в конфу? - не должно это работать
Нет не ошибся, передает каждые 200мс. Не знаю как картинку приложить.
Это уже оцинкованая жесть !!!
Полазив по форуму, нашел код, переделал неиного, все работает, но слишком медленно, частота обновления информации 1сек, а мне надо выводить 5 раз в секунду. Код такой.
********
== Какой нафиг "полазив по форуму" ? Эту ссылку я тебе тут два дня назад дал !
пост#8
Запуская вот этот код, информация выводится как положено, каждые 200мс.
Я так понимаю, первый код слишком тяжелый, задача всего то вывести 2 параметра из двух строк от GPS приемника.Может кто что подскажет по оптимизации?
=== Все нормально работает скетч !!!
Когда себя прооптимизируешь, то может поймешь, что модуль отдает информацию с частотй 1 Гц, а если нужно быстрее, то нужно перепрограммировать сам модуль !
пост#3
но жесть крепка и не пробиваема ...
нашел код, переделал неиного, все работает
Так, ну я не буду комментировать как Вы его
изуродовалипеределали, только "работает" он у Вас "как повезёт". Повезёт - найдёт строку, не повезёт - пропустит. Нормально сработает только в том случае, если $GPGGA будет чётной строкой, а $GPRMC - нечётной. Если чётность не такая - она пропустит соответсвующие строки.и что - неужели при такой вот передаче параметров последующий принт печатает ненулевые значения num_sat, time и speed?
Там же ссылки.
Модуль я перепрошил на частоту 5Гц, он работает, данные на этой частоте приходят как и положено, в мониторе порта это хорошо видно.
Модуль я перепрошил на частоту 5Гц, он работает, данные на этой частоте приходят как и положено, в мониторе порта это хорошо видно.
пост #32 прочитай, посмотри как идут строки, подумай, прими решение .
(поменяй очередность запросов в лупе)
(поменяй очередность запросов в лупе)
Ох, напрасно Вы так! Он ведь посчитает, что это должно решить проблему и ... в общем, нехорошо о Вас подумает :)
и что - неужели при такой вот передаче параметров последующий принт печатает ненулевые значения num_sat, time и speed?
Там же ссылки.
Чувствую. что мне надо это повторить... Чета казалось, что если параметр функции - ссылка, то и передавать надо ссылки, а не переменные
Вы правы, выводится 2 раза кол-во спутников, поэтому и не работает на нужной частоте 5Гц. Но что можно предпринять для выхода из этой ситуации?
(поменяй очередность запросов в лупе)
Ох, напрасно Вы так! Он ведь посчитает, что это должно решить проблему и ... в общем, нехорошо о Вас подумает :)
тогда я расстроюсь и сделаю себе харакири :-))
но похоже он это так и не попробывал сделать... тупо долбится с двойным выводом спутников ...
а то убралсябы один лишний вывод спутников, глядишь и с частотой наладилось ... пока наладилось бы ...
Вы правы, выводится 2 раза кол-во спутников, поэтому и не работает на нужной частоте 5Гц. Но что можно предпринять для выхода из этой ситуации?
например искать $GPRMC и $GPGGA в одной и той же функции. В начале функции проверяем, с чего начинается строка - и в зависимости от результата извлекаем либо то, либо другое. Заодно и дублирования своего жуткого кода с поиском запятых избавитесь
Вы имеете ввиду поменять порядок строк с переменными int speed,int num_sat и double time ?
Не злитесь, ну не спец я в этом парсинге, понимаю как должно быть, а реализовать не могу.
gzp13 - при ответе либо начинайте ответ с имени собеседника, либо цитируйте часть сообщения, на которое отвечаете.
Никто особо и не злится, а ответ на твой вопрос "что делать" см. в посте #24. Там всё написано.
Хорошо, идею я понял. Как мне в данном коде реализовать проверку приходящтх строк в одной функции .
#include <SoftwareSerial.h> static const int RXPin = 4, TXPin = 3; static const uint32_t GPSBaud = 57600; SoftwareSerial ss(RXPin, TXPin); void setup(void) { Serial.begin(9600); ss.begin(GPSBaud); } // // Эта функция принимает символ из Serial и возвращает // указатель на полученную строку или NULL, если строка // ещё не получена. // Строка всегда начинается с $ и заканчивается \r или \n // static const int MAX_LEN = 140; // 120 - максимальная длина строки - надо посмотреть правильное значение в описании протокола! char * getStrFromSerial(void) { static bool waitingForStrBegin = true; // истина, если мы ждём начала строки ($) static char strBuf[MAX_LEN]; // буфер для строки static int ptr = 0; // индекс свободного байта в буфере // // Если буфер переполнился, печатаем сообщение и начинаем ждать новую строку // if (ptr >= MAX_LEN) { Serial.println("*** Error: Too long string!!!"); ptr = 0; waitingForStrBegin = true; return NULL; } // // Если в Serial ничего нет - выходим // А если есть, то читаем 1 символ // if (!ss.available()) return NULL; const char c = ss.read(); //Serial.print(c); // // Если мы ждём начала строки, то сравинваем // прочитанный символ с '$', если равен - начало найдено // if (waitingForStrBegin) { if (c == '$') { ptr = 0; strBuf[ptr++] = c; waitingForStrBegin = false; } return NULL; } // // Если прочитанный символ - перевод строки или возврат каретки // то считаем, что строка закончилась. Возвращаем её, // а сами готовимся ждать новую. // if (c == '\r' || c == '\n') { strBuf[ptr] = '\0'; waitingForStrBegin = true; return strBuf; } // // Просто записываем символ в строку // strBuf[ptr++] = c; return NULL; } // // Читаeм долготу и широту, складывает в lon и lat // Возвращает true, если прочитала и false если нет // bool readLatLon(double & time,double & num_sat, double & date ) { // // getStrFromSerial() вернёт строку, полученную из Serial // или NULL, если строка ещё пока не получена // const char * str = getStrFromSerial(); // // Если строка ещё не получена, выходим // if (str == NULL) return false; // // Если строка не начинается с "$GNGLL", // то она нам не нужна выходим // const char * prefix = "$GPGGA"; if (strncmp(str, prefix, strlen(prefix))) return false; // // Ищем первую запятую в строке str // char * comma = strchr(str, ','); // // Если не нашли (строка кривая пришла?) - выходим // if (!comma) return false; // // со следующего символа просле запятой идёт числоа - широта // time = atof(comma+1); // // Ищем вторую запятую после начала числа-широты // comma = strchr(comma+1, ','); // сначала ищем первую запятую 2 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 4 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 6 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7 if (!comma) return false; // почему-то не нашли :(((( // // со следующего символа просле запятой идёт числоа - долгота // num_sat = atof(comma+1); // // Вроде всё // return true; } void loop(void) { // // Широта и долгота // double time,num_sat, date; // // Читаем широту и долготу и если успешно прочитались, печатаем // if (readLatLon(time,num_sat, date)) { //Serial.print("time: "); Serial.println(time, 2); Serial.print("num_sat: "); Serial.println(num_sat, 0); Serial.print("date: "); Serial.println(date, 0); } }Я правильно записал строку 76?
Время и кол-во спутников извлекаем из строки &GPGGA. Это получилось. Теперь ине надо извлечь дату из строки GPRMC.
А вот как организовать проверку, что пришла строка &GPRMC? Я так понимаю нельзя в функцию bool readLatLon добавить условие проверки
Предполагаю, что встречаются одинаковые названия функций.
что мешает сделать вот так:
const char * prefix = "$GPGGA"; const char * prefix2 = "$GNGLL"; if ( ! strncmp(str, prefix, strlen(prefix))) { // извлекаем данные из строки $GPGGA } else if ( ! strncmp(str, prefix2, strlen(prefix2))) { // извлекаем данные из строки $GNGLL } else return false;Спасибо Вам b707, направили на нужную мысль, получилось то что я хотел. Всем большое спасибо за помощь.
так, возникла еще проблемка. Скорость с GPS поступает в узлах в час, знаю что для перевода в км/час надо скорость умножить на 1.852, т.е запись будет speed=atof(comma+1)*1.852
Но мой GPS занижает скорость на 4км/час, т.е мне надо прибавить еще 4км/час.Но тогда при нулевой скорости у меня на дисплее будет индицироваться 4км/час. Думаю что коррекцию скорости надо сделать после 30км/час, посмотрите код.Коррекция начинается со строки 173-184. Но при этих строках искажаются все данные на выходе(((
#include <SoftwareSerial.h> static const int RXPin = 4, TXPin = 3; static const uint32_t GPSBaud = 57600; SoftwareSerial ss(RXPin, TXPin); byte a=0; byte b=0; void setup(void) { Serial.begin(9600); ss.begin(GPSBaud); } // // Эта функция принимает символ из Serial и возвращает // указатель на полученную строку или NULL, если строка // ещё не получена. // Строка всегда начинается с $ и заканчивается \r или \n // static const int MAX_LEN = 140; // 120 - максимальная длина строки - надо посмотреть правильное значение в описании протокола! char * getStrFromSerial(void) { static bool waitingForStrBegin = true; // истина, если мы ждём начала строки ($) static char strBuf[MAX_LEN]; // буфер для строки static int ptr = 0; // индекс свободного байта в буфере // // Если буфер переполнился, печатаем сообщение и начинаем ждать новую строку // if (ptr >= MAX_LEN) { Serial.println("*** Error: Too long string!!!"); ptr = 0; waitingForStrBegin = true; return NULL; } // // Если в Serial ничего нет - выходим // А если есть, то читаем 1 символ // if (!ss.available()) return NULL; const char c = ss.read(); //Serial.print(c); // // Если мы ждём начала строки, то сравинваем // прочитанный символ с '$', если равен - начало найдено // if (waitingForStrBegin) { if (c == '$') { ptr = 0; strBuf[ptr++] = c; waitingForStrBegin = false; } return NULL; } // // Если прочитанный символ - перевод строки или возврат каретки // то считаем, что строка закончилась. Возвращаем её, // а сами готовимся ждать новую. // if (c == '\r' || c == '\n') { strBuf[ptr] = '\0'; waitingForStrBegin = true; return strBuf; } // // Просто записываем символ в строку // strBuf[ptr++] = c; return NULL; } // // Читаeм долготу и широту, складывает в lon и lat // Возвращает true, если прочитала и false если нет // bool readLatLon(double & time,double & num_sat, double & date , double & speed ) { // // getStrFromSerial() вернёт строку, полученную из Serial // или NULL, если строка ещё пока не получена // const char * str = getStrFromSerial(); // // Если строка ещё не получена, выходим // if (str == NULL) return false; // // Если строка не начинается с "$GPGGA или GPRMC", // то она нам не нужна выходим // const char * prefix = "$GPGGA"; const char * prefix2 = "$GPRMC"; if ( ! strncmp(str, prefix, strlen(prefix))) { // Ищем первую запятую в строке str // char * comma = strchr(str, ','); // // Если не нашли (строка кривая пришла?) - выходим // if (!comma) return false; // // со следующего символа просле запятой идёт числоа - широта // time = atof(comma+1); // // Ищем вторую запятую после начала числа-широты // comma = strchr(comma+1, ','); // сначала ищем первую запятую 2 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 4 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 6 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7 if (!comma) return false; // почему-то не нашли :(((( // // со следующего символа просле запятой идёт числоа - долгота // num_sat = atof(comma+1); return true; } // Вроде всё // else if ( ! strncmp(str, prefix2, strlen(prefix2))) { char * comma = strchr(str, ','); // // Если не нашли (строка кривая пришла?) - выходим // if (!comma) return false; // // со следующего символа просле запятой идёт числоа - широта // time = atof(comma+1); // // Ищем вторую запятую после начала числа-широты // comma = strchr(comma+1, ','); // сначала ищем первую запятую 2 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 4 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // сначала ищем первую запятую 6 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7 if (!comma) return false; // почему-то не нашли :(((( speed=atof(comma+1)*1.852; // переводим скорость в км/час comma = strchr(comma+1, ','); // сначала ищем первую запятую 8 if (!comma) return false; // почему-то не нашли :(((( comma = strchr(comma+1, ','); // теперь ищем вторую запятую 9 if (!comma) return false; // почему-то не нашли :(((( date=atof(comma+1); //return true; } else return false; } void loop(void) { double time,num_sat, date,speed; if (speed>30 && a==0) //выполняем коррекцтю скорости { //при скорости более 30км/час добавляем 3 км/час speed=speed+3; //и далее скорость растет на 1км/час a=1; //т.к приемник GPS занижает скорость на км/час b=0; } if (speed<29 && b==0) // при скорости менее29 км/час { // коррекцию убираем speed=speed-3; //чтобы при нулевой скорости на дисплее был нуль b=1; a=0; } //Читаем время,кол-во спутников,дату,скорость если успешно прочитались, печатаем if (readLatLon(time,num_sat, date,speed)) { Serial.print("time: "); Serial.println(time, 2); Serial.print("num_sat: "); Serial.println(num_sat, 0); Serial.print("date: "); Serial.println(date, 0); Serial.print("speed: "); Serial.println(speed, 0); } }$GPVTG, x.x, T x.x, M x.x, N x.x, K *hh <CR><LF>
1. Направление курса в градусах, T
2. Магнитное склонение в градусах, М
3. Скорость над поверхностью (SOG) в узлах, N = узлы
4. Скорость над поверхностью (SOG) в км/ч, К = км/ч
5. hh Контрольная сумма строки (обязательно)
Пример сообщения:
$GPVTG,217.5,T,208.8,M,000.00,N,000.01,K*4C
Но мой GPS занижает скорость на 4км/час, т.е мне надо прибавить еще 4км/час.
чем измерено ?
не спидометром автомобиля часом ?
Именно им) Даже если и спидометр автомобиля завышает, все равно хотелось бы привести и ту и эту скорость к одной величине.