Problems with changing baud rate - device connected to Arduino Uno

Hi,

I’ve connected a GPS module to Arduino Uno via UART (named GPS_Serial).
Data is sent from the GPS module to Arduino, and from Arduino’s serial port to PC.
Initial baud rate of the GPS module is 4800 bps, and this is the baud I set for the serial port (from Arduino to PC) and to the GPS_Serial.
So far so good.

The problem arise when I try to change the baud rate.

I monitor the messages sent to the GPS, and if I recognise a change baud rate message - I send this message to the GPS and switch the baud rate of Serial - between Arduino and PC.
Here I have a problem. After setting the port in my terminal to the new baud rate (for instance 9600bps) - I get gibberish. Actually I get gibberish in every possible baud rate.

When I connect directly to the Tx pin - the pin on which the GPS sends data to Arduino - I get proper data in the new baud rate (9600 bps). Meaning the GPS module received the command. But I get gibberish from the serial port.

What can cause this problems?

I stated from flush() function, the added a reset function, but still getting gibberish on serial port.

This is the code - in this code I monitor 2 baud rate changes - to 115,200 bps, and to 9600 bps.
For each baud rate the implementation if different, but the result is the same - gibberish on the serial port.

#include <SoftwareSerial.h>

SoftwareSerial GPS_Serial(11,12);
// pin 11 is the Rx of Ardoino. Should be connected to the Tx of GNSS module
// pin 12 is the Tx of Ardoino. Should be connected to the Rx of GNSS module

String str = “”;
int Baud_Rate = 4800; // initial baud rate - default of the module

void setup()
{
Serial.begin(Baud_Rate);
GPS_Serial.begin(Baud_Rate);
Serial.println(“connection established”);
}

void(* resetFunc) (void) = 0; //declare reset function @ address 0

