Configuring NEO-6M GPS with Arduino Pro Mini

Hi,

I'm trying to use Arduino Pro Mini to configure my NEO-6M GPS module, so that I don't need to get back to the U-Centre (Ublox interface) every time I want to change the GPS's configuration.

I used following codes to implement the configuration, which I tried to extent the measure time from 1s to 5s.

static const int Rx = 0, Tx = 1;
static const int GPSBaud = 9600;
byte gps_config[] = {
  // Measure Time (5s)
  0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0x88, 0x13, 0x01, 0x00, 0x01,
  0x00, 0xB1, 0x49,
  // Save Config
  0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
  0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x21, 0xAF
};

TinyGPS gps;
SoftwareSerial ss(Rx, Tx)

void setup()
{
  Serial.begin(115200);
  ss.begin(GPSBaud);
  ss.write(gps_config, sizeof(gps_config));
}
;[code]

Instead of getting a longer measure time, it remains at 1s. It appears that no change has been made. I would be really appreciate if anyone could give me some clues.

Thanks in advance.

First thing to do is check the wiring to be sure the TX/RX is crossed to RX/TX. Also try a slower baud value as sometimes, SoftSerial is finicky. Check for the default value that the GPS uses even though it can run faster. You could also switch to I2C since it's supported by the GPS. This has the advantage of allowing you to add other devices onto the buss. That buss defaults to 100Kbps but can be easily pushed to 800Kbps with just one software command in the setup() routine.

PS
Just noticed that you're pushing 35 bytes to the GPS. The I2C buss buffer is only 32 bytes. There may be a similar limitation in SoftSerial. Try sending in two groups from two separate byte arrays.

Hi Arctic, thanks for your advice.

I have checked my wiring and the default baud rate of my GPS module, which is 9600. Even though I changed it to 4800, it makes no difference. I also separated the byte arrays, and again, no difference...

This might be silly to ask, but how can I switch to I2C using Arduino Mini? Do I simply switch both TX/RX pins to SDA and SCL pins, which in this case I believe are A4 and A5?

By checking the examples on arduino.cc, I assume that I might need to use the 'Wire' library to replace the 'Serial'. I tried following code, but it didn't work. Could you have a look and point out where I did wrong?

static const int Rx = A4, Tx = A5;
static const int GPSBaud = 9600;
byte gps_config1[] = {
  // Measure Time (5s)
  0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0x88, 0x13, 0x01, 0x00, 0x01,
  0x00, 0xB1, 0x49 };
byte gps_config2[] = {
  // Save Config
  0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
  0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x21, 0xAF };

TinyGPS gps;
SoftwareSerial ss(Rx, Tx)

void setup()
{
  Serial.begin(115200);
  Wire.begin();
  ss.begin(GPSBaud);
  Wire.write(gps_config1, sizeof(gps_config1));
  Wire.write(gps_config2, sizeof(gps_config2));
}

