Go Down

Topic: Neo-6M GPS shield - update faster than 1Hz (Read 8303 times) previous topic - next topic

escuta

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,

-dev

Quote
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:

Code: [Select]
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:

Code: [Select]
  // 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...

Quote
Do I need to use a different library?
Yes.  :)  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
Really, I used to be /dev.  :(

escuta

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

-dev

Quote
Re. disabling the NMEA sentences, do I add that block of binary to the "UBLOX_INIT" function?
Yes, or send the text command instead.

Quote
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") );

Quote
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;)

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
Really, I used to be /dev.  :(

escuta

#4
Apr 16, 2017, 11:55 am Last Edit: Apr 16, 2017, 04:47 pm by escuta Reason: putting in code tags
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,

Code: [Select]

#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);
 }
}

-dev

Please edit your post and insert code tags around your sketch

Code: [Select]
... 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.
Really, I used to be /dev.  :(

escuta


-dev

These two lines are wrong:

Code: [Select]
#include "TinyGPS++.h"
#include <SoftwareSerial.h>

;)

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:

Code: [Select]
#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?  :)

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.
Really, I used to be /dev.  :(

-dev

Really, I used to be /dev.  :(

escuta

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!

escuta

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!

-dev

Did you try what I put in the code?

Code: [Select]
   //  ...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:

Code: [Select]
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
Really, I used to be /dev.  :(

escuta

#12
Apr 17, 2017, 11:10 pm Last Edit: Apr 17, 2017, 11:16 pm by escuta
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,

Code: [Select]

#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);
   

  }
}

escuta

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.4*31
$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,16*72
$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,,,A*58
$GPVTG,94.77,T,,M,0.22,N,0.40,K,A*04
$GPZDA,113544.000,18,04,2017,00,00*59
$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.

-dev

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.
Really, I used to be /dev.  :(

Go Up