Ненормальное поведение tinygps с GPS EM408

У меня есть Arduino Duemilanove и em408.

Мой код таков:

#include <TinyGPS.h>
#include <SoftwareSerial.h>

#define GPS_RX_PIN 2
#define GPS_TX_PIN 3

TinyGPS gps;
SoftwareSerial ss(GPS_RX_PIN, GPS_TX_PIN);

void setup()
{
  Serial.begin(9600);
  ss.begin(4800); 
  }

void loop()
{
  while (ss.available())
  {
    char c = byte(ss.read());
    // Здесь я попробовал Serial.write(c); и я успешно увидел данные NMEA в моем последовательном мониторе
    if (gps.encode(c))
    {
      long lat, lon;
     unsigned long fix_age;
    gps.get_position(&lat, &lon, &fix_age);
    if (fix_age == TinyGPS::GPS_INVALID_AGE )
      Serial.println("No fix ever detected!");
    else if (fix_age > 2000)
      Serial.println("Data is getting STALE!");
    else
      Serial.println("Latitude and longitude valid!");

      Serial.print("Lat: "); 
      Serial.print(lat);
      Serial.print(" Lon: "); 
      Serial.println(lon);

    }
    else Serial.println("No data!");
  }
}

Мой вывод таков:

No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
No data!
Latitude and longitude valid!
Lat: 32758239
 Lon: 15637489
No data!
No data!
No data!
No data!
No data!
No data!
No data!

И затем я продолжаю получать Нет данных! навсегда...

Итак...

  1. Почему функция gps.encode() возвращает значение true только один раз? Я получил исходные данные от GPS (прокомментированный код в моем фрагменте кода), и все в порядке. Почему он возвращает true только один раз?

  2. Почему данные о долготе и широте такие? Насколько я знаю, это неверно, верно?

ИЗМЕНИТЬ: Также пробовал с TinyGPS++.. но тоже не повезло с кодировкой...

#include <TinyGPS++.h>
#include <SoftwareSerial.h>


#define GPS_RX_PIN 2
#define GPS_TX_PIN 3

TinyGPSPlus gps;
SoftwareSerial ss(GPS_RX_PIN, GPS_TX_PIN);

void setup()
{
  Serial.begin(9600);
  ss.begin(4800); 
  }

void loop()
{
  while (ss.available()>0)
  {
    char c = byte(ss.read());
    // Здесь я попробовал Serial.write(c); и я успешно увидел данные NMEA в моем последовательном мониторе
    if (gps.encode(c)) //я ранее использовал if(gps.encode(ss.read())); но тогда не повезло
    {
      Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();

    }
    else Serial.println("No data!");
  }
}

Новый код:

#include <TinyGPS++.h>
#include <SoftwareSerial.h>


#define GPS_RX_PIN 2
#define GPS_TX_PIN 3

TinyGPSPlus gps;
SoftwareSerial ss(GPS_RX_PIN, GPS_TX_PIN);

void setup()
{
  Serial.begin(9600);
  ss.begin(4800); 
}

char clat[11];
char clng[11];

void loop()
{
    //если (кнопки || наклон) {
    //если (кнопки и BUTTON_SELECT) {

        bool isGpsLocationValid = false;
        do
        {  
            while (ss.available()>0)
            {
                char c = byte(ss.read());
                if (gps.encode(c)) //я ранее использовал if(gps.encode(ss.read())); но тогда не повезло
                {    
                    if (gps.location.isValid())
                    {
                        dtostrf(gps.location.lat(), 11, 6, clat);
                        dtostrf(gps.location.lng(), 11, 6, clng);
                        //отправить-печатать
                        // задержка (на всякий случай несколько ударов)
                        isGpsLocationValid = true;
                    }
                }   
             }
        } while (isGpsLocationValid == false);
        Serial.write(clat);
        Serial.println();
        Serial.write(clng);
       //}
    //}
}

EDIT: самый новый код, который я разместил, работает на 100%! Так что, если у вас есть подобные проблемы с этим ужасным GPS, используйте это!

Видимо, TinyGPS и TinyGPS++ плохо работают с этим GPS. Если быть точным, проблема с функцией gps.encode(c).

Поэтому использование if (gps.encode(c)) в большинстве случаев возвращает false, за исключением некоторых редких случаев, когда возвращается true, и тогда вы можете выполнить некоторую обработку...

Мой последний код решает эту проблему путем непрерывной проверки с использованием цикла do...while. Если if (gps.location.isValid()) возвращает true, что означает, что у меня есть достоверные данные, тогда я выполняю требуемую обработку и завершаю цикл do...while.

, 👍-1

Обсуждение

Ваш код, похоже, никогда не выводит "Нет данных!". Это должно быть "Не закодированные данные!"?, @Peter Bloomfield

Хорошо, да. я изменил код, @user1584421

Попробуйте изменить скорость передачи Serial.begin() на 4800 и в последовательном мониторе измените то же самое., @Manihatty

Вы делаете это в помещении? Вы уверены, что у вас есть блокировка GPS? Вы получаете данные NMEA даже без блокировки, но это пустые кадры данных NMEA., @Connor Wolf