I found this example from UKHAS Wiki ( https://ukhas.org.uk/guides:ublox6 ) be very helpful, and it works on my board. Despite I reckon it uses the SoftSerial still.

Now that you have it working then just stick with the code you found.

I2C is an entirely different scheme. Two advantages is that it's fast and supports multiple slaves. It uses A4 for the bi-directional data and A5 for the master controlled clock. The TWI library is used for communication. Your device should have details on using this method.

You might want to take a look at NeoSWSerial, a very efficient and reliable alternative to SoftwareSerial.

Also, NeoGPS is an alternative GPS parser that is very efficient and configurable. It implements both the common NMEA protocol and the UBX binary protocol. The latter part is probably overkill for what you are doing, but the ublox-specific code might help you understand the spec.

BTW, there is a ublox-specific NMEA message you can send to set the rate, too: $PUBX,40. See Section 21.11 in the ublox spec. The generic NMEA part of NeoGPS has a send method that could be used to send the configuration string during setup; it calculates the checksum for you.

Cheers,
/dev

Arctic_Eddie:
Now that you have it working then just stick with the code you found.

I2C is an entirely different scheme. Two advantages is that it's fast and supports multiple slaves. It uses A4 for the bi-directional data and A5 for the master controlled clock. The TWI library is used for communication. Your device should have details on using this method.

Well, I understand the I2C can be very effective when a 'huge' amount of data needs to be transmitted, while for my project, only latitudes and longitudes are required. I wouldn't too worry about the serial method for now, but the I2C is definitely worth a while to learning about.

Thanks for your help!

Hi dev, your suggestion are really helpful!

/dev:
You might want to take a look at NeoSWSerial, a very efficient and reliable alternative to SoftwareSerial.

I used the NeoSWSerial Library that you wrote, and it works like a charm. Yes, now the overflow issue is gone.

/dev:
Also, NeoGPS is an alternative GPS parser that is very efficient and configurable. It implements both the common NMEA protocol and the UBX binary protocol. The latter part is probably overkill for what you are doing, but the ublox-specific code might help you understand the spec.

BTW, there is a ublox-specific NMEA message you can send to set the rate, too: $PUBX,40. See Section 21.11 in the ublox spec. The generic NMEA part of NeoGPS has a send method that could be used to send the configuration string during setup; it calculates the checksum for you.

The NeoGPS is quite handy as well. But just as my last reply, I don't really need too much of information from GPS except its location.

BTW, I have this question that I'd really like to ask you about. When I was trying the UKHAS example to configure my GPS, I found the checksum loop be quite annoying. It usually ran four or five times before it could return a correct checksum. So I turned this loop off, then a weird thing happened. Even the checksum was incorrect, my configuration still worked, which means the command was successfully passed to the GPS module despite the GPS said it haven't 'successfully' received it. I assume the checksum should work as an indicator to tell us whether the receiver has correctly received the information. But is it really necessary?

Cheers

I used the NeoSWSerial Library that you wrote, and it works like a charm.

Thanks, and thanks to jboyton who created it! I adopted it and posted it up on github.

I don't really need too much of information from GPS except its location.

One of the features I put in NeoGPS is configurability. You can actually disable all the code that parses GPS fields and messages you don't use. In your case, you could turn off everything except parsing the location from a $GPRMC sentence. The final program size would be very small. If your program ever gets too big or slow, NeoGPS could save a few K of FLASH, up to 1k of RAM, and a few milliseconds of CPU time per GPS update. But it sounds like your sketch works fine for now.

When I was trying the UKHAS example to configure my GPS, I found the checksum loop be quite annoying. It usually ran four or five times before it could return a correct checksum.

Yes, it is not written like a real embedded communications program. Matching configuration requests (CFG_xxx from the Arduino) to acknowledgments (ACK/NAK from the Neo-6M), and keeping track of timeouts and retries, definitely requires more sophisticated programming techniques. Every other sketch that sends UBX binary commands does not properly wait, or does not even try to wait. Usually, they just send the binary commands once and hope that it gets to the Neo-6M and is processed.

I assume the checksum should work as an indicator to tell us whether the receiver has correctly received the information. But is [the CS] really necessary?

There are two things going on here: a checksum in every message; and ACK/NAK messages to configuration requests.

The checksum is used to verify that a received message is valid and can be parsed. It is detects errors in transmission and receipt. The Neo-6M will ignore UBX messages (CFG or otherwise) that do not have a good CS (I have verified this). You have to send the correct CS.

Similarly, the Arduino should ignore UBX messages that do not have a good CS. ACKs to configuration requests and position reports all have a CS, and they should be ignored if the CS does not match. (NeoGPS calculates the CS as each frame is being sent/received, so it is guaranteed to be calculated only once.)

In contrast to the CS, the ACK message (with its own CS) tells the Arduino that the Neo-6M received the CFG request correctly (the CS passed) and also performed the request. However, if the Neo-6M receives the request correctly and does not perform the request, it will reply with a NAK message (again, with its own CS). If neither an ACK nor a NAK is received "in time" (i.e., before the timeout expires), the Arduino can assume there was a CS failure. It will usually send the message again (a "retry").

I also found that the ACK/NAK timeout had to accommodate the serial "pipeline". If the Neo-6M happened to be sending a position report back to the Arduino, the Arduino had to wait until the Neo-6M was done sending data before the timeout would expire. This could add several hundred milliseconds to the timeout. Very subtle behavior!

If the UKHAS library was failing when you were still using SoftwareSerial, I'm not at all surprised. Losing just one character will cause the CS to fail. But there are lots of ways it could have failed.

BTW, you can use u-center to send the configuration commands that you want, then look at the log for what bytes to send. Just do that in your sketch in setup... like so many others. You can also use u-center to store that configuration permanently in the Neo-6M's non-volatile memory. This is a little more reliable, IMO. It also takes the code out of your sketch.

I do not recommend switching to the UBX binary protocol until every other time- or space-saving technique has been tried with the NMEA text protocol. Sometimes, sending a UBX binary message is the only way to configure the Neo-6M, but receiving ACK/NAK messages, and handling timeouts, retries and UBX binary position reports is much more complicated!

Cheers,
/dev