Neo-6M GPS shield - update faster than 1Hz

Hello,

I'm using a Neo-6m GPS shield with an Uno card and the TinyGPS++ library. All working well with GPS updates every second. I read however that the 1Hz update is the default and that the Neo-6m can update with a rate as fast as 5Hz. How can I configure the Neo-6m to do this? Do I need to use a different library?

Thanks,

How can I configure the Neo-6m to do this?

If you don't care about getting a confirmation ACK for the configuration command, you can just send the bytes:

const unsigned char UBLOX_INIT[] PROGMEM = {
  // Rate (pick one)
//  0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz)
  //0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz)
  0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39 //(1Hz)
};

void setup()
{
    ...

  gpsPort.begin( GPS_BAUDRATE );
  // send configuration data in UBX protocol
  for(unsigned int i = 0; i < sizeof(UBLOX_INIT); i++) {                        
    gpsPort.write( pgm_read_byte(UBLOX_INIT+i) );
  }
}

At the higher update rates, you must configure the baud rate to be higher than 9600 and/or disable sentences that you don't use. Here are the binary commands to disable various NMEA sentences:

  // Disable NMEA
//  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off
//  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, // GxVTG off

You can also disable/enable NMEA sentences with a text command:

    $PUBX,40,GLL,1,0,0,0,0,0*5D

That enables the GLL sentence on the serial port.

    $PUBX,41,1,0007,0003,19200,0*25

That sets the GPS modules baud rate to 19200. Then you'll have to change the Arduino's baud rate to match. See the spec for other commands and values. Or...

Do I need to use a different library?

Yes. :slight_smile: I wrote the NeoGPS library to be smaller, faster and more accurate than all other libraries. If you really need higher update rates, NeoGPS is the best choice. It also has some ublox-specific capabilities, but I'm not sure that you need those. It will watch for an acknowledgement to ublox configuration commnds.

NeoGPS does have an NMEA send method that will calculate the checksum of these text commands for you:

    gps.send_P( &gpsPort, F("PUBX,41,1,3,3,38400,0") );

This sets the GPS device's baud rate to 38400.

Even if you don't use it, I would recommend looking at the examples for a good program structure. Many other libraries' examples will break when you try to modify them. The NeoGPS Troubleshooting page has lots of information about how to avoid some of these problems.

I would also suggest using AltSoftSerial on pins 8 & 9 for the GPS device. SoftwareSerial is very inefficient, because it disables interrupts for long periods of time. This will interfere with other parts of your sketch.

If you really can't use pins 8 & 9, you should use my NeoSWSerial. It is almost as good as AltSoftSerial, and it works at baud rates 9600, 19200 and 38400.

Cheers,
/dev

Thanks a lot /dev for the detailed reply. I had come across NeoGPS before, I'll have another look. I am using pins 8 and 9 for the GPS presently, so I will also try AltSoftSerial.

Re. disabling the NMEA sentences, do I add that block of binary to the "UBLOX_INIT" function?

How to i use the "text" commands you listed to change the baud rate of the GPS?

I'm using a second shield at 115200baud. Can I change the GPS baud rate with the text: $PUBX,41,1,0007,0003,115200,0*25 ?

Cheers

Re. disabling the NMEA sentences, do I add that block of binary to the "UBLOX_INIT" function?

Yes, or send the text command instead.

How to i use the "text" commands you listed to change the baud rate of the GPS?

You should read the spec, section 21.12, Set Protocols and Baudrate. I gave one baud rate you could send, with the required checksum:

    gpsPort.print( F("$PUBX,41,1,0007,0003,19200,0*25\r\n") );

Or you could use the NeoGPS method:

    gps.send_P( &gpsPort, F("PUBX,41,1,3,3,38400,0") );

I'm using a second shield at 115200 baud. Can I change the GPS baud rate with the text: $PUBX,41,1,0007,0003,115200,0*25 ?

No, but only because the checksum is not correct. "What's a checksum?", you ask. Read the spec, section 16, NMEA Protocol Overview. :wink:

That's one reason I added the send_P method to NeoGPS. You can also use an online "NMEA checksum calculator" to give you the correct values for a specific command. Then print the command as shown above.

Also, 115200 is not recommended for a software serial port. If you were using SoftwareSerial, you couldn't listen to two GPS devices anyway. I would not recommend going above 38400 for most configurations.