void loop()
{
//if we have some incomming serial data then…
if (GPS_Serial.available())
{
Serial.write(GPS_Serial.read());
}

while (Serial.available())
{
char c = Serial.read();
str += c;
if (c ==’\n’)
{
if (str.indexOf($PSRF100,1,115200,8,1,0*05") >= 0)
{
GPS_Serial.flush();
GPS_Serial.print(str);
delay(1000);
GPS_Serial.begin(115200);
delay(1000);
Serial.flush();

Serial.begin(115200);
}

else if (str.indexOf("$PSRF100,1,9600,8,1,0*0D") >= 0 )
{

GPS_Serial.print(str);
GPS_Serial.flush();
delay(1000);
GPS_Serial.end();
Serial.flush();
delay(2000);

Baud_Rate = 9600;
resetFunc(); //call reset

setup();
}

else
{
GPS_Serial.print(str);
}
str="";
}
}

}

Thanks a lot,
Mark

GPS_Serial.begin(115200);

SoftwareSerial won't work at 115200 baud. I think 38400 is its upper limit and 9600 would be even better.

If you need a high baud rate then you need an Arduino with a spare HardwareSerial port such as a Mega or a Leonardo or Micro.

Also, there is no point changing the baud rate on the Arduino unless you also change the baud rate on the device it is talking to.

...R

Hi Robin,

Thanks for the answer,
I took into account that 115,200 bps might be too high, so I went for the 9600 bps.
Please look at the code - there is a message of switching the baud rate to 9600 bps.

I do change the baud rate of the GPS device connected to Arduino from 4800 bps to 9600. I make sure that the device changed the transmitting data rate to 9600, by monitoring the Tx line (the line by which the GPS device transmits to Arduino). I get good valid data from this line.
So the communication between the GPS device to Arduino is fine.
My problem is that data coming from Arduino serial port to PC is gibberish. It is not 4800 bps as it was in the beginning, and not 9600 bps, and actually I scanned the whole range of baud rates - and didn't get valid data at any baud rate.

The communication properties of the GPS device are standard - 8 bits, no parity, one stop bit.

Thanks.

Mark_ORG:
I took into account that 115,200 bps might be too high, so I went for the 9600 bps.

Please post the updated version of the program in your next Reply.

And please post your program using the code button </> so it looks like this. See How to use the Forum

…R

Hi,

Thanks for the remark,
Here is my updated code:

#include <SoftwareSerial.h>

SoftwareSerial GPS_Serial(11,12);
// pin 11 is the Rx of Ardoino. Connected to the Tx of GNSS module
// pin 12 is the Tx of Ardoino. Connected to the Rx of GNSS module

String str = "";
int Baud_Rate = 4800;   // initial baud rate - default of the module

void setup()
{
    Serial.begin(Baud_Rate);
    GPS_Serial.begin(Baud_Rate);
    Serial.println("connection established");         
}

void(* resetFunc) (void) = 0; //declare reset function @ address 0

void loop()
{  
    //if we have some incomming serial data then..
    if (GPS_Serial.available())
    {
      Serial.write(GPS_Serial.read()); 
    }

    while (Serial.available())
    {
      char c = Serial.read();
      str += c; 
      if (c =='\n')
      {
        if (str.indexOf("$PSRF100,1,9600,8,1,0*0D") >= 0 )
        {
 
         GPS_Serial.print(str);
         GPS_Serial.flush();
         delay(1000);
         GPS_Serial.end();
         Serial.flush();
         delay(2000);
      // Serial.end();         // Tried with and without this line          

         Baud_Rate = 9600;
         resetFunc();                    //call reset.   Tried at first without making reset.

         setup();
        }


     else
        {
          GPS_Serial.print(str);          
        }
        str="";
      }
    }

}

Mark_ORG:
Here is my updated code:

Something is not quite right.

...R

The main problems:

Don’t print too much. It interferes with receiving consecutive GPS characters. You are printing ~3240 characters for each sentence received from the GPS device. The Arduino is spending all its time waiting to print (read this).

Don’t use SoftwareSerial. It disables interrupts for long periods of time, which will interfere with other parts of your program (or libraries). Read this for alternatives.

Don’t use String™. Here are many gory details about why you shouldn’t, and here’s a good Arduino-centric summary.

Don’t listen for the $PSIRF sentence, send it to change the baud rate:

    gpsPort.println( F("$PSRF100,1,9600,8,1,0*0D") ); // send the baudrate command

I think you probably need to do something like this:

//#define gpsPort Serial // BEST choice, but must rewire to pins 0 and 1

//#include <AltSoftSerial.h>
//AltSoftSerial gpsPort; // 2nd best choice, but must rewire to pins 8 and 9

#include <NeoSWSerial.h>
NeoSWSerial gpsPort( 11, 12 ); // 3rd best choice, works on pins 11 and 12

#include <NMEAGPS.h> // NeoGPS library
NMEAGPS gps;

void setup()
{
  Serial.begin( 4800 ); // Be sure the Serial Monitor window baud rate is also 4800

  gpsPort.begin( 4800 );                      // assume it's still @ 4800 (not needed if gpsPort *is* Serial)
  gpsPort.println( F("$PSRF100,1,9600,8,1,0*0D") ); // send the baudrate command
  gpsPort.flush();                            // and wait for it to be sent (1ms per character)

  delay( 200 );           // Let the GPS device start *sending* at new baudrate

  gpsPort.end();          // Throw away any received characters/garbage
  gpsPort.begin( 9600 );  // Start *receiving* at the new baudrate
}

void loop()
{
  if (gps.available( gpsPort )) {
    gps_fix fix = gps.read();

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

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

    Serial.println();
  }
}

This is the NMEAsimple example from the NeoGPS library. If you want to try it, NeoGPS, NeoSWSerial and AltSoftSerial are available from the Arduino IDE Library Manager, under the menu Sketch → Include Library → Manage Libraries. Be sure to follow the Installation instructions. NeoGPS has an NMEAdiagnostic program to auto-detect what the GPS device is doing.

Cheers,
/dev

Hi,
Can I suggest

    Serial.begin(115200);
    GPS_Serial.begin(Baud_Rate);

And leave the IDE monitor at 115200.
It doesn’t have to be the same as the GPS baudrate.

Just a thought.

Tom… :slight_smile:

It doesn't have to be the same as the GPS baudrate.

Unless, of course, he connects the GPS to Serial (pins 0 & 1), the most reliable way to connect to the GPS on an UNO...

BTW, NeoSWSerial doesn't support 4800. I would suggest changing the GPS baudrate permanently, but I don't know which GPS unit you are trying to connect. Which one?

TomGeorge:
Hi,
Can I suggest

    Serial.begin(115200);

GPS_Serial.begin(Baud_Rate);



And leave the IDE monitor at 115200.
It doesn't have to be the same as the GPS baudrate.

Just a thought.

Tom... :)

Plus one.

Thanks for the answers everybody,

TomGeorge:
Hi,
Can I suggest

    Serial.begin(115200);

GPS_Serial.begin(Baud_Rate);



And leave the IDE monitor at 115200.
It doesn't have to be the same as the GPS baudrate.

Just a thought.

Tom... :)

