Can't read data from GPS module

I'm setting up an arduino system for a "space balloon" that's going to be launching soon(I'm working on this as a project with an engineering club at my University). I'm using the arduino to log data from sensors onto an SD card. However, one sensor that I cannot get it to take in data from is the GPS.

In the payload we have the "Byonics GPS4" GPS module, with the serial data output from it connected to both the Arduino and a HAM radio transmitter.

The GPS works just fine, I can see the location of it using aprs.fi from the HAM radio broadcast.

However, I cannot get the data from it using the arduino.

The GPS module outputs 4800 baud NMEA 0183 serial. From what I've read, that uses RS-232 electrical signalling.

As the GPS runs off of 5v power, it puts out a signal that goes from -5v to 5v(RS-232 uses the negative voltage, rather than a 0 voltage). Using a diode and a pull-down resistor I changed the -5v signal to 0v. I tested that on an oscilloscope, and it does work.

Now, I ran that into the RX1 port on my Arduino Mega board, but the data was garbled looking. Using the "Mega multple serial test" example code(slightly modified), I ran the GPS into the computer through USB. Here is what that looked like:

(the receiving serial is set to 4800 baud, line breaks are inserted after every 100 chars received)

The GPS data is supposed to look like: "$GPGGA,201548.000,3014.5529,N,09749.5808,W,1,07,1.5,225.6,M,-22.5,M,18.8,0000*78" (example data from TinyGPS library)

I also saw some information saying that TTL and RS-232 use opposite signalling for logical 1 and 0. That is, one uses +v as a logial 1, the other uses +v as a logical 0.

So, I added a not gate into the circuit, taking in the 0v and 5v signal (which I convert from -5v and 5v), and inverting it to a 5v an 0v signal. I verified that this was working with an oscilloscope. I fed this into the arduino, and got nothing. Rather than garbled data, I got no data. No characters coming in through the arduino's RX line.

So, I'm wondering what's going on here. Should I be doing some software transformation to the garbled looking data that I'm receiving? Is there something else I need to do to convert NMEA 0183 serial to TTL serial?

Any help you can offer would be really appreciated.

A MAX232 chip will solve all of your problems. Just whacking off the -5V signal isn't enough.

Unfortunately, I don't have one of those, and I don't have time to get one.

Is there any way to do this in software, or by using more general purpose hardware components?

Are you using one of those TinyTrak units to convert the RS232 data to the radio?

I'm using this: Byonics - MT-RTG

but with the Bionics GPS4 (for higher altitude readings).

You can invert the rs232 to ttl like below just using two resistors and an NPN transistor.

An opto coupler might provide another way to level-convert - without an oscilloscope its hard to know what's happening. I'm worried by you saying "diode and pulldown resistor" when you should be saying diode-clamp... Your circuit schematic?

The rs232 signal is already being inverted.

The circuit I have is: output from the gps goes to a diode, oriented so current is not allowed to flow towards the gps(to get rid of -5v output). Then, on the output of this diode, both a 20k resistor to ground is connected(so when the gps output goes to -5v, this line will just go to 0v), and a NOT gate(well, technically a NAND gate with both inputs connected together). The output from this NOT gate goes to the arduino mega RX1 pin.

On a digital oscilloscope I have connected the gps output and the converted signal(both at the same time). The conversion is working as intended, with a 5v gps signal being converted to a 0v signal into the arduino, and a -5v gps signal being converted to a 5v signal into the arduino. Both waveforms look the same, except for the voltage change.

Isn't that what needs to be done to convert rs232(at 5v) to TTL serial? I mean, it's not working, so I guess that isn't actually fully correct somehow. Any tips on what I could be doing wrong here?

I can post a shot of the oscillosope output if that would help, but the signal is already being inverted without a problem.

I just found a challenge with the Serial.print() routine and data size. Give this a try and see if it echos your GPS data ok.

uint8_t inByte;

void setup()
{
  Serial.begin(9600);
  Serial1.begin(4800);
}
void loop()
{
  if(Serial1.available())
  {
    inByte = Serial1.read();
    if(inByte != 0xFF) Serial.print(inByte);
  }
}

Serial1.available() may return a non-zero value, even tho there is nothing in the receive buffer. That is why the "if(inByte != 0xFF)".

Insure there are two wires from the RS-232 connector to the Arduino. One is signal, and the other is ground. Check to insure each is correct, especially ground.

Thanks for the tip, I'll give that code a try.

And, that is exactly how it's hooked up. ground and rs232 lines connected between gps and the arduino.

I thought the wires and connection would be good. Ham people rarely miss anything like that.

Let me know about the code. You did not post your code, so I couldn't see if you had used a char data type. In another topic, it had caused the compiler to assign a 32 bit value. Instead of returning -1 as 0xFF (8 bit), it was being returned and displayed as 0xFFFFFFFF (32 bit) using Serial.println(). That is why the uint8_t data type instead of a char on inByte.

This is the topic:
http://arduino.cc/forum/index.php/topic,74835.0.html

Add: Insure your baud rate at the lower right corner of the IDE serial window matches the baud rate set for Serial.begin(), or it will have that garbled appearance also.

Serial1.available() may return a non-zero value, even tho there is nothing in the receive buffer.

How?

PaulS:

Serial1.available() may return a non-zero value, even tho there is nothing in the receive buffer.

How?

My client.available() returned 1024 with nothing in the receive buffer. It was called a bug.

Mine is accurate, but another user was reporting the Serial1.available() was returning non-zero values and when the Serial1.read() was done, it returned 255 (-1) "no characters available". ?? That is why I said "may".

And, that is exactly how it's hooked up. ground and rs232 lines connected between gps and the arduino.

Maybe I mised something, but where is the GPS rs232 being converted into TTL that the arduino usually uses?

My client.available() returned 1024 with nothing in the receive buffer. It was called a bug.

Mine is accurate, but another user was reporting the Serial1.available() was returning non-zero values

Do you have a link to this other report?

The client instance you refer to is an instance of Client, and its available() method is known to have issues.

The Serial(n) instances are instances of the HardwareSerial class, and its available() method does not work the same way, and is not known to have any bugs.

Here is the other report:
http://arduino.cc/forum/index.php/topic,74835.0.html

The client instance you refer to is an instance of Client, and its available() method is known to have issues.

Your version has issues. Mine no longer does.
http://arduino.cc/forum/index.php/topic,68624.0.html

Here is the other report:

I've read that thread. You are the one that assumed that Serial.available() was not working.

WE are the the ones that assumed. This was robtillaart in reply #1 of that topic.

Do you use Serial.Available() in your code (wild guess what could be the problem)

This was robtillaart in reply #1 of that topic.

Rob was asking IF OP was using Serial.available(). I don't see anywhere in his reply anything that suggests that Serial.available() was returning incorrect data.

If Serial.available() was not used, the problem that OP described could happen. So, it was reasonable to ask if Serial.available() was being used.

I don't see how you got from there to the assumption that Serial.available() might have a problem. It's a far simpler function than the Client.available() function, with much less opportunity for error.

@PaulS: Thanks for calling my attention to that other topic. I see new posts were there. I will respond there also in a few minutes.
The test I suggested there did not work. That means he cannot assume the Serial1.available() routine is broken. Only if blocking with my code 0xFF (it should be int type, and 0xFFFF) would straighten out the data stream, but it did not. There may be characters in the buffer, and something is interpreting them as 0xFF.

Nothing returned from a card swiper would be 0xFF. It's all ascii text.