Reading serial data into a char array

Hi,

I am trying to collect the GPS data send from my GPS sensor. With a little sketch found on the internet. (tweaked it a little bit).
When I print the char C I get the following output (code below):

$GPRMC,070450.00,A,5222.02163,N,00636.04015,E,0.066,210414,A76
$GPVTG,T,M,0.066,N,0.122,K,A
22
$GPGGA,070450.00,5222.02163,N,00636.04015,E,1,07,1.28,15.8,M,46.0,M,6A
$GPGSA,A,3,07,04,20,23,02,13,10,2.36,1.28,1.98
0F
$GPGSV,4,1,13,02,33,305,26,04,57,243,32,06,11,041,31,07,26,171,307A
$GPGSV,4,2,13,08,03,182,22,10,51,288,31,13,85,166,30,16,08,080,14
77
$GPGSV,4,3,13,20,22,114,21,23,53,067,37,29,00,356,30,04,185,25*7C
$GPGSV,4,4,13,31,00,026,4D
$GPGLL,5222.02163,N,00636.04015,E,070450.00,A,A
6D

This is very nice. Now i want to collect rule for rule in a char array. When I print the buffer I get the following output.
And I am struggling for days with it. Cant find what is wrong. Guess something simple. The output misses chars, has odd breaks, etc.

$GPRMC,070916.00,A,5222.02204,N,00636.41,E,0.104,210414,A78
$GPVTG,T,M,0.916.00,A,5222.02204,N,00636.41,E,0.104,210414,A
78
VTG,TM,0.04,N,0.193,K,A2D
$GPGGA,070916.00,5222.022004,210414,A
78
VTG,TM,0.04,N,0.193,K,A2D
PGG,0916.,5220220,07,04,20,23,02,13,08,10,2.40,1GSV,4,1,13,02,34,303,29,04,56,239,31,0507,04,20,23,02,13,08,10,2.40,1GSV,4,1,13,0,3433,2,4,5,39,105,00,291,06,12,039,09
74
$GPGSV,4,2,1GSV,4,1,13,0,3433,2,4,5,39,105,00,291,06,12,039,0974
GSV42,13,07,28,171,31,08,05,182,25,10,53,288,16,13,86,13655,9
74
GSV42,13,07,28,171,31,08,05,182,25,10,53,288,16,13,86,165,7B
$GPGSV,4,4,13,30,05,185,22
41

The code:

#include <Arduino.h>
#include <SoftwareSerial.h>

SoftwareSerial gpsSerial = SoftwareSerial(8, 7);

#define GPSRATE 9600
#define GPS_BUFFER_SIZE 128

// Buffer die we gebruiken om data te verzamelen. 
// (Buffer we use to collect data)
char buffer[GPS_BUFFER_SIZE];

// Alle verzamelde data wordt in deze char array gezet totdat we iets nieuws gevonden hebben. 
// (After finding a full data string, we copy it to this one)
char gps_string[GPS_BUFFER_SIZE];

// Bijhouden waar we zijn met het verzamelen van tekens. 
// (Keep track of the chars in array)
int buffer_index = 0;

// De laatst gelezen character. (Last red char)
char c;

void setup()
{
	// Output naar de PC. (For output to PC
	Serial.begin(115200);

	// Start de verbinding naar de GPS sensor. 
	// (Start softSerial at 9600)
	gpsSerial.begin(GPSRATE);

	// Laat even weten dat we gestart zijn. 
	// (Let us know that we are started)
	Serial.print("GPS ... ");

	// Alles klaarzetten. (Reset)
	reset();

	// Eerste beetje jibrisch negeren. 
	// (Ignore the first jibrish that comes in)
	while (gpsSerial.available()) {
		if (gpsSerial.read() == '\r')
			Serial.println("gestart");
			break;
	}
}

void reset() {
	// Buffer leegmaken voor een volgende ronde. 
	// (Empty the write buffer)
	memset(buffer, 0, GPS_BUFFER_SIZE);

	// Start index aan het eind op 0 zetten! of bij een fout. 
	// (Reset the index)
	buffer_index = 0; 
}