Have you figured out which sentences you need? This will determine the minimum baud rate. Count the typical number of characters that the desired sentence(s) contain, multiply by 10 (bits transmitted per character), and multiply by the update frequency (e.g. 5Hz).

Let's say you only need the RMC sentence. The example given in the spec, section 20.10, is

    $GPRMC,083559.00,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A*57

This consists of 71 characters, plus a CR and a LF, for a total of 73 characters. Use 75 to have a few extra character times. Then

    Min Baud Rate = 75 chars/sentence * 10 bits/char * 5 sentences/second
                  = 3750 bits/second

So 9600 is plenty fast.

Cheers,
/dev

Thanks again /dev. I'm using only latitude and longitude so I believe the message I need is GLL. Oddly, and still using TinyGPS++, when I disable the NMEA sentences other than GLL and change the rate to 5Hz, the updates still come no faster than once a second. Even with GLL disabled lat and lon values are still sent, so I wonder if the ublox config changes are having any effect.

If you wouldn't mind, please have a look over my sketch below, which includes code for an additional motion sensor

cheers,

#include "TinyGPS++.h"
#include <SoftwareSerial.h>

#include "NAxisMotion.h"        //Contains the bridge code between the API and the Arduino Environment
#include <Wire.h>

static const int RXPin = 9, TXPin = 8;
static const uint32_t GPSBaud = 9600;

const unsigned char UBLOX_INIT[] PROGMEM = {
 // Rate (pick one)
//  0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz)
 0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz)
// 0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39, //(1Hz)
  // Disable specific NMEA sentences
 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off
 //0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off
 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off
 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off
 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off
 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47 // GxVTG off
};

/*uint8_t gps_config_change[63]={// Rate to 250 ms
                        // 0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xFA, 0x00, 0x01, 0x00, 0x01, 0x00,
                        // 0x10, 0x96,
                        // Rate to 200 ms
                         0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xC8, 0x00, 0x01, 0x00, 0x01, 0x00,
                         0xDE, 0x6A,
                         // Baud Change
                        // 0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 
                        // 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00,
                        // 0x00, 0x00, 0xBF, 0x78,
                        
                        0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0xC2, 
                        0x01, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x7E,  
                          
                          // Save Config
                         0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 
                         0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1D, 0xAB}; 
                         */
// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

NAxisMotion mySensor;         //Object that for the sensor 
unsigned long lastStreamTime = 0;     //To store the last streamed time stamp
const int streamPeriod = 20;          //To stream at 50Hz without using additional timers (time period(ms) =1000/frequency(Hz))

   unsigned long lat = 0;
   unsigned long lng = 0;

void setup()
{
Serial.begin(115200);
ss.begin(GPSBaud);
 for(unsigned int i = 0; i < sizeof(UBLOX_INIT); i++) {                        
   ss.write( pgm_read_byte(UBLOX_INIT+i) );
 };



  I2C.begin();                    //Initialize I2C communication to the let the library communicate with the sensor.
 //Sensor Initialization
 mySensor.initSensor();          //The I2C Address can be changed here inside this function in the library
 mySensor.setOperationMode(OPERATION_MODE_NDOF);   //Can be configured to other operation modes as desired
 
 mySensor.setUpdateMode(MANUAL);  //The default is AUTO. Changing to MANUAL requires calling the relevant update functions prior to calling the read functions
 //Setting to MANUAL requires fewer reads to the sensor  
}

