GPS модуль готовый ко всем неожиданностям.

gubilon
Offline
Зарегистрирован: 24.09.2018

Приветствую, форумчане. Имеется набор Arduino UNO и GPS приемник NEO-6M. Недавно возник такой вопрос по поводу GPS модуля. Суть в том, что взяв стандартный пример из библиотеке TinyGPSPlus столкнулся с тем, что при принятии неверных данных с модуля на com-порт лишь выводится надпись "INVALID". Но решил, что зачем смотреть на эту запись и решил, что просто буду останавливать подачу данных на порт. Но теперь возник вопрос, как сделать так, что если сломался модуль и посылаются те же координаты, что и были ранее(минкт 5-10 назад), чтоб и их не пускать к отображению и например выводить надпись "Wait"?

#include <TinyGPS++.h>
 
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
void setup()
   {
Serial.begin(115200);
ss.begin(GPSBaud);
Serial.println(F("DeviceExample.ino"));
Serial.println(F("A simple demonstration of TinyGPS++ with an attached GPS module"));
Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("by Mikal Hart"));
Serial.println();
   }
void loop()
   {
while (ss.available() > 0)
if (gps.encode(ss.read()))
displayInfo();
if (millis() > 5000 && gps.charsProcessed() < 10)
     {
Serial.println(F("No GPS detected: check wiring."));
while(true);
     }
   }  
void displayInfo()
    {
Serial.print(F("Location: "));
while (!gps.location.isValid())
     {
Serial.end();
     }
Serial.begin(115200);
delay(100);
Serial.print(gps.location.lat(), 6);
Serial.print(F(","));
Serial.print(gps.location.lng(), 6);
Serial.println();
}
 
sadman41
Offline
Зарегистрирован: 19.10.2016

А какое действие совершили бы вы, чтобы понять неизменна ваша номинальная зарплата в сентябре по отношению к майской или уменьшилась?

gubilon
Offline
Зарегистрирован: 24.09.2018

Я бы сравнил два значения между собой. Но встречный вопрос: а что бы вы делали, если бы устройство было частью системы,где за одну секунду приходят порядка десяти разных данных, при чем периоды прихода таких пачек хаотичны, но время и координаты одинаковы. Вот на таком моменте я и застрял.

sadman41
Offline
Зарегистрирован: 19.10.2016

Я бы начал с чесания головы в попытке формализовать описание ситуации "зависло". Что с вашей точки зрения аварийная ситуация - отсутствие обновления определенной метрики в течении некоего периода? Отсутствие обновления нескольких метрик? Незначительные колебания значения метрики в определенном диапазоне?

gubilon
Offline
Зарегистрирован: 24.09.2018

В этом случае аварийной ситуацией считаю такую, когда потеряна на время связь со спутниками, а данные приходят. В итоге тяжело выстраивать зависимость тех же погодных условий (температуры, давления,магнитных полей и более подробных данных). Я понимаю, что существует погрешность, но хотелось бы предусмотреть.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

gubilon пишет:

В этом случае аварийной ситуацией считаю такую, когда потеряна на время связь со спутниками, а данные приходят.

Ну, значит, и анализировать нужно спутники, а не координаты.

gubilon
Offline
Зарегистрирован: 24.09.2018

Хм. Спасибо. Я и не зудумался о такой возможности.Если я не ошибаюсь,то для нормальной работы нужна связь с 4 спутниками, то есть нужно проверять переменную sat.

sadman41
Offline
Зарегистрирован: 19.10.2016

При аварии кол-во спутников меняется при неизменности координат?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:

При аварии кол-во спутников меняется при неизменности координат?

Если этот вопрос ко мне - понятия не имею.

Я лишь анализирую сформулированный ТС критерий и указываю, какие из этого критерия следуют выводы.

Если критерий сформулирован верно, то моя подсказка - путь к решению. Но может оказаться и так, что вывод покажется неразумным или невыполнимым. В этом случае нужно будет переформулировать критерий.

В любом случае для решения задачи (или детектирования ошибки) следует сформулировать критерий и осуществлять проверку именно по этому критерию. Это, - казалось бы, очевидная вещь, но часто на практике об этом забывают.

