Big issue with TinyGPS library, and now NTX2 radio....

I'm using a GPS with a transmitter for a high altitude balloon project. I want the code to work as follows:

  1. The GPS has a lock - the transmitter sends the relevant GPS data
  2. The GPS doesn't have a lock - the transmitter sends "Acquiring signal..." or similar message until GPS gets a lock

Case 1 works fine, when the GPS has a lock it transmits GPS data.

In trying to implement case 2, the transmitter repeatedly sends "Acquiring signal..." regardless of whether the GPS has a lock or not. I thought, maybe it's sending the message so often, the rest of the program doesn't have time to check if the GPS has a lock, so I implemented the following snippet of code to have the program only send "Acquiring signal..." every minute:

    TinyGPS gps;
    unsigned long check_GPS_fix = 0;
    gps.f_get_position(&current_lat, &current_lon, &fix_age);
    if (fix_age == TinyGPS::GPS_INVALID_AGE && ((check_GPS_fix - millis()) > 60000)) {
      rtty_txstring("Acquiring signal\n"); //rtty_txstring is just a function that operates the transmitter. You can think of it as Serial.print
      check_GPS_fix = millis();
    }

However, if you look closely, I implemented it wrong, as the second condition should be millis()-check_GPS_fix. Hence, the way it is written, the program should never enter this if statement. But it does! And it keeps sending "Acquiring signal" repeatedly, with no break between messages.

Earlier I tried setting up this functionality as follows:

    TinyGPS gps;
    if (gps.encode(<insert byte of serial data here>)) {
      //Get your GPS data here, send it along
    }
    else {
      rtty_txstring("Acquiring signal\n");
    }

But, as before, all I got was "Acquiring signal" on the radio.

I know the GPS has a lock because I can upload a sketch to just read GPS data through the serial monitor and I can see that it has a lock. We were outside so it had a clear view of the sky. Once I switched back to the radio sketch though, just back to "Acquiring signal"

So this leads ultimately to my question: How can I use TinyGPS to find out if the GPS unit has a signal lock or not and send that information in such a way that once it does get a lock, I can switch to transmitting GPS coordinates? Also, why the hell is it entering an if statement whose conditions have not been met? And don't tell me Murphy's law, because Murphy says anything that CAN go wrong will, but this is something that theoretically can't go wrong!!!!! :wink:

Below is the rest of my code, I wouldn't worry too much about rtty_txstring and rtty_txbyte since they just operate the radio and they work regardless of what data gets sent to them.

/*
  Radio Data Transmission
  Transmits data via Radiometrix NTX2
 
 Created 2011
 by Upu http://ava.upuaut.net
 RTTY code from Rob Harrison Icarus Project.
 
 Modified 2011
 by Nickolai http://www.nickolai.me for Project HAL
 
*/
//#include <NewSoftSerial.h>
//NewSoftSerial nss(3,4);
#include <SoftwareSerial.h>
SoftwareSerial nss = SoftwareSerial(3,4);
#include <TinyGPS.h>
TinyGPS gps;
#include <SD.h>


int RADIO_SPACE_PIN=6;
int RADIO_MARK_PIN=7;
char DATASTRING[500];
char SDcardbuffer[6000];
char GPSbyte;
float current_altitude = 0;
float current_lat = 0;
float current_lon = 0;
float current_speed = 0;
unsigned long fix_age = 0;
unsigned long time = 0;
unsigned long comp_time = 0;
unsigned long date = 0;
int writestart = 0;
int writetime = 0;
char writemessage[50];
unsigned long check_GPS_fix = 0;

int i = 0;
int j = 0;
 
void setup()
{
  pinMode(RADIO_SPACE_PIN,OUTPUT);
  pinMode(RADIO_MARK_PIN,OUTPUT);
  nss.begin(4800);
  if (!SD.begin(10))
  {
    rtty_txstring("Card failed or not present");
  }
  rtty_txstring("Card initialized");
}
 