void loop()
{
   while (ss.available() > 0) {
     if (gps.encode(ss.read())){
       if (gps.location.isValid())
         {
           if (gps.location.isValid()) {
             float latf = gps.location.lat();
             float lngf = gps.location.lng();
             lat = (latf + 90) *  (2147483647 / 180);
             lng = (lngf + 180) * (2147483647 / 360);

            }
         }
      }
   }
 if (millis() > 5000 && gps.charsProcessed() < 10)
 {
   Serial.println(F("No GPS detected: check wiring."));
   while(true);
 }
 // This sketch displays information every time a new sentence is correctly encoded.

   if ((millis() - lastStreamTime) >= streamPeriod)
 {
   lastStreamTime = millis();    
   mySensor.updateEuler();        //Update the Euler data into the structure of the object
   //mySensor.updateCalibStatus();  //Update the Calibration Status

  float headingf;
  // correct heading data for 90deg rotation of hardware 
  headingf = mySensor.readEulerHeading() - 90;  
  if (headingf < 0) {
   headingf = (360 + headingf);
  }; 
   
 //  adjust data to suit the receiving software software 

  if (headingf > 180) {
   headingf = -180 + (headingf - 180);
  }; 
  headingf = headingf * 3.1415926535898 / 180; // convert heading to radians
  float rollf;
  rollf = mySensor.readEulerRoll();
  if (rollf > 180) {
   rollf = -180 + (rollf - 180);
  }; 
  rollf = rollf * 3.1415926535898 / 180; // convert to radians

  float pitchf;
  pitchf = mySensor.readEulerPitch() * -1;
  if (pitchf > 180) {
   pitchf = -180 + (pitchf - 180);
  }; 
  pitchf = pitchf * 3.1415926535898 / 180; // convert to radians

  // note pitch and roll are swapped below because I rotate z axis of device bt 90 degrees 
   
   unsigned int heading = (headingf + 3.1415926535898) * 100;
   unsigned int pitch = (rollf + 3.1415926535898) * 100;         
   unsigned int roll = (pitchf + 3.1415926535898) * 100;
   Serial.write(251); 
   Serial.write(252); 
   Serial.write(253); 
   Serial.write(254); 
   Serial.write(heading >> 8); //high 8bits 
   Serial.write(heading & 255);  //low 8bits 
   Serial.write(roll >> 8); 
   Serial.write(roll & 255); 
   Serial.write(pitch >> 8); 
   Serial.write(pitch & 255); 

   Serial.write(lat & 255); 
   Serial.write((lat >> 8) & 255); 
   Serial.write((lat >> 16) & 255);  
   Serial.write((lat >> 24) & 255); 
   Serial.write(lng & 255); 
   Serial.write((lng >> 8) & 255); 
   Serial.write((lng >> 16) & 255);  
   Serial.write((lng >> 24) & 255); 

   Serial.write(255); 
 }
}

Please edit your post and insert code tags around your sketch

... so it looks like this.

You can use Quick Edit to put "[code]" before the 1st line of the sketch and "[/code]" after the last line of your sketch. Then press Save.

It makes it easier for us to see your entire post with a nested scrolling code block.

It makes it easier for us to Select the code and copy it to our own windows.

It prevents various C++ coding snippets from being interpreted as formatting tags. For example, an array index like [i] would be interpreted as italic formatting. The rest of the sketch appears italicized, and the [i] disappears. Smiley faces appear in the weirdest places.

Thanks.

thanks - have added the tags

These two lines are wrong:

#include "TinyGPS++.h"
#include <SoftwareSerial.h>

:wink:

Seriously, though. I wrote NeoGPS because I was tired of fixing problems in other libraries. I recommend AltSoftSerial because it is more reliable when the Arduino has other things to do (Serial writes, I2C operations, etc.). I maintain NeoSWSerial because it is more reliable and efficient than SoftwareSerial, and does not require two specific pins.

Since I am not going to debug using those two libraries again, I will suggest the problems that they typically cause:

  • The ZDA sentence is enabled in the NEO-6M by default. If you had tried NMEAorder.ino, you may have noticed that. ZDA disable command added below.

  • Other libraries do not help you sort out sentences (GLL+ZDA+RMC etc.) from the update interval (groups of those sentences at 5Hz). NeoGPS provides complete fixes, not sentences, at the update rate.

  • SoftwareSerial disables interrupts for long periods of time, which can interfere with other parts of your sketch, or with other libraries you are using. It can use 95% of the CPU time. AltSoftSerial and NeoSWSerial are hundreds of times more efficient than SoftwareSerial.

Here is a NeoGPS+AltSoftSerial version of your sketch:

#include <NMEAGPS.h>
#include <AltSoftSerial.h>

#include "NAxisMotion.h"        //Contains the bridge code between the API and the Arduino Environment
#include <Wire.h>

NMEAGPS       gps;
gps_fix       fix;
bool          receivedFix = false;
unsigned long lat = 0;
unsigned long lng = 0;

static const uint32_t GPSBaud = 9600;
AltSoftSerial gpsPort;  //  only use RXPin = 9, TXPin = 8

const unsigned char UBLOX_INIT[] PROGMEM = {
  // Rate (pick one)
  //0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz)
  0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz)
  //0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39, //(1Hz)

  // Disable specific NMEA sentences
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off
  //0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, // GxVTG off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x08,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x5C, // GxZDA off
};

