UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


guides:ublox6

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 convertor from Sparkfun or use a breakout with the integral level convertor available from HAB Supplies.

The MAX-6 Chip, Sarantel antenna and populated breakout boards can be purchased from HAB Supplies.

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”.

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.ExampleFormatNameUnitDescription
0$PUBXstring$PUBX-Message ID, UBX protocol header, proprietary sentence
100numericID-Propietary message identifier: 00
2081350.00hhmmss.sshhmmss.ss-UTC Time, Current time
34717.113210ddmm.mmmmLatitude-Latitude, Degrees + minutes, see Format description
4NcharacterN-N/S Indicator, N=north or S=south
500833.915187dddmm.mmmmLongitude-Longitude, Degrees + minutes, see Format description
6EcharacterE-E/W indicator, E=east or W=west
7546.589numericAltRefmAltitude above user datum ellipsoid.
8G3stringNavStat-Navigation Status - Example: G3 =Stand alone 3D solution, NF =No Fix
92.1numericHaccmHorizontal accuracy estimate.
102.0numericVaccmVertical accuracy estimate.
110.007numericSOGkm/hSpeed over ground
1277.52numericCOGdegreesCourse over ground
130.007numericVvelm/sVertical velocity, positive=downwards
14-numericageCsAge of most recent DGPS corrections, empty = none available
150.92numericHDOP-HDOP, Horizontal Dilution of Precision
161.19numericVDOP-VDOP, Vertical Dilution of Precision
170.77numericTDOP-TDOP, Time Dilution of Precision
189numericGU-Number of GPS satellites used in the navigation solution
190numericRU-Number of GLONASS satellites used in the navigation solution
200numericDR-DR used
21*5Bhexadecimalcs-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

uBLOX NEO-6 :

uBLOX MAX-6 :

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

guides/ublox6.txt · Last modified: 2013/07/21 16:52 by upu