HAB Flight Programme - GPS Datalogger

Hi,

Some guidance would be much appreciated.

I am making progress with a flight programme (Arduina Mega). The script occasionally secures a GPS signal (UBlox 7, HAB Supplies) and sends data on time, latitude, longitude and altitude to an SD card (Adafruit 5v Breakout Board - Serial3). However, I seem to be getting stuck on two (possibly related) issues. These are:

First, I only occasionally get a GPS signal (sometimes indoors and sometimes outdoors). When there is no signal, the Serial usually produces a readout like this: “invalid,******* **** ******* ****** ***** *** 0 0.00 *** 1947 0 27”;

Second, in attempting to sort things out, I have tried to change the GPS to ‘flight mode’, which I will need to do anyway at some point, but fail for no reason that I can readily appreciate, given my current level of understanding.

The code I have patched together and adapted follows:

//this programme (works on Mega) takes data from gps and sends string (time, lat, lon, and alt) to SD card


#include <SPI.h>//
#include <TinyGPS.h>
#include <SD.h>
#include <stdlib.h>

TinyGPS gps;
static char dtostrfbuffer[20];
int CS = 53;
int LED = 8;

//Define String
String SD_date_time = "invalid";
String SD_lat = "invalid";
String SD_lon = "invalid";
String SD_alt = "invalid";
String dataString ="";//used to concatinate string values, above

static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec, int SD_val);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
void setup()
{
  pinMode(CS, OUTPUT);  //Chip Select Pin for the SD Card//
  pinMode(LED, OUTPUT);  //LED Indicator//
  delay(100);//added
  //Serial interfaces
  Serial.begin(115200);
  Serial3.begin(4800);
//  Serial.begin(19200);
//  Serial3.begin(9600);
//  Serial.begin(19200);
//  Serial3.begin(4800);
//  Serial.begin(9600);
//  Serial3.begin(9600);

  //Connect to the SD Card
    if(!SD.begin(CS))
    {
      Serial.println("Card Failure");
      return;
    }
}

//-------------------------------------------------------------------
//-------------------------------------------------------------------
void loop()
{
  bool newdata = false;
  unsigned long start = millis();
  
  // Every second print an update
  while (millis() - start < 1000)
  {
    if (feedgps())
      newdata = true;
  }
  
    
  gpsdump(gps);
    //Write the newest information to the SD Card
  dataString = SD_date_time + "," + SD_lat + "," + SD_lon + "," + SD_alt;
  if(SD_date_time != "invalid")
    digitalWrite(LED, HIGH);
  else
    digitalWrite(LED, LOW);
  
  delay(100);//ch
    
  //Open the Data CSV File
  File dataFile = SD.open("LOG.csv", FILE_WRITE);
  if (dataFile)
  {
    dataFile.println(dataString);
    Serial.println(dataString);
    dataFile.close();
  }
  else
  {
    Serial.println("\nCouldn't open the log file!");//
  }
}

static void gpsdump(TinyGPS &gps)
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  
  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5, 1); 
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5, 2); 
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

  print_date(gps);// DATE AND TIME

    print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2, 3);//ALTITUDE
    print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
    print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2, 0);
    print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
    print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
    print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
    print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);//LED flashes
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  feedgps();
}

static void print_float(float val, float invalid, int len, int prec, int SD_val)
{
  char sz[32];
  if (val == invalid)
  {
    strcpy(sz, "*******");
    sz[len] = 0;
        if (len > 0) 
          sz[len-1] = ' ';
    for (int i=7; i<len; ++i)
        sz[i] = ' ';
    Serial.print(sz);

    if(SD_val == 1) SD_lat = sz;
    else if(SD_val == 2) SD_lon = sz;
    else if(SD_val == 3) SD_alt = sz;
  }
  else
  {
    Serial.print(val, prec);

     if (SD_val == 1) SD_lat = dtostrf(val,10,5,dtostrfbuffer);
    else if (SD_val == 2) SD_lon = dtostrf(val,10,5,dtostrfbuffer);
    else if (SD_val == 3) SD_alt = dtostrf(val,10,5,dtostrfbuffer);
    
    
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1);
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(" ");
  }
  feedgps();
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
  {
    Serial.print("*******    *******    ");
    SD_date_time = "invalid";
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
    SD_date_time = sz;
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  feedgps();
}

static bool feedgps()
{
  while (Serial3.available())
  {
    if (gps.encode(Serial3.read()))
      return true;
  }
  return false;
}

Any help on securing a consistent GPS signal and integrating a flight mode code into my script would be very helpful in moving me on. Apologies if my question lacks finesse - I am new to this!

Thanks,

Colin.

GPS signals are weak. You cannot count on receiving GPS signals indoors, or in any place that does not have a clear view of a good portion of the sky. Even vegetation can be a problem.

Some receivers and antenna combinations are much better than others, although if you get already get valid signals indoors, yours is better than many.

Hi jremington,

Many thanks for your comments.

Colin.

Hi Forum members,

I am still having problems making sure the programme is in flight mode.

I included the following section of code:

}
void setGPS_DynamicModel6()
{
 int gps_set_sucess=0;
 uint8_t setdm6[] = {
 0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06,
 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00,
 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C,
 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC };
 while(!gps_set_sucess)
 {
 sendUBX(setdm6, sizeof(setdm6)/sizeof(uint8_t));
 gps_set_sucess=getUBX_ACK(setdm6);
 }

but this is not accepted by my programme. I have been thinking that this may be because the inclusion (above) referrers to uxb - whereas my programme (posted earlier in this stream) may be in NMEA.

Can anyone help out with this problem?

Colin.

That looks like code from a different library. Unless you're trying to merge to two libraries, that's not going to work. Furthermore, merging the NMEA and ublox libraries is much more complicated than getting it to compile. There are two projects that do support the two different protocols (NMEA and UBX): Ardupilot and NeoGPS. I don't think you are experienced enough to use either one.

It would probably be easier to download the u-center PC app, configure the ublox Neo-7 device (no Arduino), and SAVE the configuration. You'll need a TTL Serial-to-USB converter module. Then reattach it to the Arduino, and it should still be using that configuration. No UBX code needed in the Arduino.

Cheers,
/dev

Thank you, dev.

Your comments confirm my suspicions and gives me a useful lead. I have downloaded the UBlox Centre and shall sort out a serial to USB module.

Again thanks for the very useful guidance.

Colin.