NAxisMotion mySensor;
unsigned long lastStreamTime = 0;     // the last streamed time stamp
const int streamPeriod = 20;          // stream at 50Hz (time period(ms) =1000/frequency(Hz))


void setup()
{
  Serial.begin(115200);
  gpsPort.begin(GPSBaud);

  for (size_t i = 0; i < sizeof(UBLOX_INIT); i++) {                        
    gpsPort.write( pgm_read_byte(UBLOX_INIT+i) );
  };


  I2C.begin();

  mySensor.initSensor();   //The I2C Address can be inside this function in the library
  mySensor.setOperationMode(OPERATION_MODE_NDOF);
  mySensor.setUpdateMode(MANUAL);
    // The default is AUTO. Changing to MANUAL requires calling the 
    // relevant update functions prior to calling the read functions
    // Setting to MANUAL requires fewer reads to the sensor  
}

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

    if (fix.valid.location) {
      // Using the floating-point forms loses accuracy, because 
      //   they only have ~6 significant digits.

      lat = (fix.latitude () +  90.0) * (2147483647 / 180);  // fix.latitudeL() would be better
      lng = (fix.longitude() + 180.0) * (2147483647 / 360); // fix.longitudeL()
      
      //  I don't think this calculation does what you expect.  It
      //   introduces additional errors, including overflow
      //   that loses the top bits.  o_O
    }

    receivedFix = true;
  }

  if ((millis() > 5000) && !receivedFix) {
    Serial.println( F("No GPS detected: check wiring.") );
    while(true);
  }


  if ((millis() - lastStreamTime) >= streamPeriod)
  {
    lastStreamTime = millis();    
    mySensor.updateEuler();
    //mySensor.updateCalibStatus();

    // correct heading data for 90deg rotation of hardware 
    float headingf = mySensor.readEulerHeading() - 90;  
    if (headingf < 0) {
      headingf = (360 + headingf);
    }
    
    //  adjust data to suit the receiving software
    if (headingf > 180) {
     headingf = -180 + (headingf - 180);
    }
    headingf = headingf * PI / 180; // convert heading to radians

    float rollf = mySensor.readEulerRoll();
    if (rollf > 180) {
     rollf = -180 + (rollf - 180);
    }
    rollf = rollf * PI / 180; // convert to radians

    float pitchf = mySensor.readEulerPitch() * -1;
    if (pitchf > 180) {
      pitchf = -180 + (pitchf - 180);
    }
    pitchf = pitchf * PI / 180; // convert to radians

    // note pitch and roll are swapped below because I rotate z axis of device by 90 degrees 
    
    unsigned int heading = (headingf + PI) * 100;
    unsigned int pitch   = (rollf    + PI) * 100;         
    unsigned int roll    = (pitchf   + PI) * 100;

    Serial.write(251); 
    Serial.write(252); 
    Serial.write(253); 
    Serial.write(254); 

    // If you write LSB then MSB, you could just
    //    Serial.write( &heading, sizeof(heading) );
    Serial.write(heading >> 8); //high 8bits 
    Serial.write(heading & 255);  //low 8bits 
    Serial.write(roll >> 8); 
    Serial.write(roll & 255); 
    Serial.write(pitch >> 8); 
    Serial.write(pitch & 255); 

    // For some reason, you are writing the lat/lon as Little Endian,
    //  but the heading/roll/pitch are written as Big Endian.  On an UNO,
    //  you can do this for the lat/lon:
    Serial.write( (unsigned char *) &lat, sizeof(lat) );
    Serial.write( (unsigned char *) &lng, sizeof(lng) );

    Serial.write(255);
    
    // NOTE: If all these pieces were in a struct, you could write the whole struct
    //    with one statement:
    //
    //      Serial.write( (unsigned char *) myStruct, sizeof(myStruct) );
    //
    // This could include all constant bytes, too.

  }
}

This works for me. No sensor, of course.

I would also suggest deleting the obvious comments:

        //mySensor.updateCalibStatus();  //Update the Calibration Status

You don't say? :slight_smile:

I think you need to look at the output format. Can you change the "receiving software"? You are losing significant digits, and some values are written Big Endian and others are written Little Endian. That's pretty weird.

I just added an example for setting the update rate and baud rates. It takes commands from the Serial Monitor window.

Very generous of you to send this, thanks a lot. Thanks also for pointing out the errors in the transmission of latitude and longitude. I see that fix.latitudeL() and fix.longitudeL() are signed longs that can be divided by 10^7 to get back to floats (if needed). What's the best method to transmit these numbers over the serial port to my "receiving software"? I'm worried now about doing this incorrectly... And yes, I can modify the receiving software, so I'll tidy up the inconsistencies.
All the best!