gubilon
Offline
Зарегистрирован: 24.09.2018

Да, ваша посдсказка со спутниками помогла. Но смоделировал такую ситуацию, что при работе устройства неожиданно сгорает модуль. Самое интересное, что продолжают писаться координаты и время, которые были переданы ранее. При чем сравнить предыдущую величину со следующей я не могу, так как приходят пачки с разной периодичностью. В цикле while на проверку последовательного порта Arduino начинает "выплёвывать" ошибки. Вот и не могу понять, что ему предоставить на проверку. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Надо либу ковырять - чего тут думать-то. Скорее всего заложен в нее алгоритм вытеснения старых данных новыми без учета некоего таймаута. Нет новых данных - в памяти болтаются старые, невытесненные.

gubilon
Offline
Зарегистрирован: 24.09.2018

Для обработки алгоритма использовал библиотеку TinyPLusGPS. Скорей всего она где-то их хранит, так как буфер порта пробывал очищать и не помогло(

b707
Offline
Зарегистрирован: 26.05.2017

gubilon пишет:

Для обработки алгоритма использовал библиотеку TinyPLusGPS. Скорей всего она где-то их хранит, так как буфер порта пробывал очищать и не помогло(

ну так загляните в код библиотеки, не надо ее боятся - там такой же См, как и в вашем скетче

gubilon
Offline
Зарегистрирован: 24.09.2018

Заглянул и понял, как я позабыл теорию( Искал решения и понял, что лучше всего парсить код GPS, так как и места меньше займет и обработка данных быстрее. Плюс при отключении модуля, переменные точно будут обнулятся и процесс проверки упроститься. Но вот с парсингом всё плохо. После функции strtok я застрял. Не мог у понять, как разбитые строки присвоить в переменные, а тем более преобразовать в общий вид. Буду рад советам в плане литературы. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Так, например:

typedef struct {                                  
  uint32_t timestamp;
  uint8_t status;
  ...
} gprmc_t ;

gprmc_t gprmc;
...
fieldNumber = 0x00;
while (ch) {
   ch = strtok(buffer, ',');
   switch (fieldNumber) {
      ...
     case 0x01:
        gprmc.timestamp = stringToTimeStamp(ch );
        break;

     case 0x02:
        gprmc.status = (0 == strcmp(ch, "A"));
        break;
      ...
    }
  fieldNumber++;
}

 

gubilon
Offline
Зарегистрирован: 24.09.2018

sadman41 пишет:

Так, например:

typedef struct {                                  
  uint32_t timestamp;
  uint8_t status;
  ...
} gprmc_t ;

gprmc_t gprmc;
...
fieldNumber = 0x00;
while (ch) {
   ch = strtok(buffer, ',');
   switch (fieldNumber) {
      ...
     case 0x01:
        gprmc.timestamp = stringToTimeStamp(ch );
        break;

     case 0x02:
        gprmc.status = (0 == strcmp(ch, "A"));
        break;
      ...
    }
  fieldNumber++;
}

 

Это конечно всё красиво,но боюсь, что надо всё таки в учебник заглянуть.  Получилось сделать временную структуру для проверки на стабильность, но она на строчек сто, при этом Расшифровывает только RMC, где беру координаты и дату со временем. Sadman41, подскажите пожалуйста книжку, или,если вам не будет трудно пару уроков с дом. заданием. Честно для меня неприятный пробел(

sadman41
Offline
Зарегистрирован: 19.10.2016

Учебники, как тут пишут опытные поросяты и коты, - это Керниган и Ритчи, да Страуструпп. Я-то сильно эти делом не увлекаюсь, мне двадцати операторов хватает на все ))

gubilon
Offline
Зарегистрирован: 24.09.2018

Тогда такой вопрос. Приходит сообщениие типа GPGGA и мы видим его в терминале в виде последовательность повторяющейся каждую секунду( в зависимости от интервала). Команда strtok позволяет разделить строку на подстроки опираясь на запятые, как разделительные знаки. Я не могу понять, как дальше эти строки внести в переменные и преобразовать.

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, я же вам показал пример: берете fieldNumber , которая будет обозначать номер поля (фрагмента) строки. strtok же фрагментами вам нарубит строку, так? Ну вот, значит, получили кусок, switch-ом проанализировали какой он по счету от начала, им же "положили" в желаемую переменную. Затем номер поля увеличили и опять strtok сделали. Затем вновь switch моможет по номеру фрагмента засунуть в нужную переменную. And again, again and again, пока strtok не вернет NULL, т.е. дойдет до конца строки.

Самый простой вариант, по-моему, с минимумом оверхеда. 

gubilon
Offline
Зарегистрирован: 24.09.2018

Хорошо. Попробую сделать по вашему примеру. 

gubilon
Offline
Зарегистрирован: 24.09.2018

вниз

gubilon
Offline
Зарегистрирован: 24.09.2018

вниз

renoshnik
Offline
Зарегистрирован: 11.04.2013

gubilon пишет:

Хорошо. Попробую сделать по вашему примеру. 

strncmp – сравнение строк с ограничением количества сравниваемых символов.

strtok – разбиение строки на части по указанному разделителю.

может это поможет ?

gubilon
Offline
Зарегистрирован: 24.09.2018

Прошу прощения за молчание. Был немного занят другим. Вашему вниманию такая "простыня". И да, sadman41, ваш способ непонял всё равно.

//$GPRMC,125504.049,A,5542.2389,N,03741.6063,E,0.06,25.82,200906,,,*17
 
#include <SoftwareSerial.h>
 String data;
 String Time;
  String Status;
  String Lantitude;
  String NS;
  String Longitude;
  String EW;
  String Gorsost;
  String Angle;
  String Date;
  String Magsclon;
  String Naprav;
  String Dostov;
 char sz[64];
 char floatbuf1[32]; 
 char floatbuf2[32]; 
SoftwareSerial ss(D1, D8);  //  RX, TX
 
void setup() {
  Serial.begin(57600);
  ss.begin(9600);
  delay(1000);
}
 
void loop() {  
  data=ss.readStringUntil(13);
  data.trim();  
  if (data.startsWith("$GPRMC")) {
 int index1 = data.indexOf(',');
 int index2 = data.indexOf(',',index1+1);
 int index3 = data.indexOf(',', index2+1);
 int index4 = data.indexOf(',', index3+1);
 int index5 = data.indexOf(',',index4+1);
 int index6 = data.indexOf(',', index5+1);
 int index7 = data.indexOf(',', index6+1);
 int index8 = data.indexOf(',',index7+1);
 int index9 = data.indexOf(',', index8+1);
 int index10 = data.indexOf(',', index9+1);
 int index11 = data.indexOf(',', index10+1);
 int index12 = data.indexOf(',', index11+1);
 Time = data.substring(index1+1,index2);
 //Status = data.substring(index2+1,index3);
 Lantitude = data.substring(index3+1,index4);
 //NS = data.substring(index4+1,index5);
 Longitude = data.substring(index5+1,index6);
 //EW = data.substring(index6+1,index7);
 //Gorsost = data.substring(index7+1,index8);
 //Angle = data.substring(index8+1,index9);
 Date = data.substring(index9+1,index10);
 //Magsclon = data.substring(index10+1,index11);
 //Naprav = data.substring(index11+1,index12);
 //Dostov = data.substring(index12+1);
  Lantitude.toCharArray(floatbuf1, sizeof(floatbuf1));
 double Lant = atof(floatbuf1);
 Lant=Lant/100;
 Longitude.toCharArray(floatbuf2, sizeof(floatbuf2));
 double Long = atof(floatbuf2);
 Long=Long/100;
 int year = Date.substring(4, 6).toInt();
 int month = Date.substring(2, 4).toInt();
 int day = Date.substring(0, 2).toInt();
int hour = Time.substring(0, 2).toInt()+3;
if (hour > 24)
{
  hour=hour%24;
}
int minute = Time.substring(2, 4).toInt();
int seconds = Time.substring(4, 6).toInt();
sprintf(sz,"%02d-%02d-%02d %02d:%02d:%02d", day, month, year, hour, minute, seconds);
Serial.println(sz);
Serial.println(Lant,4);
Serial.println(Long,4);
Serial.println();
  }
}