объясните как оно работает...
- Войдите на сайт для отправки комментариев
Ср, 07/02/2018 - 17:30
в общем столкнулся с таким кодом (библиотека TinyGPS.h)
for (unsigned long start = millis(); millis() - start < 1000;) {
while (skgps.available()){
char c = skgps.read();
if (gps.encode(c)) newData = true;
}
}
в общем оно работает нормально - НО при этом всё остальное виснет намертво.... тоесть если кроме этого запроса есть еще код с лупе - он тупит неимеверно
я попробовал заменил его на простой вызов по таймеру
if(tm5>interval5) { timer5=tm; /* Каждую секунду парсим GPS данные*/
while (skgps.available()){ char c = skgps.read(); if (gps.encode(c)) newData = true; }
}
так весь код в лупе работает нормально, НО теперь данные с жпс не идут - они тупят дико и получает 1 раз из 20 информацию....
вот теперь я както в замешательстве...
это получается 1й вариан висит пока всё не сделает сам... а во втором он просто не успевает сделать что требуется?...
подскажите решение, как забирать и парсить ЖПС и при этом не тормозить остального......
всё сам разобрался
неудачный пример использовал - оно тупо зациклено долбило порт пока не получала данные и продолжала долбить - вот и жрало всё.... переписал немного - теперь хоть не вешает так дико, хотя есть небольшие тормоза
надо както менять алгоритм чтобы она не ждала, когда в порте чтото появится , а отправляла запрос ЖПС приемнику на отдачу даннх и получала их сразу... вот только как это сделать - кто может подсказать библиотеку или пример как работать с ЖПС приемником в режиме запрос-ответ
//пс приемник полноценный, с компа можно настройки менять как удобно
первый пример - абсолютный бред (неужели из библиотеки)?
Второй вариант - по таймеру - много лучше. Чтобы не терялось, надо просто интервал делать поменьше, скажем 50мс. При неблокирующем коде частый опрос ничего тормозить не будет.
Я тоже как-то мучался с TinyGPS.h. Пока низкий апгрейд рейт, как у Вас в коде - 1сек, то можно было терпеть. Проапгрейдил приемник - стал получать 5Гц, да и бодрейт поднял, - пришлось отказаться от этой библиотеки, и писать свой парсер. Там ничего сложного, надо просто разобраться в формате предложений RMC и если нужна высота, то GGA. Остальное поотрубать нафиг.
первый пример - абсолютный бред (неужели из библиотеки)?
Мне пришлось вообще отдельный микропроцессор ставить на обработку ЖПС, но зато получил бонус в виде получения данных по i2c.
да не, в первом примере он при кажом входе читает порт и парсит всё, что есть
и если удачно - тода дает на выход результат
и судя по логу - он это делает раз 20 с векунду (328й столько успевает пройти раз)
и только с 15-25й прохода он видимо получает с порта верную последовательность (полный набор данных) и тогда дает 1 секунду отдыха....
вот в этом и проблема - ведь я же не знаю, когда в порт придет полный пакет нужных данных, чтобы его считать весь и сразу а не бесконечно ждать и парсить....
первый пример - абсолютный бред (неужели из библиотеки)?
Мне пришлось вообще отдельный микропроцессор ставить на обработку ЖПС, но зато получил бонус в виде получения данных по i2c.
а можно по подробней об этом...
а то у меня валяется кучка айтюни13 - я думаю её же хватит жпс читать и парсить... былобы очень удобно по i2c или spi получать готовый результат - и нагрузки на основной проц не будет )
а то у меня валяется кучка айтюни13 - я думаю её же хватит жпс читать и парсить... былобы очень удобно по i2c или spi получать готовый результат - и нагрузки на основной проц не будет )
ТОлько чего рассказывать не знаю :) Все просто как борщ: мониторим сериал, пришли данные, определяем что за предложение и парсим в зависимости от того. Свежими данными заполняем структуру данных, куда включены все координаты. Выставляем флаг что есть новые данные. Основной проц идет в своем лупе, смотрит - флаг на ноге висит, забирает данные по ай2си. Данные ушли - снимаем флаг. Усе. :)
да не, в первом примере он при кажом входе читает порт и парсит всё, что есть
и если удачно - тода дает на выход результат
и судя по логу - он это делает раз 20 с векунду (328й столько успевает пройти раз)
если судить по тому коду. что у вас приведен - все СОВСЕМ не так.
в лупе запрос
if (millis() - gps_start > 1000) { Serial.println("GPS read"); /* */ if (readgps()){ gps_start = millis(); // Получаем координаты gps.f_get_position(&lat, &lon, &age); if(latp<1 || lonp<1 ) {latp=lat; lonp=lon;} // Получаем дату и время // gps.crack_datetime(&year, &month, &day, &hour, &minutes, &second, &hundredths, &age); //test test(); /*перерассчет одометров и скорости по жпс*/ } }вне лупа функция запроса
bool readgps(){ while (skgps.available()){ int b = skgps.read(); //в TinyGPS есть ошибка: не обрабатываются данные с \r и \n if('\r' != b){ if (gps.encode(b))return true; } } return false; }ну и лог частоты вызовов и результата
а где же вот это:
for (unsigned long start = millis(); millis() - start < 1000;) { while (skgps.available()){ char c = skgps.read(); if (gps.encode(c)) newData = true; } }хотелось бы посмотреть в глаза тому. кто встроил сюда FOR.
Это не вы. случайно?
не, я с инета код взял первый попавшийся
только начал с жпс разбираться
ELITE, в том коде, что вы привели в #9 - никакого криминала нет, его частые вызовы программу вряд ли нагруэают - они только проверяют наличие данных от GPS и при отсуствии - сразу отваливаются. Если надо сделать вызовы пореже - достаточно в первый из кодов вставить буквально одну строку...
только начал с жпс разбираться
да тут не в GPS надо разбираться - это стандартный обмен по сериал, как любой другой.
Так все-таки непонятно - откуда взялся код с FOR ? Раньше вы писали, что это из библиотеки, теперь приводите куски. где FOR нет...
Так все-таки непонятно - откуда взялся код с FOR ? Раньше вы писали, что это из библиотеки, теперь приводите куски. где FOR нет...
ELITE, в том коде, что вы привели в #9 - никакого криминала нет, его частые вызовы программу вряд ли нагруэают - они только проверяют наличие данных от GPS и при отсуствии - сразу отваливаются. Если надо сделать вызовы пореже - достаточно в первый из кодов вставить буквально одну строку...
это код из другого источника и работает куда лучше, чем из примера библиотеки
но и он создает задержки при выполнении
подскажиче какую строчку можно дописать, дабы улучшить работу?
подскажиче какую строчку можно дописать, дабы улучшить работу?
например, для опроса не чаще 50мс
int interval; if (millis() - gps_start > interval) { Serial.println("GPS read"); /* */ gps_start = millis(); if (readgps()){ interval =1000; // Получаем координаты gps.f_get_position(&lat, &lon, &age); if(latp<1 || lonp<1 ) {latp=lat; lonp=lon;} // Получаем дату и время // gps.crack_datetime(&year, &month, &day, &hour, &minutes, &second, &hundredths, &age); //test test(); /*перерассчет одометров и скорости по жпс*/ } else { interval =50; } }спасибо, работает, но тормоза в работе запроса то весьма большие
обработка почти 200 мс длится
хотя не, не работает - то нормально то 3-4-5 и более секунд не может получить данные...
чем быстрее и чаще идет опрос порта - тем стабильнее получает данные с приемника
может быть буфер порта переполняется?...
//и да, если фажно, использую SoftwareSerial для подключения приемника на портах А0 А1 мк 328й
спасибо, работает, но тормоза в работе запроса то весьма большие - обработка почти 200 мс длится
Ну, это я не трогал. Зато после запроса - 1 секунда паузы. Если данные не обязательно обновлять раз в секунду - можете паузу после чтения данных поставить и побольше.
хотя не, не работает - то нормально то 3-4-5 и более секунд не может получить данные...
чем быстрее и чаще идет опрос порта - тем стабильнее получает данные с приемника
Попробуйте менять интервал опроса - вместо 50мс поставьте 30 или 20. Чаще нет смысла. Да и вообще, не думаю, что это связано. Если вы возьмете свой лог из сообщения #9 - у вас тоже были паузы по 20-40мс
я попробовал смотреть что идет с порта (байты)
и выяснил, что он ищет байт конца строки (10) и после него берет весь блок и дешифрует
но приемник то шлет 10 строк в секунду (по мануалу на мой 10гц)
при этом буфер порта всё время полный и идет со сдвигом
в результате при запросах с интервалом есть моменты, когда конец строки уже потерян или сдвинут и нет полной строки для считывания - вот на этом и проблема
думаю, что если както ощичать буфер перед каждым поиском нужного байта
но приемник то шлет 10 строк в секунду (по мануалу на мой 10гц)
хотя щас без задержек попробовал - выдает 5-7 ответов в секунду.
наверное надо делать реально uart-i2s на 13 тюньке и с неё забирать готовые данные
... бум учить как это теперь сделать )
хотя щас без задержек попробовал - выдает 5-7 ответов в секунду.
наверное надо делать реально uart-i2s на 13 тюньке и с неё забирать готовые данные
... бум учить как это теперь сделать )
#include <arduino.h> #include <Wire.h> //#include <TinyGPS.h> #include <SoftwareSerial.h> #define SLAVE_ADDRESS 4 #define DATA_LENGTH 19 #define DELAY 1 SoftwareSerial ss(2, 4); struct { float flat, flon, current_course, speed; unsigned int altitude; byte fixed_data = 0; } buffer; byte buffer_to_send [sizeof(buffer)]; byte text[100]; //сюда считываем NMEA строку для последующего парсинга bool new_data = 0; void setup() { Serial.begin(38400); ss.begin(38400); //GPS сконфигурирован под 38400, выдает только RMC и GGA Wire.begin(SLAVE_ADDRESS); Wire.onRequest(slaveTX); } void loop() { if (ss.available()) listen_uart(); if(new_data)data_to_buffer(); } void slaveTX() { //передаем buffer на мастер по i2c Wire.write(buffer_to_send, sizeof(buffer_to_send)); } void data_to_buffer() { cli(); memcpy(buffer_to_send, & buffer, sizeof(buffer_to_send)); sei(); new_data = 0; } void listen_uart() { if (ss.available() > 100) { while (ss.available())ss.read(); return; }//если больше 100байт - очищаем все int i = 0; byte buff; do { buff = ss.read(); } while (buff != 36); //читаем все до знака $ delay(1); do { if(i>99)return; text[i++] = ss.read(); delayMicroseconds(100);//ожидание прихода следующего байта } while (text[i - 1] != 42); //заполняем text[]прока не встретим * ss.read();ss.read(); //ложим болт на контрольную сумму if (text[4] == 'C') parse_rmc(); if (text[4] == 'A') parse_gga(); new_data = 1; } void parse_rmc() { byte count = 0; byte i = 0; do { if (text[i++] == ',') count++; } while (count < 2); text[i] == 'A' ? buffer.fixed_data = 1 : buffer.fixed_data = 0; Serial.print("fixed_data = "); Serial.print(buffer.fixed_data); do { if (text[i++] == ',') count++; } while (count < 3); buffer.flat = parse_coords(i); Serial.print(" flat = "); Serial.print(buffer.flat, 6); do { if (text[i++] == ',') count++; } while (count < 5); buffer.flon = parse_coords(i + 1); Serial.print(" flon = "); Serial.print(buffer.flon, 6); do { if (text[i++] == ',') count++; } while (count < 7); buffer.speed = parse_speed(i); buffer.speed = buffer.speed * 1.852; Serial.print(" speed = "); Serial.print(buffer.speed); do { if (text[i++] == ',') count++; } while (count < 8); buffer.current_course = parse_speed(i); Serial.print(" current_course = "); Serial.print(buffer.current_course); } void parse_gga() { byte count = 0; byte i = 0; do { if (text[i++] == ',') count++; } while (count < 9); int n = -1; do { n++; } while (text[i++] != '.'); i = i - n - 1; buffer.altitude = parse_value(i, n); //for( byte l = 0; l<n; l++)altitude+=(text[l+i]-48)*(unsigned int)(pow(10, n-l-1)+0.5); Serial.print(" alt = ");Serial.println(buffer.altitude); } long parse_value(byte i, byte n) { long value = 0; for (byte j = 0; j < n; j++) value = value * 10 + (text[i + j] - '0'); return value; } float parse_coords( byte i) { float coord = 0; coord = parse_value(i, 2); float minutes = parse_value(i + 2, 2); float after_dot = parse_value(i + 5, 4); minutes = minutes + after_dot / 10000.; coord = coord + minutes / 60.; return coord; } float parse_speed(byte i) { if (text[i] == 44)return 0; int n = -1; float res = 0; byte j = i; do { n++; } while (text[j++] != 46); res = parse_value(i, n); res = res + (text[i + n + 1] - '0') / 10.; return res; }Структура занимает 19 байт. На приемной стороне надо сформировать такую же структуру, ну и обращаться к ней соответствующе. Будут вопросы - спрашивайте. Я считал, что она на 10Гц работать должна, но все сериал.принт надо выкинуть.
Так же впервые столкнулся с gps, и целый день почти потратил на разбор того, почему данные читаются как бог пошлет. Посылал далеко и на долго. Чтение проходило один раз из 100-1000. Оказалось, что взял за основу неудачный пример криворукого блоггера.
Как и в одном из примеров ELITE, переменная для поиска начала строки была типа int.
Что интересно как часы вполне работает, т.к. все ресурсы МК тратятся на работу с gps и переодически фазы луны и мк совпадаю