With the help of google, found a solution.

Where lat = fix.latitudeL()

unsigned char buf[sizeof(long int)];
memcpy(buf,&lat,sizeof(long int));
Serial.write(buf,sizeof(buf));

This is unravelled correctly as a signed long by the receiving program.

All the best!

Did you try what I put in the code?

   //  ...On an UNO,
    //  you can do this for the lat/lon:
    Serial.write( (unsigned char *) &lat, sizeof(lat) );
    Serial.write( (unsigned char *) &lng, sizeof(lng) );

And if you put everything in a struct:

struct message_t
{
  int32_t lat;
  int32_t lng;
  uint16_t roll;
  uint16_t pitch;
  uint16_t yaw;
};

message_t message;

void loop()
{
   ...

  message.lat = fix.latitudeL();
  message.lng = fix.longitudeL();

   ...

  message.roll = (pitchf   + PI) * 100;

   ...

  Serial.write( (uint8_t *) &message, sizeof(message) );

Cheers,
/dev

No, sorry, I hadn't. I'd assumed that it would only work with unsigned values. I've now implemented all your suggestions, including the struct, fixed the receiving program to suit, and it's all working and is much tidier.

Doing a test now outside however, I'm not convinced that the Neo-6M is giving any unique updates faster than 1Hz. I wonder why that would be? I'll be able to test again tomorrow afternoon.
Cheers and thanks,

#include <NMEAGPS.h>
#include <AltSoftSerial.h>

#include "NAxisMotion.h"        //Contains the bridge code between the API and the Arduino Environment
#include <Wire.h>

NMEAGPS       gps;
gps_fix       fix;
bool          receivedFix = false;
//unsigned long lat = 0;
//unsigned long lng = 0;
long int lat = 0;
long int lng = 0;

struct message_t
{
  uint16_t heading;
  uint16_t roll;
  uint16_t pitch;
  int32_t lat;
  int32_t lon;
};
message_t message;

static const uint32_t GPSBaud = 9600;
AltSoftSerial gpsPort;  //  only use RXPin = 9, TXPin = 8

const unsigned char UBLOX_INIT[] PROGMEM = {
  // Rate (pick one)
  //0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz)
  0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz)
  //0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39, //(1Hz)

  // Disable specific NMEA sentences
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off
  //0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, // GxVTG off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x08,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x5C, // GxZDA off
};

NAxisMotion mySensor;
unsigned long lastStreamTime = 0;     // the last streamed time stamp
const int streamPeriod = 20;          // stream at 50Hz (time period(ms) =1000/frequency(Hz))


void setup()
{
  Serial.begin(115200);
  gpsPort.begin(GPSBaud);

  for (size_t i = 0; i < sizeof(UBLOX_INIT); i++) {                        
    gpsPort.write( pgm_read_byte(UBLOX_INIT+i) );
  };


  I2C.begin();

  mySensor.initSensor();   //The I2C Address can be inside this function in the library
  mySensor.setOperationMode(OPERATION_MODE_NDOF);
  mySensor.setUpdateMode(MANUAL);
    // The default is AUTO. Changing to MANUAL requires calling the 
    // relevant update functions prior to calling the read functions
    // Setting to MANUAL requires fewer reads to the sensor  
}

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

    if (fix.valid.location) {
      // Using the floating-point forms loses accuracy, because 
      //   they only have ~6 significant digits.

     // lat = (fix.latitude () +  90.0) * (2147483647 / 180);  // fix.latitudeL() would be better
      //lng = (fix.longitude() + 180.0) * (2147483647 / 360); // fix.longitudeL()

      message.lat = fix.latitudeL();
      message.lon = fix.longitudeL();
      //  I don't think this calculation does what you expect.  It
      //   introduces additional errors, including overflow
      //   that loses the top bits.  o_O
    }

    receivedFix = true;
  }

  if ((millis() > 5000) && !receivedFix) {
    Serial.println( F("No GPS detected: check wiring.") );
    while(true);
  }


  if ((millis() - lastStreamTime) >= streamPeriod)
  {
    lastStreamTime = millis();    
    mySensor.updateEuler();
    //mySensor.updateCalibStatus();

    // correct heading data for 90deg rotation of hardware 
    float headingf = mySensor.readEulerHeading() - 90;  
    if (headingf < 0) {
      headingf = (360 + headingf);
    }
    
    //  adjust data to suit the receiving software
    if (headingf > 180) {
     headingf = -180 + (headingf - 180);
    }
    headingf = headingf * PI / 180; // convert heading to radians

    float rollf = mySensor.readEulerRoll();
    if (rollf > 180) {
     rollf = -180 + (rollf - 180);
    }
    rollf = rollf * PI / 180; // convert to radians

    float pitchf = mySensor.readEulerPitch() * -1;
    if (pitchf > 180) {
      pitchf = -180 + (pitchf - 180);
    }
    pitchf = pitchf * PI / 180; // convert to radians

    // note pitch and roll are swapped below because I rotate z axis of device by 90 degrees 
    
    message.heading = (headingf + PI) * 100;
    message.pitch = (rollf    + PI) * 100; 
    message.roll = (pitchf   + PI) * 100;
    
    Serial.write(251); 
    Serial.write(252); 
    Serial.write(253); 
    Serial.write(254);

    Serial.write( (uint8_t *) &message, sizeof(message) );
    Serial.write(255);
    

  }
}

