Error taking gps data and putting it into a string

Hi everyone! I have been working on an RTTY telemetry system for a weather balloon. I have overcome many obstacles and this one seems like the last.

I am using the Arduino Mega 2560 to take data from Adafruit’s Ultimate GPS Module through its hardware Serial1 port and output it through an audio cable with RTTY to a handheld ham radio.

So far, I have managed to send through RTTY the altitude, latitude, and longitude. Unfortunately, the latitude and longitude only output two number (and a negative sign for the longitude). It seems like it’s only spitting out characters to the decimal place.

The code is below.

#include <baudot.h>
#include <RTTY.h>





#include <TinyGPS++.h> // Include the TinyGPS++ library
TinyGPSPlus tinyGPS; // Create a TinyGPSPlus object


float LAT, LONG, ALT;



// Set Serial1 to either ssGPS if using SoftwareSerial or Serial1 if using an
// Arduino with a dedicated hardware serial port


// Define the serial monitor port. On the Uno, and Leonardo this is 'Serial'
//  on other boards this may be 'SerialUSB'
#define SerialMonitor Serial

void setup()
{
  RTTY.attach(12);
  SerialMonitor.begin(9600);
  Serial1.begin(9600);
}

void loop()
{

  LAT = tinyGPS.location.lat();
  char latString[1+10+1];  // sign + 5 digits + terminator
  itoa(LAT, latString, 10);  // convert integer to a string in base 10
  
  LONG = tinyGPS.location.lng();
  char longString[1+10+1];  // sign + 5 digits + terminator
  itoa(LONG, longString, 10);  // convert integer to a string in base 10
  
  ALT = tinyGPS.altitude.feet();
  float altString[1+10+1];  // sign + 5 digits + terminator
  itoa(ALT, altString, 10);  // convert integer to a string in base 10
 printGPSInfo();

  
RTTY.tx("alt: ");
RTTY.tx(altString);
RTTY.tx("\n");

RTTY.tx("lat: ");
RTTY.tx(latString);
RTTY.tx("\n");

RTTY.tx("long: ");
RTTY.tx(longString);
RTTY.tx("\n");
  // print position, altitude, speed, time/date, and satellites:


  // "Smart delay" looks for GPS data while the Arduino's not doing anything else
  smartDelay(2000); 
}

void printGPSInfo()
{
  // Print latitude, longitude, altitude in feet, course, speed, date, time,
  // and the number of visible satellites.
  SerialMonitor.print("Lat: "); SerialMonitor.println(tinyGPS.location.lat(), 6);

  SerialMonitor.print("Long: "); SerialMonitor.println(tinyGPS.location.lng(), 6);
  SerialMonitor.print("Alt: "); SerialMonitor.println(tinyGPS.altitude.feet());

  SerialMonitor.print("Course: "); SerialMonitor.println(tinyGPS.course.deg());
  SerialMonitor.print("Speed: "); SerialMonitor.println(tinyGPS.speed.mph());
  SerialMonitor.print("Date: "); printDate();
  SerialMonitor.print("Time: "); printTime();
  SerialMonitor.print("Sats: "); SerialMonitor.println(tinyGPS.satellites.value());
  SerialMonitor.println();
}

// This custom version of delay() ensures that the tinyGPS object
// is being "fed". From the TinyGPS++ examples.
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    // If data has come in from the GPS module
    while (Serial1.available())
      tinyGPS.encode(Serial1.read()); // Send it to the encode function
    // tinyGPS.encode(char) continues to "load" the tinGPS object with new
    // data coming in from the GPS module. As full NMEA strings begin to come in
    // the tinyGPS library will be able to start parsing them for pertinent info
  } while (millis() - start < ms);
}

// printDate() formats the date into dd/mm/yy.
void printDate()
{
  SerialMonitor.print(tinyGPS.date.day());
  SerialMonitor.print("/");
  SerialMonitor.print(tinyGPS.date.month());
  SerialMonitor.print("/");
  SerialMonitor.println(tinyGPS.date.year());
}

// printTime() formats the time into "hh:mm:ss", and prints leading 0's
// where they're called for.
void printTime()
{
  SerialMonitor.print(tinyGPS.time.hour());
  SerialMonitor.print(":");
  if (tinyGPS.time.minute() < 10) SerialMonitor.print('0');
  SerialMonitor.print(tinyGPS.time.minute());
  SerialMonitor.print(":");
  if (tinyGPS.time.second() < 10) SerialMonitor.print('0');
  SerialMonitor.println(tinyGPS.time.second());
}

Whenever I try to take the char and turn it into a float, it says itoa can’t turn a float into a string.

I am kinda a newbie when it comes to software so this code is the best I could do.

Any help is greatly appreciated.

Noah

The 'i' in 'itoa' is short for 'integer'.

Does that mean I can't turn the float into a string?

No, of course not.
Use dtostrf instead.

Yes, use dtostrf.

#include <baudot.h>
#include <RTTY.h>

#include <NMEAGPS.h>
NMEAGPS gps;  // Define the object that parses GPS characters into...
gps_fix fix;  //   ... the structure containing all those field values.

#define GPS_BAUD 9600 // GPS module baud rate. GP3906 defaults to 9600.

#define gpsPort Serial1

