mikalhart / TinyGPSPlus

A new, customizable Arduino NMEA parsing library
http://arduiniana.org
1.08k stars 491 forks source link

sending data to Terminal Node Controller (TNC) #62

Closed bill-orange closed 5 years ago

bill-orange commented 5 years ago

I have been successful in setting up a logger on an ESP8266. I am creating a file in SPIFFS that can be converted to a KLM file for Google Earth.

Now I would like to hook up my Ham Radio TNC. I need to feed it the appropriate NEMA sentence. $GPGGA should work.

Is ther a way to make TinyGPSPlus echo a NEMA sentence?

something like (I just made this up):

char sentence[128]; // echo last $GPGGA sentence sentence = gps.nema.gpgga();

Suggestions? How can I accomplish something like this.

TD-er commented 5 years ago

Well you just feed the TinyGps object a sentence a character at a time using the encode function. At the place where you call this encode function, you can also feed that character to a String (or an array). A NMEA line may not exceed 80 characters, so you can use some fixed sized array for this.

If the parser finished a line, the encode function will return true. See how I used it here for debugging purposes in ESPeasy: https://github.com/letscontrolit/ESPEasy/blob/5b42210c47201e43a2310826d514911450fc211a/src/_P082_GPS.ino#L93-L113

bill-orange commented 5 years ago

Thanks @TD-er . I may switch to your approach. Before reading your reply I did this. Its awkward but seems to work. I reconstructed the string.

Before setup:

TinyGPSCustom msg1(gps, "GPGGA", 1);
TinyGPSCustom msg2(gps, "GPGGA", 2);
TinyGPSCustom msg3(gps, "GPGGA", 3);
TinyGPSCustom msg4(gps, "GPGGA", 4);
TinyGPSCustom msg5(gps, "GPGGA", 5);
TinyGPSCustom msg6(gps, "GPGGA", 6);
TinyGPSCustom msg7(gps, "GPGGA", 7);
TinyGPSCustom msg8(gps, "GPGGA", 8);
TinyGPSCustom msg9(gps, "GPGGA", 9);
TinyGPSCustom msg10(gps, "GPGGA", 10);
TinyGPSCustom msg11(gps, "GPGGA", 11);
TinyGPSCustom msg12(gps, "GPGGA", 12);
TinyGPSCustom msg13(gps, "GPGGA", 13);
TinyGPSCustom msg14(gps, "GPGGA", 14);
TinyGPSCustom msg15(gps, "GPGGA", 15);

In my loop:

sprintf (sentence, "$GPGGA,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,*%s", msg1.value(), msg2.value(), msg3.value(), msg4.value(), msg5.value(), msg6.value(), msg7.value(), msg8.value(), msg9.value(), msg10.value(), msg11.value(), msg12.value(), msg13.value(), msg14.value(), msg15.value());

Serial.println(sentence);

So, within my serial output is the $GPGGA string. My TNC will ignore anything not starting with $GPGGA so I should not have to suppress any other output.

Rats! The checksum filed is not coming through correctly. I am not sure what to do about that except to go back to your approach.

I will leave this open for a while in case other ideas emerge.

bill-orange commented 5 years ago

@TD-er I tried your suggestion or at least my interpretation of it.

static void smartDelay(unsigned long ms)
{
  char inbyte;
  unsigned long start = millis();
  do
  {
    while (ss.available())
      inbyte = ss.read();
      gps.encode(inbyte);
  } while (millis() - start < ms);
}

Even without sending any data to another serial port this just generates garbage. Suggestions? I am still hoping for another approach. perhaps adding some sort of debug print to the tinygpsplus library.

TD-er commented 5 years ago

You don't check for the result of the encode function. It will only return true when a complete NMEA sentence has been parsed. So you should keep track of it and return when done with the line. Also you are missing a scope for the inner while.

static void smartDelay(unsigned long ms)
{
  char inbyte;
  unsigned long start = millis();
  while (ss.available()) 
  {
    inbyte = ss.read();
    if (gps.encode(inbyte))
    {
      // Do stuff with your collected string data (collected where?)
      return;
    }
    if (millis() - start >= ms)  return;
  }
}

Also I think it would be nice to return whether you were successful in parsing a line. And I always find it a bit tricky to do these calculations to see whether the timeout has been reached. Quite often they are wrong (thus wait for 49 days in some situations), but in this case the ss.available() will run out so it will not be that bad I guess.

bill-orange commented 5 years ago

@TD-er YES, that does the trick! I had to make some other changes. Calls to smartDelay need to be smartDelay(10); , any long and FTP doesn't work and any shorter and I get garbled strings.

I also upped the clock speed on the EPS8266 to 160 from 80. This accomplishes what I was after. The Terminal Node Controller (TNC, a ham radio modem) receives only GGA strings, only when there is is good data and only when the user turns it on. If a few bad packets get through it not the end of the world. The receiving station will reject them.

static void smartDelay(unsigned long ms)
{
  char inbyte;
  unsigned long start = millis();
  while (ss.available()) 
  {
    inbyte = ss.read();
    currentSentence += inbyte;
    if (gps.encode(inbyte))
    {
      lastSentence = currentSentence;
      if (lastSentence.indexOf("GPGGA")>=0 && lastSentence.length()<=86 && gps.location.isValid()&& TNCwrite) {
        Serial.print (lastSentence);
      }
      currentSentence = "";
      return;
    }
    if (millis() - start >= ms)  return;
  }
}
bill-orange commented 5 years ago

If any Hams need my code, let me know. It will be used for APRS tracks.