void loop() {
	while (1) {
		c = gpsSerial.read();

		// Zooi filteren. 
		// (Ignore jibrish)
		if (c == -1) {
			continue;
		}

		//Serial.print(c);


		// Laatste 2 chars in de string zijn \r\n met de \n niets doen, bij de \r is de reeks al afgerond. 
		// (Last 2 chars of the string are \r\n. Ignore the \n. The string is already compleated by the \r)
		if (c == '\n') {
			continue;
		}

		// Buffer overflow gevonden. Stop er mee om schrijven buiten het geheugen gebied te voorkomen. 
		// (Found a buffer overflow. Reset and break to prefent problems
		if (buffer_index == GPS_BUFFER_SIZE - 1) {
			// Resetten want we hebben een overflow
			reset();
			break;
		}

		// Laatste character in de reeks gevonden. Buffer eindigen met een \0. 
		// (Found the last usefull char \r. Finish the string with \0)
		if (c == '\r') {
			buffer[buffer_index] = '\0';

			Serial.println(buffer);

			// Buffer kopiëren naar een nieuwe array. 
			// (Copy the buffer to a new array so that this is not overwritten in the next round until its clear)
			strcpy(gps_string, buffer);

			// Klaarmaken voor de volgende reeks. (Resetting for the next round)
			reset();

			break;
		}


		// Er gaat wat mis. Het eerste character is altijd een $. 
		// (Somthing is wrong. The procol starts always with a $)
		if (buffer_index == 0 && c != '

) {
//Serial.print(“ERROR Eerste char is een:”);
//Serial.println(c);
}

	buffer[buffer_index++] = c;
}

}

Alright now I am confused. When setting the Hardware serial to a baud rate of 9600 (Connection to my pc) printing the buffer is fine. What is up with that :S:S So this code below works but I cant explain why. (I adjusted the baud rate on the serial monitor as well. So it always matched the codes speed 9600<-> 9600 and 115200 <–> 115200) In my understanding Baud rate is just the speed of the serial connection. The numbers of chars per second send over that connection.

[EDIT]
Tested all the baud rates. Everything over 9600 gives jibrish. This explains why I didn’t get the error on (buffer_index == 0 && c != ‘$’) despite the fact that the first char printed was not a $. Is this a problem with using softserial and hardserial together ?

[EDIT 2]
This was all tested with an aduino pro mini. Now I used an arduino UNO. Exactly the same problems, but the jibrish is a lot less. Still some to many flaws.

#include <Arduino.h>
#include <SoftwareSerial.h>

SoftwareSerial gpsSerial = SoftwareSerial(8, 7);

#define GPSRATE 9600
#define GPS_BUFFER_SIZE 128

// Buffer die we gebruiken om data te verzamelen. 
// (Buffer we use to collect data)
char buffer[GPS_BUFFER_SIZE];

// Alle verzamelde data wordt in deze char array gezet totdat we iets nieuws gevonden hebben. 
// (After finding a full data string, we copy it to this one)
char gps_string[GPS_BUFFER_SIZE];

// Bijhouden waar we zijn met het verzamelen van tekens. 
// (Keep track of the chars in array)
int buffer_index = 0;

// De laatst gelezen character. (Last red char)
char c;

void setup()
{
	// Output naar de PC. (For output to PC
	Serial.begin(9600);

	// Start de verbinding naar de GPS sensor. 
	// (Start softSerial at 9600)
	gpsSerial.begin(GPSRATE);

	// Laat even weten dat we gestart zijn. 
	// (Let us know that we are started)
	Serial.print("GPS ... ");

	// Alles klaarzetten. (Reset)
	reset();

	// Eerste beetje jibrisch negeren. 
	// (Ignore the first jibrish that comes in)
	while (gpsSerial.available()) {
		if (gpsSerial.read() == '\r')
			Serial.println("gestart");
			break;
	}
}

void reset() {
	// Buffer leegmaken voor een volgende ronde. 
	// (Empty the write buffer)
	memset(buffer, 0, GPS_BUFFER_SIZE);

	// Start index aan het eind op 0 zetten! of bij een fout. 
	// (Reset the index)
	buffer_index = 0; 
}