// Define the serial monitor port. On the Uno and Leonardo this is 'Serial'
//  on other boards this may be 'SerialUSB'
#define SerialMonitor Serial

void setup()
{
  RTTY.attach(12);
  SerialMonitor.begin(9600);
  gpsPort.begin(GPS_BAUD);
}

void loop()
{
  if (gps.available( gpsPort )) {
    fix = gps.read();
  
    char buffer[16];

    RTTY.tx("alt: ");
    buffer[0] = '\0'; // empty the string
    if (fix.valid.altitude)
      dtostrf( fix.altitude_ft(), 1, 2, buffer );
    RTTY.tx( buffer );
    RTTY.tx("    ");

    RTTY.tx("lat: ");
    buffer[0] = '\0'; // empty the string
    if (fix.valid.location)
      dtostrf( fix.latitude(), 1, 6, buffer );
    RTTY.tx( buffer );
    RTTY.tx("    ");

    RTTY.tx("long: ");
    buffer[0] = '\0'; // empty the string
    if (fix.valid.location)
      dtostrf( fix.longitude(), 1, 6, buffer );
    RTTY.tx( buffer );
    RTTY.tx("    ");

    printGPSInfo();
  }
}

void printGPSInfo()
{
  // print position, altitude, speed

  SerialMonitor.print( F("Location: ") );
  if (fix.valid.location) {
    SerialMonitor.print( fix.latitude(), 6 );
    SerialMonitor.print( ',' );
    SerialMonitor.print( fix.longitude(), 6 );
  }

  SerialMonitor.print( F(", Altitude: ") );
  if (fix.valid.altitude)
    SerialMonitor.print( fix.altitude() );

  SerialMonitor.println();
}

If you want to try that NeoGPS version of your sketch, you can get the NeoGPS library from the Arduino Library Manager, under the menu Sketch-> Include Library-> Manage Libraries.

Of course, we still don’t know which RTTY library you are using. None of the libraries I can find will compile with your sketch. :-/

Noah517:
Hi everyone! I have been working on an RTTY telemetry system for a weather balloon. I have overcome many obstacles and this one seems like the last.

Any help is greatly appreciated.

You might want to consider a LoRa based balloon tracker, it will transmit the GPS co-ordinates as LoRa telemetry or FSK RTTY.

Range to a high altitude balloon is 250-400km at a mere 10mW.

Small and light, can run for weeks on a couple of AA batteries;

Thank you for the information. The code works perfectly. I have my ham radio license so I am going to output the audio to a handheld vhf radio and transmit my license with the data. The LoRa telemetry system is a good idea but I don’t see how even with a high gain antenna, you can get 250-400 km with 10 mW. It is difficult for me to get 2 km with a 100 mW HC-12. But I will definitely look into that. The library I used is bellow.

I don't see how even with a high gain antenna, you can get 250-400 km with 10 mW.

Read up on the technology. LoRa radios can receive and process signals at -130 dBm. Also, check out the range tests with low gain antennas at srnet's site http://www.loratracker.uk/.

Noah517:
The LoRa telemetry system is a good idea but I don’t see how even with a high gain antenna, you can get 250-400 km with 10 mW.

No need for fancy antennas, 1/4 wave wire with radials on the balloon transmitter and say a 5dB gain omni on the receiver is good enough.

The current record with that sort of equipment is 702km, 868Mhz @ 25mW;

702km World record.

Noah517:
Thank you for the information. The code works perfectly. I have my ham radio license so I am going to output the audio to a handheld vhf radio and transmit my license with the data.

Here in the UK you cannot use your amateur licence for airborne transmitters, so we are restricted to using ISM band devices, typically at 10mW only.

Simple radio modules such as the RFM22\SI4432 or indeed the LoRa devices can produce FSK RTTY, this is much more effective than AFSK RTTY, distance wise. Baud rate is low, typically 100 - 200baud, but that is OK.

The FSK RTTY can cover similar distances too, no need to send a UHF handheld up in a balloon and use large amounts of transmit power to compensate.

I live in the U.S. So that’s not too big of a problem. Although you are right, sending a handheld up to 100 thousand feet is not the best method, it will work and to my knowledge, it seems to be more reliable. The LoRa incredible. It would be amazing if they could apply that to voice. 200+ km walkie talkies!

Noah517:
Although you are right, sending a handheld up to 100 thousand feet is not the best method, it will work and to my knowledge, it seems to be more reliable.

Maybe, but handhelds are quite complex devices, with batteries that are not optimised for the cold with connectors and switches that can be affected by condensation as a balloon decends.

The LoRa module in the picture of the tracker I showed earlier does not have many parts and apart from the Arduino Pro Mini on the back of the board, there are only a couple of other components needed.

The tracker will run on 2 x AA Lithium Energizer batteries for several weeks, those batteries are good down to -40C, most batteries give up long before that.

LoRa is at its best at low data rates and its easy to send a binary location packet (10bytes of data) at a rate that will give a range of 3 times what I quoted earlier. When a balloon lands and you need to find it this extra range is a great help.

In one experiment I used a low cost radio controlled plane to take my LoRa relay to altitude and I was able to locate a LoRa tracker (balloon ?) on the ground over 12km away in an Urban area, effectivly searching an area of 500sqkm in 10 minutes.

How to Search 500 Square Kilometres in 10 minutes