void loop() 
{
  comp_time = millis() / 1000;
  GPSbyte = nss.read();
  SDcardbuffer[j] = GPSbyte;
  j++;
  if (gps.encode(GPSbyte)) {
    current_altitude = gps.f_altitude();
    gps.get_datetime(&date,&time,&fix_age);
    gps.f_get_position(&current_lat, &current_lon, &fix_age);
//  if (fix_age == TinyGPS::GPS_INVALID_AGE) {
//    rtty_txstring("Acquiring signal");
//  }
    sprintf(DATASTRING, "Time running: %d sec, Lat: %f, Lon: %f, Alt: %f m, Fix age: %d\n",comp_time,current_lat, current_lon, current_altitude, fix_age);
    rtty_txstring(DATASTRING);
    if (GPSbyte == 10 && j > 900) {
      writestart = millis();
      writetoSD("RESULTS.TXT", SDcardbuffer);
      j = 0;
      writetime = millis() - writestart;
      sprintf(writemessage, "Write time was: %d milliseconds",writetime);
      rtty_txstring(writemessage);
    }
  }
  if (GPSbyte == 10 && j > 900) {
    writestart = millis();
    writetoSD("RESULTS.TXT", SDcardbuffer);
    j = 0;
    writetime = millis() - writestart;
    sprintf(writemessage, "Write time was: %d milliseconds",writetime);
    rtty_txstring(writemessage);
  }
//gps.f_get_position(&current_lat, &current_lon, &fix_age);
//if (((check_GPS_fix - millis()) > 60000)) {
//  rtty_txstring("Acquiring signal\n");
//  check_GPS_fix = millis();
//}
}
 
void rtty_txstring (char * string)
{
 
    /* Simple function to sent a char at a time to
    ** rtty_txbyte function.
    ** NB Each char is one byte (8 Bits)
    */
 
    char c;
 
    c = *string++;
 
    while ( c != '\0')
    {
        rtty_txbyte (c);
        c = *string++;
    }
}
 
void rtty_txbyte (char c)
{
    /* Simple function to sent each bit of a char to
    ** rtty_txbit function.
    ** NB The bits are sent Least Significant Bit first
    **
    ** All chars should be preceded with a 0 and
    ** proceded with a 1. 0 = Start bit; 1 = Stop bit
    **
    */
 
    int i;
 
    rtty_txbit (0); // Start bit
 
    // Send bits for for char LSB first
 
    for (i=0;i<7;i++) // Change this here 7 or 8 for ASCII-7 / ASCII-8   
    {       if (c & 1) rtty_txbit(1);           else rtty_txbit(0);         c = c >> 1;
 
    }
 
    rtty_txbit (1); // Stop bit
}
 
void rtty_txbit (int bit)
{
        if (bit)
        {
          // high
                    digitalWrite(RADIO_MARK_PIN, HIGH);
                    digitalWrite(RADIO_SPACE_PIN, LOW);
        }
        else
        {
          // low
                    digitalWrite(RADIO_SPACE_PIN, HIGH);
                    digitalWrite(RADIO_MARK_PIN, LOW);
 
        }
//                delayMicroseconds(1680); // 600 baud unlikely to work.
                  //delayMicroseconds(3375); // 300 baud
                delayMicroseconds(10000); // For 50 Baud uncomment this and the line below.
                delayMicroseconds(10150); // For some reason you can't do 20150 it just doesn't work.
 
}
 
void callback()
{
  digitalWrite(RADIO_SPACE_PIN, digitalRead(RADIO_SPACE_PIN) ^ 1);
}


void writetoSD(char* filename, char* buffer)
{
  File datafile = SD.open(filename, FILE_WRITE);
  if (datafile)
  {
    datafile.println(buffer);
  }
  datafile.close();
}
//uint16_t gps_CRC16_checksum (char *string)
//{
//    size_t i;
//    uint16_t crc;
//    uint8_t c;
// 
//    crc = 0xFFFF;
// 
//    // Calculate checksum ignoring the first two $s
//    for (i = 2; i < strlen(string); i++)
//    {
//        c = string[i];
//        crc = _crc_xmodem_update (crc, c);
//    }
// 
//    return crc;
//}
  GPSbyte = nss.read();
  SDcardbuffer[j] = GPSbyte;