Yes - I tried it, and in general it works.
I establish the connection between the Arduino to PC @115200 bps, and leave is stable. Just changing the baud rate between the Arduino and GPS.
One problem that I see - sometimes, when the baudrate of Arduino to PC is 115200, and GPS to Arduino is 4800 - I send a command to GPS and it goes gibberish - not accepted. It doesn't happen all the time, just sometimes.

Regarding connecting the GPS to pins 0,1 - I just wonder - aren't those the pins of the main serial connection of the UNO? Parallel to the connector to USB?

I was busy with other things but will try today to implement it with NeoSWSerial.

BTW the GPS is CSR SiRFStar V.

Hi,
Thanks for the information.
I went through the NeoGPS library, and it can be very useful.
But right now I just need the was NMEA sentences, transmitted to PC.
On PC host SW the NMEA sentences will be parsed according to different demands and process the data.

-dev:
The main problems:

Don’t print too much. It interferes with receiving consecutive GPS characters. You are printing ~3240 characters for each sentence received from the GPS device. The Arduino is spending all its time waiting to print (read this).

Don’t use SoftwareSerial. It disables interrupts for long periods of time, which will interfere with other parts of your program (or libraries). Read this for alternatives.

Don’t use String™. Here are many gory details about why you shouldn’t, and here’s a good Arduino-centric summary.

Don’t listen for the $PSIRF sentence, send it to change the baud rate:

    gpsPort.println( F("$PSRF100,1,9600,8,1,0*0D") ); // send the baudrate command

I think you probably need to do something like this:

//#define gpsPort Serial // BEST choice, but must rewire to pins 0 and 1

//#include <AltSoftSerial.h>
//AltSoftSerial gpsPort; // 2nd best choice, but must rewire to pins 8 and 9

#include <NeoSWSerial.h>
NeoSWSerial gpsPort( 11, 12 ); // 3rd best choice, works on pins 11 and 12

#include <NMEAGPS.h> // NeoGPS library
NMEAGPS gps;

void setup()
{
  Serial.begin( 4800 ); // Be sure the Serial Monitor window baud rate is also 4800

gpsPort.begin( 4800 );                      // assume it’s still @ 4800 (not needed if gpsPort is Serial)
  gpsPort.println( F("$PSRF100,1,9600,8,1,0*0D") ); // send the baudrate command
  gpsPort.flush();                            // and wait for it to be sent (1ms per character)

delay( 200 );          // Let the GPS device start sending at new baudrate

gpsPort.end();          // Throw away any received characters/garbage
  gpsPort.begin( 9600 );  // Start receiving at the new baudrate
}

void loop()
{
  if (gps.available( gpsPort )) {
    gps_fix fix = gps.read();

Serial.print( F("Location: ") );
    if (fix.valid.location) {
      Serial.print( fix.latitude(), 6 );
      Serial.print( ‘,’ );
      Serial.print( fix.longitude(), 6 );
    }

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

Serial.println();
  }
}



This is the NMEAsimple example from the [NeoGPS](https://github.com/SlashDevin/NeoGPS) library. If you want to try it, NeoGPS, NeoSWSerial and AltSoftSerial are available from the Arduino IDE Library Manager, under the menu **Sketch -> Include Library -> Manage Libraries**. Be sure to follow the Installation instructions. NeoGPS has an NMEAdiagnostic program to auto-detect what the GPS device is doing.

Cheers,
/dev