UBLOX_INIT doesn't seem to be doing anything in my code.

I've got your ubloxRate.INO running now (it was necessary to change LAST_SENTENCE_IN_INTERVAL in NMEAGOS_cfg.h to NMEAGPS::NMEA_GLL. It was originally set to NMEAGPS::NMEA_RMC.

The program runs and data is printed to screen every a second. When I enter the command 'r5' or 'r0' (without quotes) there is no change in the rate of data printed. Should there be?

The '0' and 'd' commands also don't seem to do anything.

Here is a typical data line when command '1' is sent:

3,2017-04-18 11:32:53.00,-156593350,-478401383,9477,1860,102530,8,7808,3,431308,

Here is a line when '0' is sent:

3,2017-04-18 11:34:27.00,-156592900,-478404100,9477,1170,99920,7,8648,4,482484,

Still in '0' mode, here is a typical print out when 'e' is toggled:

$GPGSA,A,3,12,05,15,31,25,20,29,,,,,,1.8,1.0,1.431
$GPGSV,3,1,11,05,16,137,41,10,10,335,,12,32,037,32,15,16,055,36
7D
$GPGSV,3,2,11,18,35,342,,20,60,112,25,21,46,256,,25,77,032,1672
$GPGSV,3,3,11,26,11,217,,29,42,165,28,31,21,265,22
4C
$GPRMC,113544.000,A,1545.5582,S,04750.4172,W,0.22,94.77,180417,,,A58
$GPVTG,94.77,T,,M,0.22,N,0.40,K,A
04
$GPZDA,113544.000,18,04,2017,00,0059
$GPTXT,01,01,01,ANTENNA OK
35
$GPGGA,113545.000,1545.5581,S,04750.4173,W,1,07,1.0,1009.1,M,0.0,M,,50
$GPGLL,1545.5581,S,04750.4173,W,113545.000,A,A
5A3,2017-04-18 11:35:45.00,-156593017,-478402883,9477,220,100910,7,9346,5,524800,

All these messages come once a second.

If I enter 'r5' or 'r0' there is no change in the rate.

Hmm, it's definitely still at 1Hz, and it's still sending other sentences besides the GLL.

I think it's time to question the wiring.

Here's the exact device that I'm using:

I'm using it with a Arduino 9 Axes Motion Shield.

When testing just now with your update code, I had the GPS's Tx connected to arduino pin 4 and the Rx attached to 3. The Motion shield was still attached.

When working with my code, i connect the GPS's Tx to 8 and the Rx to 9.

I'll try a little later running this without the motion shield

Removed the motion shield and ran ubloxRate again. Same result. Any change in the Tx and Rx wiring just results in no data whatsoever being received and displayed.

One thing that sort of works is the command '3' which results in gibberish printed to the screen. So it seems that the device did receive the message to change the baud rate. The only thing is, is that when I reset the monitor to 38400 baud, and additionally enter '1' as requested, the ASCII still is not displayed correctly. I can only get the correct display of data when device and monitor are set to 9600 baud.

This is a 3.3V device, so you really need to shift the Arduino's 5V levels down to 3.3V. This is strongly recommended for connecting the Arduino transmitting pin (9 or whatever, outputs minimum of 3.9V) ) to the GPS RX pin (max allowed is 3.6V) . A resistor divider will work.