What does this code do if there is no serial data available. Yep, it just stuffed a -1 in the buffer. Probably not a good idea.

    if (fix_age == TinyGPS::GPS_INVALID_AGE && ((check_GPS_fix - millis()) > 60000)) {

Literals (60000) are interpreted as ints, in the absence of any contrary directives. There being nothing to tell the compiler otherwise, 60000 is stuffed into an int. What happens? The int overflows, resulting in a negative number. Now, since check_GPS_fix is less than millis(), the subtraction results in a negative number to. This negative number is compared to the negative number that 60000 stuffed into an int overflows to. The result may or may not be true.

You need to tell the compiler not to treat 60000 as an int, by suffixing L (long) or UL (unsigned long).

I should have mentioned that I'm not using an Arduino per se but a chipkit Uno32, which has a 32 bit processor, and I started with a delay of 20000, which shouldnt be stuffed into a negative number right?

Also, SoftwareSerial doesn't have an 'available' function, and NewSoftSerial has yet to be ported to chipkit boards :frowning:

I should have mentioned that I'm not using an Arduino per se but a chipkit Uno32, which has a 32 bit processor, and I started with a delay of 20000, which shouldnt be stuffed into a negative number right?

Yes, you should have mentioned all this. The value 20000 fits in an int without overflow.

Also, SoftwareSerial doesn't have an 'available' function, and NewSoftSerial has yet to be ported to chipkit boards

Still no excuse for assuming that nss.read() returns valid data every time. Why is the instance of SoftwareSerial called nss?

It seems to me that you have an awful lot going on in this sketch. Dump the radio stuff until you are getting valid data from the GPS. Or, if you are certain that the radio stuff is working, AND not interfering with SoftwareSerial (which uses polling, not interrupts) use that link to put out more debug statements.

How can I use TinyGPS to find out if the GPS unit has a signal lock or not

There is a section on the TinyGPS page labeled Establishing a fix that defines how to determine if the GPS has a fix.

Well, the GPS outputs data whenever it's powered up and I haven't had a problem with nss.read(). I called it nss because I was using NewSoftSerial until I switched to chipkit....

I can't just dump the radio stuff. If the GPS doesn't have a signal lock, I need to know and I need to transmit that knowledge over the radio. Yes there's a lot going on in the sketch, this is what happens when you're trying to have 3 relatively complex devices all working together. If the GPS loses signal during flight for whatever reason, I need to know that it's the GPS that lost signal and not the radio malfunctioning.

As you can see in the code from my initial post, I've seen that section on the TinyGPS website and tried to follow it to no avail. I'll try to restructure my code to put the parts that establish a fix before the rest, we'll see what happens but I'm not optimistic

I can't just dump the radio stuff.

Sure you can. Not in the final product, obviously, but while working on getting data from the GPS, create a sketch that does just that. Only when that works should you try to integrate that code into the bigger picture.

PaulS:

I can't just dump the radio stuff.

Sure you can. Not in the final product, obviously, but while working on getting data from the GPS, create a sketch that does just that. Only when that works should you try to integrate that code into the bigger picture.

nbelakovski:
I know the GPS has a lock because I can upload a sketch to just read GPS data through the serial monitor and I can see that it has a lock. We were outside so it had a clear view of the sky. Once I switched back to the radio sketch though, just back to "Acquiring signal"

I reorganized the main loop to look more similar to the notes on the TinyGPS page, but I'm still getting the same issue

void loop() 
{
  GPSbyte = nss.read();
  SDcardbuffer[j] = GPSbyte; j++;
  gps.f_get_position(&current_lat, &current_lon, &fix_age);
  if (fix_age == TinyGPS::GPS_INVALID_AGE) {
    rtty_txstring("Acquiring signal\n");
  }
  else if (fix_age > 5000) {
    rtty_txstring("Old data\n");
  }
  else {
  if (gps.encode(GPSbyte)) {
    current_altitude = gps.f_altitude();
    gps.get_datetime(&date,&time,&fix_age);
    gps.f_get_position(&current_lat, &current_lon, &fix_age);
//  if (fix_age == TinyGPS::GPS_INVALID_AGE) {
//    rtty_txstring("Acquiring signal");
//  }
    sprintf(DATASTRING, "Time running: %d sec, Lat: %f, Lon: %f, Alt: %f m, Fix age: %d\n",comp_time,current_lat, current_lon, current_altitude, fix_age);
    rtty_txstring(DATASTRING);
  }
  }
}

I added a Serial.print statement to the radio transmit functions so I can just go in there and see what's happening. All that happens is I get "Acquiring signal" constantly. And, again, I uploaded a sketch to just read from the GPS and it confirms that the GPS is indeed getting a signal lock.

  GPSbyte = nss.read();

GPSByte can still be -1.

  SDcardbuffer[j] = GPSbyte; j++;

Do you really want to store -1 in the buffer?

  gps.f_get_position(&current_lat, &current_lon, &fix_age);

You haven't, yet, verified that gps has been given a complete packet.

  if (gps.encode(GPSbyte)) {

What do you expect gps.encode() to do with the (potentially) -1?

    gps.f_get_position(&current_lat, &current_lon, &fix_age);

What value do you get for fix_age?

Does the value for fix_age get reset each time a new packet is received from the GPS, while it is locked? Can you simply reject any packets that have a fix_age greater than some value?

I don't know what kind of people devices people are using with Arduino but my GPS has never returned a -1. It's always spitting out data once it has power, even if it doesn't have a signal. Still, I put in a -1 checker in the code.

On your other concerns, gps.encode() returns 0 if the device doesn't have a lock, so if I'm trying to figure that out I need to put gps.f_getposition(&flat,&flon,&fix_age); outside that if statement.

When it doesn't have a lock, I don't get any value for fix_age. I try to print it but nothing happens.

I finally decided that TinyGPS isn't capable of doing what I need it to do so I started rolling my own solution. It seems to work OK now, but there are a few odd glitches that are puzzling me.

Following is the idea behind the solution and then the actual code:

  1. Check if GPSbyte == '$' ($ in ASCII is 36). Then set a flag to 1 and set the comparebuffer index to 0

  2. Record 10 bytes of data into the comparebuffer (which is initialized as char comparebuffer[9])

  3. After recording 10 bytes, reset the flag to 0, and check whether the first 9 bytes are equal to '$GPGSA,A,"
    The GPGSA sentence, from my experience, always displays an A for automatic in that first position. The alternative is M for manual, but I have yet to see that and perhaps one needs to send specific commands to the unit to activate manual mode.

  4. Do one of three things depending on the value of the last character in comparebuffer
    a- If the value is a 1, display "Acquiring signal"
    b- If the value is a 2, display "Weak signal"
    c- If the value is a 3, display "Lock acquired"
    d- If the value is none of the above, display an error message indicating what the value was

  5. Print the comparebuffer to screen for diagnostic purposes

An issue I have is that when it prints the comparebuffer, there's some "extra" stuff with it, as follows:

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,195

Acquiring signal
$GPGSA,A,100

Acquiring signal
$GPGSA,A,100

The 95's and 00's don't make any sense to me. Why are they there? How can they be there when comparebuffer is only initialized to 9? Also, when it does have a lock, it might print "Lock acquired" once or twice, but no more, it just proceeds to spit out GPS data. This second issue is admittedly not that big of a deal but I'm curious as to why it happens?

Code:

char GPSbyte;
float flat, flon;
unsigned long fix_age;
char comparebuffer[9];
int k=0;
int flag = 0;
float current_altitude = 0;
unsigned long time = 0;
unsigned long date = 0;
//unsigned long fix_age;
char DATASTRING[300];
char message[30];

void loop()
{
  GPSbyte = gps.read(); //Read a byte
  if (GPSbyte == -1) delay(100); //check if serial port is available
  else {
    if (GPSbyte == 36) k = 0; flag = 1; //if we're starting a new sentence, reset the index and trip the flag
    if (flag) {
      comparebuffer[k] = GPSbyte; //store data into the buffer
      k++;
    }
    if (k == 10) { //when the buffer reaches full size, clear the flag and begin analysis
      flag = 0;
      if (!strncmp(comparebuffer,"$GPGSA,A,",8)) { //check to make sure we have a GPGSA sentence, and that it looks ok
        switch (comparebuffer[9]) { //comparebuffer[9] is the value after the comma after A. It gives information regarding the fix
          case '1': //A 1 means there is no fix
            Serial.println("Acquiring signal");
            break;
          case '2': //A 2 means there is a 2D fix (3 satellites providing tracking information)
            Serial.println("Weak signal");
            break;
          case '3': //A 3 means there is a 3D fix (at least 4 satellites providing tracking)
            Serial.println("Lock acquired");
            break;
          default: //Sometimes the GPS sentences get corrupted, this is what there is a default. It's hardly necessary tho.
            sprintf(message, "Data corrupted, value is %c",comparebuffer[9]);
            Serial.println(message);
        }
        Serial.println(comparebuffer); //Print the comparebuffer to the screen for debugging purposes.
      }
    }
    if (parsed.encode(GPSbyte)) { //parsed.encode(GPSbyte) will return true when it receives full packets from GPS and GPS has a lock
      parsed.f_get_position(&flat, &flon, &fix_age);
      current_altitude = parsed.f_altitude();
      parsed.get_datetime(&date,&time,&fix_age);
      sprintf(DATASTRING, "Current time: %d sec, Lat: %f, Lon: %f, Alt: %f m, Fix age: %d",time,flat, flon, current_altitude, fix_age);
      Serial.println(DATASTRING);
    }
  }
}
  if (GPSbyte == -1) delay(100); //check if serial port is available

The comment is wrong for this code. The logic would make more sense like so:

void loop()
{
  GPSbyte = gps.read(); //Read a byte
  if (GPSbyte != -1)
  {
     // Use the byte read
  }
}

No delay is required. Either there is data or there isn't. Don't put in an artificial delay is there is none.

    if (GPSbyte == 36) k = 0; flag = 1; //if we're starting a new sentence, reset the index and trip the flag

The variable flag will ALWAYS be set to 1. Is that what you want? Why do you want to consult an ASCII table every time you look at this code?

    if (GPSbyte == '

works the same, with no need to look anything up.

      if (!strncmp(comparebuffer,"$GPGSA,A,",8)) { //check to make sure we have a GPGSA sentence, and that it looks ok

1, 2, 3, ... 8, 9. Hmmm, I count 9 characters in that string.

        switch (comparebuffer[9]) { //comparebuffer[9] is the value after the comma after A. It gives information regarding the fix

The compareBuffer variable has 9 elements, indexed 0 to 8. Why are you reading beyond the end of the array?

When it doesn't have a lock, I don't get any value for fix_age. I try to print it but nothing happens.

Printing it how?)


works the same, with no need to look anything up.

§DISCOURSE_HOISTED_CODE_4§


1, 2, 3, ... 8, 9. Hmmm, I count 9 characters in that string.

§DISCOURSE_HOISTED_CODE_5§


The compareBuffer variable has 9 elements, indexed 0 to 8. Why are you reading beyond the end of the array?

> When it doesn't have a lock, I don't get any value for fix_age. I try to print it but nothing happens.

Printing it how?

nbelakovski:
I don't know what kind of people devices people are using with Arduino but my GPS has never returned a -1.

Returning -1 is not a feature of the serial device, it's a feature of the Arduino serial library. If you call 'Serial.read()' when there's no serial data available, it will not block (as some other OS serial reads would do), but will return -1. To make sure that a serial byte is available, call 'Serial.available()' and check the return value, before calling 'Serial.read()'.

To make sure that a serial byte is available, call 'Serial.available()' and check the return value, before calling 'Serial.read()'.

SoftwareSerial does not provide an available() method.

@PaulS

Try NewSoftSerial available at arduiniana.org/libraries/newsoftserial.

It works fine!

Would you all kindly go read reply #2 and 3. There is a reason OP can't use NewSoftSerial.

@PaulS,

Sorry for the misunderstanding.

Would you mind mentioning chipkit Uno32 on the thread name to avoid confusion?

There's a second hardware serial port on the chipKIT Uno32 called Serial1 with pins RX=39 and TX=40.

I'm also using a chipKIT Uno32. Please join the chipKIT32/chipKIT-core · Discussions · GitHub to ask for a NewSoftSerial implementation on the chipKIT Uno32 as I did.

Good luck!

Thanks for the help PaulS. Being new to C I'm having trouble getting all the indices right but I looked at it again and implemented the correct numbering. It's no longer spitting out garbage at the end, and it seem to work OK, but there's a minor issue I have. Whenever it does have a lock, it reports the GPS data, but it doesn't report that it has a lock.

I moved the Serial.println(comparebuffer) line to outside the statement where it checks that it's a GPGSA sentence. Opening up serial monitor when it has a lock shows all sorts of sentences being printed out BUT GPGSA sentences.

Also, it doesn't go through the loop to spit out GPS data after moving that Serial.print line. It just prints the comparebuffer line after line. How is it that moving that one line causes it to become unable to go through the if(parsed.encode(GPSbyte)) statement?

Also, I was printing fix_age with Serial.print. Although I wasn't sure what would come out when it was supposed to be equal to TinyGPS::GPS_INVALID_AGE....

Here's the updated code:

char GPSbyte;
float flat, flon;
unsigned long fix_age;
char comparebuffer[10];
int k=0;
int flag = 0;
float current_altitude = 0;
unsigned long time = 0;
unsigned long date = 0;
//unsigned long fix_age;
char DATASTRING[300];
char message[30];

void setup()
{
  gps.begin(4800); //GPS communications occur at 4800 baud
  Serial.begin(115200); //This value can be any baud rate you like, so long as you can tune to it in the serial monitor
}

void loop()
{
  GPSbyte = gps.read(); //Read a byte
  if (GPSbyte != -1) { //check if serial port is available
    if (GPSbyte == 36) {//if we're starting a new sentence, reset the index and trip the flag
      k = 0;
      flag = 1; 
    }
    if (flag) {
      comparebuffer[k] = GPSbyte; //store data into the buffer
      k++;
    }
    if (k == 10) { //when the buffer reaches full size, clear the flag and begin analysis
      flag = 0;
      if (!strncmp(comparebuffer,"$GPGSA,A,",9)) { //check to make sure we have a GPGSA sentence, and that it looks ok
        switch (comparebuffer[9]) { //comparebuffer[9] is the value after the comma after A. It gives information regarding the fix
          case '1': //A 1 means there is no fix
            Serial.println("Acquiring signal");
            break;
          case '2': //A 2 means there is a 2D fix (3 satellites providing tracking information)
            Serial.println("Weak signal");
            break;
          case '3': //A 3 means there is a 3D fix (at least 4 satellites providing tracking)
            Serial.println("Lock acquired");
            break;
          default: //Sometimes the GPS sentences get corrupted, this is what there is a default. It's hardly necessary tho.
            sprintf(message, "Data corrupted, value is %c",comparebuffer[9]);
            Serial.println(message);
        }
      }
      Serial.println(comparebuffer); //Print the comparebuffer to the screen for debugging purposes.
    }
    if (parsed.encode(GPSbyte)) { //parsed.encode(GPSbyte) will return true when it receives full packets from GPS and GPS has a lock
      parsed.f_get_position(&flat, &flon, &fix_age);
      current_altitude = parsed.f_altitude();
      parsed.get_datetime(&date,&time,&fix_age);
      sprintf(DATASTRING, "Current time: %d sec, Lat: %f, Lon: %f, Alt: %f m, Fix age: %d",time,flat, flon, current_altitude, fix_age);
      Serial.println(DATASTRING);
    }
  }
}

On the other points, sorry for not being explicit from the start that I'm using a chipkit Uno32. Although this message is only just over a page long at this point so it wouldn't kill you to read the rest of the replies before posting your own.

I've talked to chipkit people about porting NewSoftSerial. They say it's using interrupts instead of polling which makes it difficult to port. Essentially it won't be done anytime soon and I'm planning to launch within a week.

I didn't use the chipkit's port 39/40 because I wanted it to be backwards compatible with Arduino in case I ran into other issues on the chipkit. SoftwareSerial seems to work fine despite the lack of an available function.

Thank you for sharing your result about SoftwareSerial on chipKIT Uno32.

nbelakovski:
I didn't use the chipkit's port 39/40 because I wanted it to be backwards compatible with Arduino in case I ran into other issues on the chipkit. SoftwareSerial seems to work fine despite the lack of an available function.

I faced the same problem and built a proxy serial port, actually a abstraction layer library, I could use on both environment, with NewSoftSerial on Arduino environment and Serial1 (pins 39 & 40) on chipKIT.

Please refer to my detailed post. Code included.

Best regards,

The code looks fine to me (except for the {s on the same line as the statement) and the 36 in the comparison (instead of '$'). Without seeing the output you are getting, I can't hazard a guess as to where the problem is.

I'd add more Serial.print() statements until I figured it out.

I coded up a solution that seemed to work towards the initial goal that I originally posted, but it had some small issues. When it didn't have a signal, it transmits "acquiring signal," but when it does have a signal, it goes straight to transmitting gps without saying "lock acquired." I figured that's not a big deal since it's working pretty much the way it was supposed to.

But now I have an issue with the radio I am using to transmit the data. The serial monitor output says that data is being sent, but i'm not picking it up on my receiver. All I pick up is a single tone that indicates the radio is getting power. Below is the main flight code, and a code that I use to check that the radio is working, which has shown that the radio can transmit data just fine:

#include <SoftwareSerial.h>
SoftwareSerial gps = SoftwareSerial(3,4);

//#include <NewSoftSerial.h>
//NewSoftSerial gps(3,4);

//HardwareSerial gps = Serial1;

#include <SD.h>
#include <TinyGPS.h>
TinyGPS parsed;

int RADIO_SPACE_PIN = 6;
int RADIO_MARK_PIN = 7;
char GPSbyte;
float flat, flon;
unsigned long fix_age;
char comparebuffer[10];
int i = 0;
int j = 0;
int k = 0;
int flag = 0;
float current_altitude = 0;
unsigned long time = 0;
unsigned long date = 0;
//unsigned long fix_age;
char DATASTRING[300];
char message[30];
char buffer[2000];

void setup()
{
  gps.begin(4800); //GPS communications occur at 4800 baud
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  if (!SD.begin(8))
  {
    rtty_txstring("Card failed or not present\n");
  }
  rtty_txstring("Card initialized\n");
}

void loop()
{
  GPSbyte = gps.read(); //Read a byte
  if (GPSbyte != -1) 
  { //check if serial port is available
    buffer[i] = GPSbyte;
    i++;
    if (i > 1800 && GPSbyte == 10)
    { //one there is enough data in the buffer, initiate the analysis routine
      j = 0;
      writetoSD("RESULTS.TXT", buffer);
      analyze(buffer);
      i = 0;
    }
  }
}

void analyze( char * bytes)
{
  while (j < i)
  {
    GPSbyte = bytes[j];
    if (GPSbyte == '

And the known working radio code:

/*
  HAL Radio Data Transmission Test
  Transmits data via NTX2
 
 Created 2011
 by Upu http://ava.upuaut.net
 RTTY code from Rob Harrison Icarus Project.
 
 */
 
int RADIO_SPACE_PIN=6;
int RADIO_MARK_PIN=7;
char DATASTRING[200];
 
void setup() {
  pinMode(RADIO_SPACE_PIN,OUTPUT);
  pinMode(RADIO_MARK_PIN,OUTPUT);
  Serial.begin(9600);
}
 
void loop() {
 
   sprintf(DATASTRING,"Daytona\n");
  
  noInterrupts(); //I've tried throwing this line and the interrupts(); line into the flight computer code but they don't seem to do anything. Removing them from this program has no effect on the radio (i.e. it still transmits just fine). I'm also not sure how this lines work with a chipkit...
  rtty_txstring (DATASTRING);
  interrupts();
}
 
void rtty_txstring (char * string)
{
 
    /* Simple function to sent a char at a time to
    ** rtty_txbyte function.
    ** NB Each char is one byte (8 Bits)
    */
 
    char c;
 
    c = *string++;
 
    while ( c != '\0')
    {
        rtty_txbyte (c);
        Serial.print(c);
        c = *string++;
    }
}
 
void rtty_txbyte (char c)
{
    /* Simple function to sent each bit of a char to
    ** rtty_txbit function.
    ** NB The bits are sent Least Significant Bit first
    **
    ** All chars should be preceded with a 0 and
    ** proceded with a 1. 0 = Start bit; 1 = Stop bit
    **
    */
 
    int i;
 
    rtty_txbit (0); // Start bit
 
    // Send bits for for char LSB first
 
    for (i=0;i<7;i++) // Change this here 7 or 8 for ASCII-7 / ASCII-8   
    {       if (c & 1) rtty_txbit(1);           else rtty_txbit(0);         c = c >> 1;
 
    }
 
    rtty_txbit (1); // Stop bit
}

void rtty_txbit (int bit)
{
        if (bit)
        {
          // high
                    digitalWrite(RADIO_MARK_PIN, HIGH);
                    digitalWrite(RADIO_SPACE_PIN, LOW);
        }
        else
        {
          // low
                    digitalWrite(RADIO_SPACE_PIN, HIGH);
                    digitalWrite(RADIO_MARK_PIN, LOW);
 
        }
//                delayMicroseconds(1680); // 600 baud unlikely to work.
//                  delayMicroseconds(3370); // 300 baud
                delayMicroseconds(10000); // For 50 Baud uncomment this and the line below.
                delayMicroseconds(10150); // For some reason you can't do 20150 it just doesn't work.
//                  delayMicroseconds(10000); // 100 baud (?)
 
}
 
void callback()
{
  digitalWrite(RADIO_SPACE_PIN, digitalRead(RADIO_SPACE_PIN) ^ 1);
}}

For what it's worth, the radio is a radiometrix NTX2. Here is the serial output from the first code (shortened a bit due to post character count limit):

 initialized
Analyzing
Acquiring signal
$GPGSA,A,1Analyzing
$GPRMC,001Analyzing
$GPGGA,001Analyzing
Acquiring signal
$GPGSA,A,1Analyzing
$GPRMC,001Analyzing
$GPGGA,001Analyzing
Acquiring signal
$GPGSA,A,1Analyzing
$GPRMC,001Analyzing
$GPGGA,001Analyzing
Acquiring signal
$GPGSA,A,1Analyzing
$GPRMC,001Analyzing
$GPGGA,001Buffering...Analyzing
$GPGGA,001Analyzing
Acquiring signal
$GPGSA,A,1Analyzing
$GPRMC,001Analyzing
$GPGGA,001Analyzing
Acquiring signal
$GPGSA,A,1Analyzing

Any help would be greatly appreciated, as I am trying to launch tomorrow!)
   {//if we're starting a new sentence, reset the index and trip the flag
     k = 0;
     flag = 1;
   }
   if (flag)
  {
     comparebuffer[k] = GPSbyte; //store data into the buffer
     k++;
   }
   if (k == 10 && flag)
   { //when the buffer reaches full size after the flag has tripped, clear the flag and begin analysis
     flag = 0;
     rtty_txstring("Analyzing\n");
     if (!strncmp(comparebuffer,"$GPGSA,A,",9))
     { //check to make sure we have a GPGSA sentence, and that it looks ok
       switch (comparebuffer[9])
       { //comparebuffer[9] is the value after the comma after A. It gives information regarding the fix
         case '1': //A 1 means there is no fix
           rtty_txstring("Acquiring signal\n");
           break;
         case '2': //A 2 means there is a 2D fix (3 satellites providing tracking information)
           rtty_txstring("Weak signal\n");
           break;
         case '3': //A 3 means there is a 3D fix (at least 4 satellites providing tracking)
           rtty_txstring("Lock acquired\n");
           break;
         default: //Sometimes the GPS sentences get corrupted, this is what there is a default. It's hardly necessary tho.
           sprintf(message, "Data corrupted, value is %c\n",comparebuffer[9]);
           rtty_txstring(message);
           rtty_txstring("\n");
       }
     }
     rtty_txstring(comparebuffer);
   }
   if (parsed.encode(GPSbyte))
   { //parsed.encode(GPSbyte) will return true when it receives full packets from GPS and GPS has a lock
     parsed.f_get_position(&flat, &flon, &fix_age);
     current_altitude = parsed.f_altitude();
     parsed.get_datetime(&date,&time,&fix_age);
     sprintf(DATASTRING, "$PRHAL,%d,%f,%f,%f,M,%d\n",time,flat, flon, current_altitude, fix_age);
     rtty_txstring(DATASTRING);
   }
   j++;
 }
 rtty_txstring("Buffering...");
}

void rtty_txstring (char * string)
{

/* Simple function to sent a char at a time to
   ** rtty_txbyte function.
   ** NB Each char is one byte (8 Bits)
   */

char c;

c = *string++;

while ( c != '\0')
   {
       rtty_txbyte (c);
       Serial.print(c);
       c = *string++;
   }
}

void rtty_txbyte (char c)
{
   /* Simple function to sent each bit of a char to
   ** rtty_txbit function.
   ** NB The bits are sent Least Significant Bit first
   **
   ** All chars should be preceded with a 0 and
   ** proceded with a 1. 0 = Start bit; 1 = Stop bit
   **
   */

int i;

rtty_txbit (0); // Start bit

// Send bits for for char LSB first

for (i=0;i<7;i++) // Change this here 7 or 8 for ASCII-7 / ASCII-8  
   {       if (c & 1) rtty_txbit(1);           else rtty_txbit(0);         c = c >> 1;

}

rtty_txbit (1); // Stop bit
}

void rtty_txbit (int bit)
{
       if (bit)
       {
         // high
                   digitalWrite(RADIO_MARK_PIN, HIGH);
                   digitalWrite(RADIO_SPACE_PIN, LOW);
       }
       else
       {
         // low
                   digitalWrite(RADIO_SPACE_PIN, HIGH);
                   digitalWrite(RADIO_MARK_PIN, LOW);

}
//                delayMicroseconds(1680); // 600 baud unlikely to work.
                 //delayMicroseconds(3375); // 300 baud
               delayMicroseconds(10000); // For 50 Baud uncomment this and the line below.
               delayMicroseconds(10150); // For some reason you can't do 20150 it just doesn't work.

}

void callback()
{
 digitalWrite(RADIO_SPACE_PIN, digitalRead(RADIO_SPACE_PIN) ^ 1);
}

void writetoSD(char* filename, char* buffer)
{
 File datafile = SD.open(filename, FILE_WRITE);
 if (datafile)
 {
   datafile.println(buffer);
 }
 datafile.close();
}


And the known working radio code:

§DISCOURSE_HOISTED_CODE_1§


For what it's worth, the radio is a radiometrix NTX2. Here is the serial output from the first code (shortened a bit due to post character count limit):

§DISCOURSE_HOISTED_CODE_2§


Any help would be greatly appreciated, as I am trying to launch tomorrow!