GPS модуль. как померить скорость?

Тема в разделе "Iskra JS, Espruino, Йодо", создана пользователем Ilichevai, 4 янв 2018.

Метки:
  1. Ilichevai

    Ilichevai Нуб

    Всем привет.
    Хочу получить скорость и в зависимости от ее величины делать определенные манипуляции, например, зажечь светодиод.
    Вижу 2 пути решения.
    1) Если использовать стандартную библиотеку Esprino, взятый по ссылкам ниже,
    http://wiki.amperka.ru/продукты:troyka-gps-glonass
    https://www.espruino.com/GPS
    Код (Javascript):
    Serial3.setup(115200, {rx: P0, tx: P1});
    var gps = require("GPS").connect(Serial3, function(data) {
      console.log(data);
    });
    то выводится следующие данные:
    Код (Javascript):
    { "time":"16:35:29", "lat":53.068403,"lon":-4.076282,"fix":1,"satellites":7,"altitude":1085.0 }
     
    соответственно зная широту, долготу и время в момент T1 и T0 то можно посчитать пройденное расстояние, а из него получить скорость c точностью 0,3%, что мне достаточно. код здесь https://www.movable-type.co.uk/scripts/latlong.html
    Проблема
    Как из этого добра получить широту и долготу в T0 и T1 и передать переменной?
    Код (Javascript):
    Serial3.setup(115200, {rx: P0, tx: P1});
    var gps = require("GPS").connect(Serial3, function(data) {
      console.log(data);
    });
    В консоль данные выводятся, а вот переменной передаваться упорно не хотят.
    Если сделать как-нибудь так
    Код (Javascript):
    Serial3.setup(115200, {rx: P0, tx: P1});
    var gps = require("GPS").connect(Serial3, function(data) {
      T1=data;
    return T1;
    })
    console.log(gps);

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

    2) Если общаться с Serial.
    Имеем:
    Использовал такой код
    Код (C++):
    Serial3.setup(115200, {rx: P0, tx: P1});
    var bufer='';
    Serial3.on('data',function(data){
    bufer +=data;
    var lines = bufer.split('$');
    bufer =lines [lines.length-1];
    if (lines.length >1){
    for (l=0;l<lines.length-1;l++){ print(lines[l]);}}});
     
    Проблема
    Как результат,он выводит все, что передает GPS контроллер но здесь http://www.gpsinformation.org/dale/nmea.htm
    я сообщений с таким кодами не нашел и соответственно не понимаю какая позиция, что значит и как это все дело грамотно распарсить, чтобы вытянуть скорость.

    для С++есть куча библиотек и готовых решений, а тут что-то пошло не так =(
     
  2. Ilichevai

    Ilichevai Нуб

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

    Код (Javascript):
    //********* конектимся к GPS приемнику
    Serial3.setup (115200, {rx: P0, tx: P1});

    var R = 6371e3; // радиус земли в метрах
    var Led= require('@amperka/led').connect(A1);//вводим светодиод

    var lastData; // все данные полученные от GPS в T0
    var lastData2; //секунды в T0***
    var lastLon;  // широта в T0
    var lastLat; //  долгота в T0
    var LastTime; // предыдущее время
    var toRad=Math.PI/180; // переводим в радианы
    var i=0;//ограничитель выводов инфы в консоль


    var gps = require ("GPS"). connect (Serial3, function (data) {

      if (lastData,i<50) {            //ограничиваем 50-ю измерениями, чтобы проанализировать надо убрать результат
       // do stuff here - eg. the difference between the two readings
      //****** расстояние
        var Lon=data.lon*toRad; // lon в  t1
        var Lat=data.lat*toRad; //lat в  t1
        var diffLon=Math.abs(Lon-lastLon*toRad); //ищем дельту
        var diffLat= Math.abs(Lat-lastLat*toRad); //ищем дельту
    //************************************** блок расчета расстояния      

    var a= Math.sin(diffLat/2) * Math.sin(diffLat/2) +
            Math.cos(Lat) * Math.cos(lastLat*toRad) *
            Math.sin(diffLon/2) * Math.sin(diffLon/2);
     
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var distansP = R * c;
    //****** время между измерениями
    var tTime= data.time.split(':'); // массив чч мм
    tTime=tTime[2];
    var diffTime=tTime-LastTime;
        //****** скорость
        var speed1= distansP/diffTime; // м/с
        var speed2= speed1*3.6; // км/ч
    //********************зажигаем диод если скорость больше 60  
        if(speed2>40){
       
          Led.turnOn();
        }
        else{Led.turnOff();}
    console.log(speed2,speed1); // выводим скорость в консоль

    //console.log ('1',Math.sin(diffLat/2),diffLat/2,'2',Math.cos(Lat),  '3',Math.cos(lastLat*toRad),lastLat*toRad,'4',Math.sin(diffLon/2),'5',Math.sin(diffLon/2),'6',Math.sqrt(a),a,'7',Math.sqrt(1-a),'8',diffTime );
      }
    // передаем предыдущие показания
    lastData=data;
    lastLon=data.lon; //в градусах
    lastLat=data.lat; //в градусах

    LastTime=  data.time.split(':'); //сохраняем предыдущее значение времени в массив
    LastTime= LastTime[2]; // вытаскиваем изменение секунд

    //  lastData = data.time.split(':');
    //lastData2 = lastData[2];
    //  lastLon= data.lon;
      i=i+1; /ограничитель выводов инфы в консоль. надо убрать чтоб работало в авто.
    });
     
     
    Последнее редактирование: 7 янв 2018
  3. Sergei K

    Sergei K Нерд

    Подскажите, пожалуйста, измерения происходят раз в секунду или чаще?
    Есть ли возможность увеличить частоту приема сигнала до десяти раз в секунду, как для библиотек Arduino?
     
  4. ELITE

    ELITE Гик

    1) - смотри даташит на ЖПС приемник - выше, чем он отдает, не прыгнуть
    2) - ЖПС уже сам может отдавать скорость - зачем изобретать велосипед?

    почитайте о протоколе NMEA - там много чего с вашего ЖПС идет интересного

    и да, не обязательно брать библиотеки - можно просто парсить что приходит на порт
    как пришло $ - начало строки - читать и сравнивать с шаблоном
    а дабы не было ошибок - под конец каждой строки есть хешсумма, сверили, если верно - собранные данные пускать в дело
     
    sys и Igor68 нравится это.
  5. Ilichevai

    Ilichevai Нуб

    Ну созданием нормальных библиотек никто так и не озаботился и походу тема с espruino потихоньку помирает и до ардуино им очень далеко. Безгеморно на этой платформе можно только задачи из наборчика йодо решать, если чуть в сторону, то получаешь сразу кучу гемора. Если идти по вар. 2. (см мой первый пост), то сообщения со спутника приходят гораздо чаще, чем раз в секунду, и очень много сообщений. Как правильно распарсить и какое сообщение со спутника парсить, чтобы вытащить скорость, я так и не разобрался. Кстати продавец контроллера мог бы и написать какие конкретно сообщения он принимает и что в них что значит. То же самое могу сказать и про гребаный гланас. За пару часов нагуглить справочник по их сообщениям не поучилось.
     
    Последнее редактирование: 6 мар 2018
  6. ИгорьК

    ИгорьК Гуру

  7. sys

    sys Злобный Буратино Модератор

    https://labs.mediatek.com/en/chipset/MT3333
    https://labs.mediatek.com/en/download/VT9qMakW
    https://ru.wikipedia.org/wiki/NMEA_0183
    https://ru.wikipedia.org/wiki/ГЛОНАСС
    https://www.sparkfun.com/datasheets/GPS/NMEA Reference Manual1.pdf
    http://gnss.4du.ru/wp-content/uploads/2016/02/NMEA.pdf

    это все в дополнение к тому что уже есть на http://wiki.amperka.ru/продукты:troyka-gps-glonass :
    http://naviaglonass.ru/wp-content/uploads/Apparatura-navigatsionnaya-NL3333-RE`-v1_2.pdf
    http://naviaglonass.ru/wp-content/uploads/Opisanie-komand-NL3333_KL3333-i-SL3333E-v1_0.pdf
    https://www.espruino.com/GPS
    http://www.gpsinformation.org/dale/nmea.htm
    http://www.espruino.com/modules/GPS.js

    так чего не хватает?
     
    Последнее редактирование: 7 мар 2018
  8. ИгорьК

    ИгорьК Гуру

    Нормальных библиотек :)
     
  9. Sergei K

    Sergei K Нерд

    Таким образом получается, что для измерения скорости в принципе не нужны дополнительные танцы.
    Все данные выводятся, например, в рекомендованном минимальном наборе данных (команда $RMC).
    Для смены скорости сообщений, например, до десяти раз в секунду (http://wiki.amperka.ru/продукты:troyka-gps-glonass) нужно отправить из консоли соответствующую команду типа РМТК220 (с предварительно подсчитанной для нее чек-суммой). Это справедливо для Iskra JS? Кстати в коде, представленном по ссылке http://www.espruino.com/modules/GPS.js указано условие:
    if (tag=="GGA")
    Вероятно, если подставить
    if (tag=="RMC"), то будет выводиться минимальный набор данных, включая скорость, правда в узлах (но это не проблема). Далее, надо распарсить строку, зная где находится значение скорости.
    Правильно ли я понимаю суть вопроса?
     
    Последнее редактирование: 7 мар 2018
  10. ELITE

    ELITE Гик

    да RMC - ваше всё )
    жаль в нем нет высоты только
    но никто не мешает распарсивать и RMС и GGA
    а если приемник отдает то и ZDA - там дата время хранится
     
  11. Ilichevai

    Ilichevai Нуб

    ну хз там большая часть сообщений RMС
    Такт ну давно это было. Насколько я помню и судя по моему посту rmc он не выводит. Выводит что то чего в справочниках по сообщениям gps нет.
     
  12. Ilichevai

    Ilichevai Нуб

    В общем в Вики амперки все написано для Ардуино. Для искры js есть стандартный запрос, который выводит небольшой набор данных, в котором даже скорости нет.
    Если брать все данные, которые с контроллера приходят (см пост 1 вар. 2) то получаю сообщения, которые в справочниках не ищутся.
    Соответственно, вопрос можно сформулировать так:
    Какой код написать, чтобы получить скорость в км/ч из sme сообщений. То, что я делал, см выше. Распарить не получилось.
    PsPs же подробно все расписал.
     
  13. ELITE

    ELITE Гик

    подключите ЖПС к компу и посмотрите в мониторе порта что с него идет
    и сюда выложите

    сразу будет видно что есть и что брать
     
    MickNich и sys нравится это.
  14. Ilichevai

    Ilichevai Нуб

    Ну а кто-нибудь может уже брал скорость из данных полученных из порта?
     
    Последнее редактирование: 7 мар 2018
  15. ELITE

    ELITE Гик

    брал что?
     
  16. Ilichevai

    Ilichevai Нуб

    Поправил
     
  17. ELITE

    ELITE Гик

    я брал, у меня парсер простейший именно эту группу и распарсивает

    вот собственно сам код, - как пример как распарсивать....
    Код (C++):
    if(gps_valid) {digitalWrite(LED_GPS, 1);}else{digitalWrite(LED_GPS, 0);}

    while(true)
      if(gps.available())
      {
        char ch=gps.read();   // Serial.print(ch);

        if(ch == '$') { cnt = 0; csv = 0; fix = 0;  }
        else
        {
          data[cnt++] = ch; /* сбор символов /**/
     
          if(ch == ',')
          {
            data[--cnt] = 0;  /* если нашли , то ставим 0 (конец строки) /**/ cnt = 0;   csv++;

            if(csv == 1)
            {
              res = strcmp(data,"GPRMC");
              if(res == 0) fix = 1;
            }

            if(fix == 1)
            {              // Serial.print(": ");Serial.println(data);
              if(csv == 2)      { time=data; hour=((data[0]-48)*10+(data[1]-48)); minute=((data[2]-48)*10+(data[3]-48)); second=((data[4]-48)*10+(data[5]-48)); }
              else if(csv == 3) { if(data[0]==65){ gps_valid=true;}else if(data[0]==86){gps_valid=false;}}
              else if(csv == 4) { data[4]=data[3];data[3]=data[2];data[2]='\0'; lat = atol(data) + ((atol(data+3)/60.0)/10000.0); }
              else if(csv == 6) { data[5]=data[4];data[4]=data[3];data[3]='\0'; lng = atol(data) + ((atol(data+4)/60.0)/10000.0); }
              else if(csv == 8) { spd = atof(data); spd>0.50?spd*=1.852:spd=0; }
              else if(csv == 9) { crs = atoi(data); }
              else if(csv == 10){ date=data; day=((data[0]-48)*10+(data[1]-48));  month=((data[2]-48)*10+(data[3]-48)); year=((data[4]-48)*10+(data[5]-48)); }
              else if(csv == 11)
              {int i=0;fix = 0;
               long dist_tmp = 0;
              if(latp==0 || lngp==0 ) {latp=lat; lngp=lng; }
              if(latp!=lat || lngp!=lng) {dist_tmp = distance_between(lat,lng,latp,lngp);  latp=lat; lngp=lng;   }
             
              if(btn_b[5]){ dist=dist+dist_tmp; }
              if(btn_b[4]){ dist=dist-dist_tmp; }
                   
               if(gps_valid){ gps_info();
           
    /*************************************************/
                 if(fname==""){
                    fname=date+".plt";
                    sd_filename_chek:
                    Serial.println(fname);
                    if(!SD.exists(fname)){ //если файла нет такого
                        Serial.println("SD creat File "+fname);
                       LosGps = SD.open(fname, FILE_WRITE);
                       if(!LosGps){ //если НЕ удалось открыть файл
                        SD.begin(SD_CS);LosGps = SD.open(fname, FILE_WRITE);  Serial.print("SD Reopen!");  //репеподключаю и переоткрываю
                       }
                       if(LosGps) { //если удалось открыть файл
                         LosGps.println("OziExplorer Track Point File Version 2.0");
                         LosGps.println("WGS 84");
                         LosGps.println("Altitude is in Feet");
                         LosGps.println("Reserved 3");
                         LosGps.println("0,2,255,Treck Start "+date+" "+time+",1,0,F80");    //0,ширина,цыет,название,нормально,0,цветр ржб заполнения  http://www.oziexplorer3.com/eng/help/fileformats.html
                         LosGps.println(" ");                                                //точек в треке
                         LosGps.close();          
                       } else {Serial.print("SD NO!"); }
                 
                     } else {
                      fname = "_"+fname;
                      goto sd_filename_chek;
                     }

                    }else{
                      if(dist_tmp!=0){  Serial.println("SD write GPS");
                        LosGps = SD.open(fname, FILE_WRITE);
                        if(LosGps){
                          LosGps.print(lat,6); LosGps.print(", ");
                          LosGps.print(lng,6); LosGps.print(", 0, ");//Код - 0, если это нормально, 1, если перерыв в дорожке.
                          LosGps.print("-777, "); /*высота*///Высота в футах (-777, если не действительна).
                          LosGps.print(", "); /*время делфи*/
                          LosGps.print(date); LosGps.print(", ");
                          LosGps.print(time); LosGps.println(" ");
                        LosGps.close();
                        } else { //не удалось открыть файл!!
                           Serial.println("SD WARNING !!!! no open file!!!");
                        }
                   
                      }
                    }

    /*************************************************/
                  }else{Serial.println("GPS Sat NO SIGNAL!");}

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

    код ищет начало строки $
    потом ключевое слово GPRMC (можно и другие поставить)
    и потом просто разбирает по запятым на блоки
    // проверки хешсуммы строк нету

    -------------
    //и да, не забывайте, что ЖПС приемник координаты может отдавать в РАЗНЫХ форматах!! (точнее одном из возможных форматов)
    есть 3 основных формата ЖПС координат - так что тут повнимательнее, если вам потом надо будет их переводить в путь или накладывать на карту!
     
    Последнее редактирование: 7 мар 2018
    sys нравится это.
  18. Ilichevai

    Ilichevai Нуб

    Круто !