void loop() {
	while (1) {
		c = gpsSerial.read();

		// Zooi filteren. 
		// (Ignore jibrish)
		if (c == -1) {
			continue;
		}

		//Serial.print(c);


		// Laatste 2 chars in de string zijn \r\n met de \n niets doen, bij de \r is de reeks al afgerond. 
		// (Last 2 chars of the string are \r\n. Ignore the \n. The string is already compleated by the \r)
		if (c == '\n') {
			continue;
		}

		// Buffer overflow gevonden. Stop er mee om schrijven buiten het geheugen gebied te voorkomen. 
		// (Found a buffer overflow. Reset and break to prefent problems
		if (buffer_index == GPS_BUFFER_SIZE - 1) {
			// Resetten want we hebben een overflow
			reset();
			break;
		}

		// Laatste character in de reeks gevonden. Buffer eindigen met een \0. 
		// (Found the last usefull char \r. Finish the string with \0)
		if (c == '\r') {
			buffer[buffer_index] = '\0';

			Serial.println(gps_string);

			// Buffer kopiëren naar een nieuwe array. 
			// (Copy the buffer to a new array so that this is not overwritten in the next round until its clear)
			strcpy(gps_string, buffer);

			// Klaarmaken voor de volgende reeks. (Resetting for the next round)
			reset();

			break;
		}


		// Er gaat wat mis. Het eerste character is altijd een $. 
		// (Somthing is wrong. The procol starts always with a $)
		if (buffer_index == 0 && c != '

) {
//Serial.print(“ERROR Eerste char is een:”);
//Serial.println(c);
}

	buffer[buffer_index++] = c;
}

}

npostma:
Now I used an arduino UNO. Exactly the same problems, but the jibrish is a lot less. Still some to many flaws.

There should be zero gibberish. The fact that you get 'something' means that they're mostly connected.

Check stop bits and parity on PC port and Arduino serial port. Most typical is called N-8-1 meaning no stop bits, 8 bits data, and 1 parity bit.

void loop() {
	while (1) {

I refuse to read code that contains a stupid infinite loop inside an infinite loop().

A GPS is NOT a beginner project. By the time you get to experimenting with a GPS, you should KNOW that loop() is called in an infinite loop and that adding another infinite loop is useless.

I refuse to read code that contains a stupid infinite loop inside an infinite loop().

Its a simple code example. A part of a bigger project. I am working on a telemetries project for my RC car. (Multiple temperature sensors, accelerometer (by i2c), GPS (serial), RPM (With a analog hall sensor)) sending the data over a 2.4 ghz module. All of this works, so I have a some experience, but I just cant explain the problems I am having. Because when I send it over 2.4 ghz, to an other arduino pro and printing this on screen over with a rate of 115200 there is no jibrish. But then again, on that other end i'm not using softserial.

while(1) is not in the original code, that gives the exact same problem. In the original code there is a while(running), and instead of the break; there is running = false. I didn't want to post to much code because 1 this example has the same problem and this code is small and readable.

It is not clear what your problem is. If you are reading from a GPS and printing to the Serial Monitor WITHOUT ANY RADIOS then, the baud rates are all correct, and HardwareSerial and SoftwareSerial are working correctly.

If adding radios causes the problems, then, clearly the radios are the problem.

This is why i didn't want to confuse this thread with the rest of my project. The example in this thread has the exact same problem as in my main project.

1 - simple code sketch -> reading problem with baud rate higher then 9600
2 - main project reading serial from transmitter before sending data -> reading problem with baud rate higher then 9600
3 - main project, sending data over RF2.4 mhz to receiver then reading serial -> no problem reading over 115200 baud rate

I hope its more clear now. Sorry for the confusion.

I am trying to finish my project but there are still these bumps in the road that I want to understand before i'll do.

1 - simple code sketch -> reading problem with baud rate higher then 9600

It's like pulling teeth to get you to clarify anything. You have two baud rates. One is defined by the hardware (the GPS). You can't just make up any old baud rate for that one. The other one, between the Arduino and the PC, can be changed - as long as both ends agree on what the baud rate is.

Now, which one causes problems when it is above 9600?

The connection to the PC. cant be set higher than 9600. The GPS is fixed on 9600 so softserial has to use 9600.

The connection to the PC. cant be set higher than 9600.

Why not? What application on the PC is listening to the serial port? Are you changing the speed in that application, too?

I have no clue why not. Thats the strange thing. I taught I got a corrupted buffer. Turns out that the jibrisih I was reading came from the baud rate settings.

Tried the arduino monitor, Visual micro monitor in Visual Studio and I tried to listen to the COM port in C#.
In all of those 3 situations I can change the baud rate. Set it to the same speed as in the arduino code. But all of them giving me the same scrambled output. Unless I used 9600.

Have you tried something simple that does not involve reading from a GPS? Just have loop send the same string once a second. Change the length of the string to see if that is a factor. Run through all the baud rates.

Other people can read from GPSs at 9600 baud using SoftwareSerial, and send that data to the PC, using HardwareSerial, at 115200. There is no reason that you shouldn't be able to, too.

Thanks I am going to give it a try.

I also taught of the possibility that visual micro was also sending debug information over serial, that could conflict. But turning that off does not change anything.