Мужик, я знаю. Я использую его у нас дома. Получите действительные данные NMEA (увидел координаты на необработанных данных). Пробовал все комбинации скорости передачи. Пробовал разные перестановки, например char c = байт (ss.read()); char c = сс.read(); int c = байт (ss.read()); int c = ss.read(); //лучший байт c = байт (ss.read()); байт c = ss.read(); Никто не может дать мне ответ, это смешно. Попробовал на официальном форуме arduino, написал письмо создателю TinyGPS и TinyGPS++..., @user1584421

Если вы получаете правильные заблокированные данные GPS при выводе необработанного потока NMEA, очевидно, в библиотеке TinyGPS есть проблема, возможно, в результате взаимодействия с вашим конкретным GPS. Добро пожаловать в мир открытого исходного кода. Библиотека TinyGPS — это проект, созданный кем-то в свободное время и выпущенный **бесплатно**. Им *не* нужно вообще заботиться о его поддержке. Поскольку [источник доступен](https://github.com/mikalhart/TinyGPS), почему бы вам не попробовать исправить это самостоятельно?, @Connor Wolf

Попробуйте заставить tinyGPS проанализировать последовательные сообщения с ПК, а затем самостоятельно отправить действительную строку NMEA в последовательный монитор. Таким образом, вы можете быть уверены, что проблема связана с библиотекой или с GPS., @BrettAM

Если вы решили проблему, не могли бы вы опубликовать решение в качестве ответа? Это облегчит поиск для будущих посетителей. Спасибо!, @Peter Bloomfield


2 ответа


Лучший ответ:

2

Последний код, который я разместил, работает на 100%! Так что, если у вас есть подобные проблемы с этим ужасным GPS, используйте это!

Видимо, TinyGPS и TinyGPS++ плохо работают с этим GPS. Если быть точным, проблема с функцией gps.encode(c).

Поэтому использование if (gps.encode(c)) в большинстве случаев возвращает false, за исключением некоторых редких случаев, когда возвращается true, и тогда вы можете выполнить некоторую обработку...

Мой последний код решает эту проблему путем непрерывной проверки с использованием цикла do...while. Если if (gps.location.isValid()) возвращает true, что означает, что у меня есть достоверные данные, тогда я выполняю требуемую обработку и завершаю цикл do...while.

ПРИМЕЧАНИЕ. Этот код предназначен для библиотеки TinyGPS++. Та же теория, конечно, работает и для TinyGPS...

Вот оно:

#include <TinyGPS++.h>
#include <SoftwareSerial.h>


#define GPS_RX_PIN 2
#define GPS_TX_PIN 3

TinyGPSPlus gps;
SoftwareSerial ss(GPS_RX_PIN, GPS_TX_PIN);

void setup()
{
  Serial.begin(9600);
  ss.begin(4800); 
}

char clat[11];
char clng[11];

void loop()
{
    bool isGpsLocationValid = false;
    do
    {  
        while (ss.available()>0)
        {
            char c = byte(ss.read());
            if (gps.encode(c)) //я ранее использовал if(gps.encode(ss.read())); но тогда не повезло
            {    
                if (gps.location.isValid())
                {
                    dtostrf(gps.location.lat(), 11, 6, clat);
                    dtostrf(gps.location.lng(), 11, 6, clng);                        
                    isGpsLocationValid = true;
                }
            }   
        }
    } while (isGpsLocationValid == false);
    Serial.write(clat);
    Serial.println();
    Serial.write(clng);
}
,

Вы уверены насчет «пока (isGpsLocationValid = false)»? Это должно быть `в то время как (isGpsLocationValid == false)], иначе вы никогда не выйдете из этого цикла!, @jfpoilpret

ой, хорошее наблюдение, @user1584421


0

Большое спасибо!!! Вы уже дали мне решение моей проблемы, я пытался получить эти данные в течение 3 дней!! Когда я использовал только модуль GPS, все было в порядке, я мог получать данные, но когда я пытался использовать модуль GSM + GPS, я не мог получить данные от GPS! Ты дал мне решение

bool isGpsLocationValid = false;
        do
        {  
            while (ss.available()>0)
            {
                char c = byte(ss.read());
                if (gps.encode(c)) //я ранее использовал if(gps.encode(ss.read())); но тогда не повезло
                {    
                    if (gps.location.isValid())
                    {
                        dtostrf(gps.location.lat(), 11, 6, clat);
                        dtostrf(gps.location.lng(), 11, 6, clng);                        
                        isGpsLocationValid = true;
                    }
                }   
             }
        } while (isGpsLocationValid == false);
        Serial.write(clat);
        Serial.println();
        Serial.write(clng);

Поздравляем!! бразильские объятия для вас; )

,

Нет проблем... Просто проголосуйте за мой пост, если вы нашли его полезным (потому что на данный момент его -3), @user1584421

Преобразование в байт решает проблему? Потому что в противном случае не имеет смысла, что это будет работать, а старый код — нет, поскольку вам все еще нужно пройти через кодировку, чтобы выполнить тело IF., @rbaleksandar