Connecting the Arduino receiving pin to the GPS TX pin usually works, but it may not be reliable. The Arduino requires 3.5V, but the GPS TX only outputs 2.9V. To be fully "in spec", you have to use a diode or transistor. Level-shifting modules are usually bi-directional. This post describes a few ways to do "level-shifting".

It is possible that you have damaged the GPS RX pin, but the GPS TX pin is obviously working.

Do you have a 3.3V TTL Serial-to-USB converter? (Also called "FTDI" USB module.) If you connect the GPS device to the PC with that module, you could try the u-center Windows app to see if the NEO-6M is responding.

Many, many seller listings say "5V compatible", but it usually means that VCC can take 5V, not the GPS RX pin. Because GPS RX pin is connected directly to the NEO-6M chip, you must be careful. Some shields do have on-board resistors or transistors to shift the levels, but yours does not.

Thanks /dev, yes, I was beginning to come to the same conclusion. I had indeed originally used the 5v source because I read the GPS would take it. More's better, right? Very imprudent of me. I'll buy another GPS, not so expensive, even here in Brazil. At least this discussion helped me to improve accuracy in the readings, using those signed longs. I'll check out a 3.3V TTL Serial-to-USB converter. I already have the u-centre, running in Linux under wine. I'll let you know how I get on with the new Neo when it arrives. Thanks for all the help, i really appreciate it. All the best!

Hello, back again. The new GPS unit arrived. I wired it up to the arduino with VCC connected to 3.3V, ground to ground and Tx and Rx of the GPS wired to pins 4 and 3 of the arduino respectively. Testing with your ubloxRate code results in the same behaviour as the last GPS unit, ie. it transmits GPS data but doesn't respond to any configuration messages. I notice when the serial monitor window is first opened, the following message:

ubloxRate.INO: started
Looking for GPS device on NeoSWSerial( RX pin 4, TX pin 3 )
Status,UTC Date/Time,Lat,Lon,Hdg,Spd,Alt,Sats,Rx ok,Rx err,Rx chars,
3,2000-01-01 17:46:19.00,-156592950,-477405433,,,101390,8,2,0,122,
etc......

The "Rx ok,Rx err" is curious.

Here is the print out running NMEADiagnostic.ino if that's any help:

,08,34,320,21,10,09,098NMEAdiagnostic.INO: started
Looking for GPS device on SoftwareSerial( RX pin 4, TX pin 3 )


Checking 9600 baud...
Received GSV
Received RMC
Received VTG
Received ZDA
Received GGA
Received GLL
Received GSA
Received GSV
Received GSV
Received GSV
Received GSV
Received RMC
Received VTG
Received ZDA
Received GGA
Received GLL
Received GSA
Received GSV
Received GSV
Received GSV
Received GSV

**** NMEA sentence(s) detected! ****
Received data:
32382C3239312C32322C32362C30372C3034352C2C32372C31392C3335372C32 28,291,22,26,07,045,,27,19,357,2
352C33312C34362C3130332C33382A37440D0A2447504753562C342C342C3133 5,31,46,103,387D..$GPGSV,4,4,13
2C33322C31312C3134322C32382A34370D0A244750524D432C3138323532312E ,32,11,142,28
47..$GPRMC,182521.
3030302C412C313534352E353636322C532C30343735302E343235382C572C30 000,A,1545.5662,S,04750.4258,W,0
2E31342C3335352E39332C3236303431372C2C2C412A36390D0A244750565447 .14,355.93,260417,,,A69..$GPVTG
2C3335352E39332C542C2C4D2C302E31342C4E2C302E32362C4B2C412A33350D ,355.93,T,,M,0.14,N,0.26,K,A
35.
0A2447505A44412C3138323532312E3030302C32362C30342C323031372C3030 .$GPZDA,182521.000,26,04,2017,00
2C30302A35460D0A2447505458542C30312C30312C30312C414E54454E4E4120 ,00*5F..$GPTXT,01,01,01,ANTENNA

Device baud rate is 9600

GPS data fields received:

Status,UTC Date/Time,Lat,Lon,Hdg,Spd,Alt,Sats,Rx ok,Rx err,Rx chars,
3,2017-04-26 18:25:23.00,-156594267,-477404333,35593,230,100550,9,21,0,1274,

** NMEAdiagnostic completed **

Any suggestions?

Thanks,