Table of Contents
uBlox NEO-6Q / uBlox MAX-6Q
Overview
The uBLOX NEO-6Q/MAX-6Q are the sucessor to the uBLOX 5 module used in the Falcom FSA-03. They are 50 channel GPS in a 16 x 12.2 x 2.4mm (NEO) 9.7 x 10.1 x 2.4mm (MAX) package. They are rated up to 50,000 meters (164,000 feet) altitude in flight mode. They are an inexpensive module with good performance. The chip is shielded though normal precautions with regards to ESD should be observed. Data sheet is available here.
WARNING : uBLOX 6 Chips are rated at 3.3v so you can't just plug this into an 5V Arduino board or a PC serial connection as these run at 5V.
You can purchase a seperate level converter from Sparkfun or use a breakout with the integral level converter available from Uputronics.
The MAX-6 Chip, Sarantel antenna and populated breakout boards can be purchased from Uputronics.
Hardware
Unlike the Falcom FSA03 these units are just supplied as a standalone surface mount chip without an antenna. To use it you will need to use a breakout board/design your own board.
If you want to integrate the units into your own design both modules and antennas are in Ava.lbr.
Software Serial Configuration Example
All commands the same as the uBLOX5 documented by Jcoxon in the Falcom FSA03 guide.The following code has been updated to reflect the changes to Software Serial in Arduino. The uBLOX 6 modules do seem particularly sensitive to timing issues on Software Serial therefore its recommended you use the hardware UARTS on the Arduino for the GPS. Tested in Arduino 1.0.1 :
/* GPS Level Convertor Board Test Script 03/05/2012 2E0UPU This example connects the GPS via Software Serial. Initialise the GPS Module in Flight Mode and then echo's out the NMEA Data to the Arduinos onboard Serial port. This example code is in the public domain. Additional Code by J Coxon (http://ukhas.org.uk/guides:falcom_fsa03) */ #include <SoftwareSerial.h> SoftwareSerial GPS(4, 5); byte gps_set_sucess = 0 ; void setup() { GPS.begin(9600); // START OUR SERIAL DEBUG PORT Serial.begin(9600); Serial.println("GPS Level Convertor Board Test Script"); Serial.println("03/06/2012 2E0UPU"); Serial.println("Initialising...."); // // THE FOLLOWING COMMAND SWITCHES MODULE TO 4800 BAUD // THEN SWITCHES THE SOFTWARE SERIAL TO 4,800 BAUD // GPS.print("$PUBX,41,1,0007,0003,4800,0*13\r\n"); GPS.begin(4800); GPS.flush(); // THIS COMMAND SETS FLIGHT MODE AND CONFIRMS IT Serial.println("Setting uBlox nav mode: "); uint8_t setNav[] = { 0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC }; while(!gps_set_sucess) { sendUBX(setNav, sizeof(setNav)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setNav); } gps_set_sucess=0; // THE FOLLOWING COMMANDS DO WHAT THE $PUBX ONES DO BUT WITH CONFIRMATION // UNCOMMENT AS NEEDED /* Serial.println("Switching off NMEA GLL: "); uint8_t setGLL[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B }; while(!gps_set_sucess) { sendUBX(setGLL, sizeof(setGLL)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setGLL); } gps_set_sucess=0; Serial.println("Switching off NMEA GSA: "); uint8_t setGSA[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32 }; while(!gps_set_sucess) { sendUBX(setGSA, sizeof(setGSA)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setGSA); } gps_set_sucess=0; Serial.println("Switching off NMEA GSV: "); uint8_t setGSV[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39 }; while(!gps_set_sucess) { sendUBX(setGSV, sizeof(setGSV)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setGSV); } gps_set_sucess=0; Serial.print("Switching off NMEA RMC: "); uint8_t setRMC[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40 }; while(!gps_set_sucess) { sendUBX(setRMC, sizeof(setRMC)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setRMC); } */ } void loop() { while(1) { if(GPS.available()) { // THIS IS THE MAIN LOOP JUST READS IN FROM THE GPS SERIAL AND ECHOS OUT TO THE ARDUINO SERIAL. Serial.write(GPS.read()); } } } // Send a byte array of UBX protocol to the GPS void sendUBX(uint8_t *MSG, uint8_t len) { for(int i=0; i<len; i++) { GPS.write(MSG[i]); Serial.print(MSG[i], HEX); } GPS.println(); } // Calculate expected UBX ACK packet and parse UBX response from GPS boolean getUBX_ACK(uint8_t *MSG) { uint8_t b; uint8_t ackByteID = 0; uint8_t ackPacket[10]; unsigned long startTime = millis(); Serial.print(" * Reading ACK response: "); // Construct the expected ACK packet ackPacket[0] = 0xB5; // header ackPacket[1] = 0x62; // header ackPacket[2] = 0x05; // class ackPacket[3] = 0x01; // id ackPacket[4] = 0x02; // length ackPacket[5] = 0x00; ackPacket[6] = MSG[2]; // ACK class ackPacket[7] = MSG[3]; // ACK id ackPacket[8] = 0; // CK_A ackPacket[9] = 0; // CK_B // Calculate the checksums for (uint8_t i=2; i<8; i++) { ackPacket[8] = ackPacket[8] + ackPacket[i]; ackPacket[9] = ackPacket[9] + ackPacket[8]; } while (1) { // Test for success if (ackByteID > 9) { // All packets in order! Serial.println(" (SUCCESS!)"); return true; } // Timeout if no valid response in 3 seconds if (millis() - startTime > 3000) { Serial.println(" (FAILED!)"); return false; } // Make sure data is available to read if (GPS.available()) { b = GPS.read(); // Check that bytes arrive in sequence as per expected ACK packet if (b == ackPacket[ackByteID]) { ackByteID++; Serial.print(b, HEX); } else { ackByteID = 0; // Reset and look again, invalid order } } } }
Hardware Serial Configuration Example
You will need :
1 x Arduino Board
1 x ublox MAX6 Breakout (Level Converted if using 5V Arduino)(UB6)
1 x UM232 Serial UART Development Module or equivalent.
Connect UB6 5V on the board to 5V on the Arduino
Connect UB6 GND on the board to GND on the Arduino
Connect UB6 RX on the board to pin 1 TX
Connect UB6 TX on the board to pin 0 RX
Connect UM232R pin DB0 to pin 4 on the Arduino
Connect UM232R pin DB1 to pin 5 on the Arduino
Connect UM232R pin GND to GND on the Arduino
/* GPS Level Convertor Board Test Script 03/05/2012 2E0UPU Initialise the GPS Module in Flight Mode and then echoes out the NMEA Data to the Software Serial. This example code is in the public domain. Additional Code by J Coxon (http://ukhas.org.uk/guides:falcom_fsa03) */ #include <SoftwareSerial.h> SoftwareSerial mySerial(4, 5); byte gps_set_sucess = 0 ; void setup() { mySerial.begin(9600); Serial.begin(9600); mySerial.println("GPS Level Convertor Board Test Script"); mySerial.println("03/06/2012 2E0UPU"); mySerial.println("Initialising...."); // THIS COMMAND SETS FLIGHT MODE AND CONFIRMS IT mySerial.println("Setting uBlox nav mode: "); uint8_t setNav[] = { 0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC }; while(!gps_set_sucess) { sendUBX(setNav, sizeof(setNav)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setNav); } gps_set_sucess=0; // THE FOLLOWING COMMANDS DO WHAT THE $PUBX ONES DO BUT WITH CONFIRMATION /* debug.println("Switching off NMEA GLL: "); uint8_t setGLL[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B }; while(!gps_set_sucess) { sendUBX(setGLL, sizeof(setGLL)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setGLL); } gps_set_sucess=0; debug.println("Switching off NMEA GSA: "); uint8_t setGSA[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32 }; while(!gps_set_sucess) { sendUBX(setGSA, sizeof(setGSA)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setGSA); } gps_set_sucess=0; debug.println("Switching off NMEA GSV: "); uint8_t setGSV[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39 }; while(!gps_set_sucess) { sendUBX(setGSV, sizeof(setGSV)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setGSV); } gps_set_sucess=0; debug.print("Switching off NMEA RMC: "); uint8_t setRMC[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40 }; while(!gps_set_sucess) { sendUBX(setRMC, sizeof(setRMC)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setRMC); } gps_set_sucess=0; debug.print("Switching off NMEA VTG: "); uint8_t setVTG[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46 }; while(!gps_set_sucess) { sendUBX(setVTG, sizeof(setRMC)/sizeof(uint8_t)); gps_set_sucess=getUBX_ACK(setVTG); } */ } void loop() { while(1) { if(Serial.available() > 0) { char inByte = Serial.read(); mySerial.write(inByte); } } } // Send a byte array of UBX protocol to the GPS void sendUBX(uint8_t *MSG, uint8_t len) { for(int i=0; i<len; i++) { Serial.write(MSG[i]); mySerial.print(MSG[i], HEX); } Serial.println(); } // Calculate expected UBX ACK packet and parse UBX response from GPS boolean getUBX_ACK(uint8_t *MSG) { uint8_t b; uint8_t ackByteID = 0; uint8_t ackPacket[10]; unsigned long startTime = millis(); mySerial.print(" * Reading ACK response: "); // Construct the expected ACK packet ackPacket[0] = 0xB5; // header ackPacket[1] = 0x62; // header ackPacket[2] = 0x05; // class ackPacket[3] = 0x01; // id ackPacket[4] = 0x02; // length ackPacket[5] = 0x00; ackPacket[6] = MSG[2]; // ACK class ackPacket[7] = MSG[3]; // ACK id ackPacket[8] = 0; // CK_A ackPacket[9] = 0; // CK_B // Calculate the checksums for (uint8_t i=2; i<8; i++) { ackPacket[8] = ackPacket[8] + ackPacket[i]; ackPacket[9] = ackPacket[9] + ackPacket[8]; } while (1) { // Test for success if (ackByteID > 9) { // All packets in order! mySerial.println(" (SUCCESS!)"); return true; } // Timeout if no valid response in 3 seconds if (millis() - startTime > 3000) { mySerial.println(" (FAILED!)"); return false; } // Make sure data is available to read if (Serial.available()) { b = Serial.read(); // Check that bytes arrive in sequence as per expected ACK packet if (b == ackPacket[ackByteID]) { ackByteID++; mySerial.print(b, HEX); } else { ackByteID = 0; // Reset and look again, invalid order } } } }
NMEA
If you only need to turn of the sentances then you can just use NMEA commands:
// Turning off all GPS NMEA strings apart from GPGGA on the uBlox modules Serial.print("$PUBX,40,GLL,0,0,0,0*5C\r\n"); Serial.print("$PUBX,40,ZDA,0,0,0,0*44\r\n"); Serial.print("$PUBX,40,VTG,0,0,0,0*5E\r\n"); Serial.print("$PUBX,40,GSV,0,0,0,0*59\r\n"); Serial.print("$PUBX,40,GSA,0,0,0,0*4E\r\n"); Serial.print("$PUBX,40,RMC,0,0,0,0*47\r\n");
Saving your settings
As the uBLOX6 modules don't have any RAM or flash memory, its RAM must be buffered by a backup battery to retain settings or use external 1-Wire Flash module(see data sheets). As long as the backup battery remains in place, you can can save your settings as per page 99 of the UBX protocol specification “Clear, Save and Load configurations”.
Navigation data
By default, uBLOX6 modules are configured to output several NMEA sentences including GPRMC, GPGGA & GPVTG. Of these, GPGGA is the most useful for high altitute balloon applications as it contains altitude data. Un-necessary sentences can be disabled see previous code sample section for more information.
Polling the module
Ublox6 based GPS modules implement a proprietary NMEA extension in the form of a polled sentence which reports all navigation parameters of interest (to us at least) in a single sentence when requested. Using this provides advantages in that you can request an update exactly when you need it, and you only need to parse one specific sentence to capture latitude, longitude, altitude, speed, course, etc. For those using a SoftwareSerial library, this method fixes the buffer overrun issues.
To use the sentence firstly disable any GPS sentences which are currently switched on:
Serial.println("$PUBX,40,GLL,0,0,0,0*5C"); Serial.println("$PUBX,40,GGA,0,0,0,0*5A"); Serial.println("$PUBX,40,GSA,0,0,0,0*4E"); Serial.println("$PUBX,40,RMC,0,0,0,0*47"); Serial.println("$PUBX,40,GSV,0,0,0,0*59"); Serial.println("$PUBX,40,VTG,0,0,0,0*5E");
The sentence can be requested by sending the string “$PUBX,00*33”:
Serial.println("$PUBX,00*33");
The module responds (within 1 second) with the current navigation data in the following format:
$PUBX,00,hhmmss.ss,Latitude,N,Longitude,E,AltRef,NavStat,Hacc,Vacc,SOG,COG,Vvel,ageC,HDOP,VDOP,TDOP,GU,RU,DR,*cs<CR><LF>
Field No. | Example | Format | Name | Unit | Description |
---|---|---|---|---|---|
0 | $PUBX | string | $PUBX | - | Message ID, UBX protocol header, proprietary sentence |
1 | 00 | numeric | ID | - | Propietary message identifier: 00 |
2 | 081350.00 | hhmmss.ss | hhmmss.ss | - | UTC Time, Current time |
3 | 4717.113210 | ddmm.mmmm | Latitude | - | Latitude, Degrees + minutes, see Format description |
4 | N | character | N | - | N/S Indicator, N=north or S=south |
5 | 00833.915187 | dddmm.mmmm | Longitude | - | Longitude, Degrees + minutes, see Format description |
6 | E | character | E | - | E/W indicator, E=east or W=west |
7 | 546.589 | numeric | AltRef | m | Altitude above user datum ellipsoid. |
8 | G3 | string | NavStat | - | Navigation Status - Example: G3 =Stand alone 3D solution, NF =No Fix |
9 | 2.1 | numeric | Hacc | m | Horizontal accuracy estimate. |
10 | 2.0 | numeric | Vacc | m | Vertical accuracy estimate. |
11 | 0.007 | numeric | SOG | km/h | Speed over ground |
12 | 77.52 | numeric | COG | degrees | Course over ground |
13 | 0.007 | numeric | Vvel | m/s | Vertical velocity, positive=downwards |
14 | - | numeric | ageC | s | Age of most recent DGPS corrections, empty = none available |
15 | 0.92 | numeric | HDOP | - | HDOP, Horizontal Dilution of Precision |
16 | 1.19 | numeric | VDOP | - | VDOP, Vertical Dilution of Precision |
17 | 0.77 | numeric | TDOP | - | TDOP, Time Dilution of Precision |
18 | 9 | numeric | GU | - | Number of GPS satellites used in the navigation solution |
19 | 0 | numeric | RU | - | Number of GLONASS satellites used in the navigation solution |
20 | 0 | numeric | DR | - | DR used |
21 | *5B | hexadecimal | cs | - | Checksum |
22 | - | character | <CR><LF> | - | Carriage Return and Line Feed |
For details see page 52 of the UBX protocol specification “Proprietary Messages, UBX00”.
You can use a modified version of the TinyGPS library to parse PUBX sentences – TinyGPS_UBX.
Images
Troubleshooting
No Response From GPS
- Check power, measure VCC and GND.
- Run above scripts, check that you get SUCCESS on ACKs.
No time updated or GPS fix
- Hook up the module to a 3.3v FTDI with the corresponding wires (TX,RX,VCC,GND)
- Start up uBlox u-center http://www.u-blox.com/en/evaluation-tools-a-software/u-center/u-center.html