Sending I2C commands to u-blox M8 receivers

Hey there,

I’ve been struggling for a while now to figure out how to send UBX commands to u-blox M8 receivers via I2C. There’s plenty of examples of how to do so over Serial, which is also now a breeze with the M9 receivers and the commands: newCfgValset8, addCfgValset8(), sendCfgValset8(), etc. However, I’ve been left scratching my head with I2C and the M8s.

I can see that the SparkFun u-blox Library has the command:

sfe_ublox_status_e sendI2cCommand(ubxPacket outgoingUBX, uint16_t maxWait = 250)

But this appears to require that you conform to a specific ubxPacket structure.

One of the commands I want to send will configure the receiver for ON/OFF operation by modifying the UBX-CFG-PM2 register. Specifically, I need to set the “extintWake” and “extintBackup” bits high. From u-center, I get the following hex command when doing so:

// UBX-CFG-PM2

0xB5, 0x62, 0x06, 0x3B, 0x2C, 0x00, 0x01, 0x06, 0x00, 0x00, 0x6E, 0x00, 0x42, 0x01,

0xE8, 0x03, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x4F, 0xC1, 0x03, 0x00, 0x86, 0x02, 0x00, 0x00,

0xFE, 0x00, 0x00, 0x00, 0x64, 0x40, 0x01, 0x00, 0xB2, 0x7A

Is there a way to pass this hex data to via I2C to my SAM-M8Q and ZOE-M8Q receivers?

Cheers,

Adam

Hi there,

I expect that the reason there hasn’t been a response to this post is because it turns out that sending I2C commands to an M8 receiver is not the simplest of tasks! I was, however, successfully able do so and will list the steps below in case anyone else is curious. For those applications that don’t require a programmatic way of accomplishing this, I’d highly recommend using u-center!

As I mentioned below, I wished to configure my ZOE-M8Q receiver for ON/OFF operation by modifying the UBX-CFG-PM2 register. To do so, we start with:

Step 1: Obtain the hex code from u-blox’s u-center.

  • The image below highlights the register I’m modifying (PM2), the checked extintWake and extintBackup boxes, and the resulting hex command.
  • https://i.imgur.com/LnhsGSS.png

    Step 2: Create a ubxPacket to send to the receiver

  • This hex code then needs to be placed into a ubxPacket that can be sent to the receiver using the SparkFun u-blox library.
  • The tricky thing is that it needs to conform to the [struct outlined on lines 376-387 of the SparkFun_Ublox_Arduino_Library.h source file (shown below).
  • [/list]

    //-=-=-=-=- UBX binary specific variables
    typedef struct
    {
    	uint8_t cls;
    	uint8_t id;
    	uint16_t len;		   //Length of the payload. Does not include cls, id, or checksum bytes
    	uint16_t counter;	  //Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
    	uint16_t startingSpot; //The counter value needed to go past before we begin recording into payload array
    	uint8_t *payload;
    	uint8_t checksumA; //Given to us from module. Checked against the rolling calculated A/B checksums.
    	uint8_t checksumB;
    	boolean valid; //Goes true when both checksums pass
    } ubxPacket;
    

  • This requires that the hex code obtained from u-center be parsed to create a separate payload, and the relevant pieces of information required by the ubxPacket struct be extracted.

  • The resulting payload and ubxPacket are shown below:
  • // Configure u-blox M8Q receiver for ON/OFF operation (UBX-CFG-PM2)
    static uint8_t ubxCfgPm2_payload[] = {
      0x01, 0x06, 0x00, 0x00, 0x6E, 0x18, 0x42, 0x01, 0xE8, 0x03, 0x00,
      0x00, 0x10, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x4F, 0xC1, 0x03, 0x00, 0x86,
      0x02, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x64, 0x40, 0x01, 0x00
    };
    
    ubxPacket ubxCfgPm2 = {
      0x06, 0x3b, 44, 0, 0, ubxCfgPm2_payload, 0, 0, false
    };
    

  • To break down the ubxPacket in more detail, the following code should help:
  • ubxPacket ubxCfgPm2 = {
      0x06,               // cls
      0x3b,               // id
      44,                 // len
      0,                  // counter
      0,                  // startingSpot
      ubxCfgPm2_payload,  // *payload
      0,                  // checksumA
      0,                  // checksumB
      false               // valid
    };
    

    Step 3: Send command

  • In setup() I’ve included the following three lines of code to enable debugging, send the ubxPacket above, and save the configuration to the receiver’s memory:
  •     gps.enableDebugging(Serial);    // Enable debug messages over Serial
        gps.sendCommand(ubxCfgPm2);     // Configure UBX-CFG-PM2 for ON/OFF operation
        gps.saveConfiguration();        // Save current settings to flash and BBR
    

  • The debugging output (included below) will show that the command has been sent and that there is an ACK timeout. This is a known bug with the SparkFun u-blox library and will not prevent the command from actually being received.
  • 14:43:01.297 -> SparkFun Ublox Example
    14:43:01.297 -> 
    14:43:01.297 -> Sending: CLS:CFG ID:3B Len: 0x2C Payload: 1 6 0 0 6E 18 42 1 E8 3 0 0 10 27 0 0 0 0 0 0 0 0 0 0 2C 1 0 0 4F C1 3 0 86 2 0 0 FE 0 0 0 64 40 1 0
    14:43:01.297 -> sendCommand: Waiting for ACK response
    14:43:01.297 -> checkUbloxI2C: Reading 10 bytes
    14:43:01.297 -> Incoming: Size: 2 Received: CLS:ACK ID:1 Len: 0x2 Payload: 6 3B
    14:43:01.297 -> packetAck now valid
    14:43:01.297 -> checkUbloxI2C: OK, zero bytes available
    14:43:01.404 -> checkUbloxI2C: OK, zero bytes available
    14:43:01.513 -> checkUbloxI2C: Large packet of 225 bytes received
    14:43:01.551 -> checkUbloxI2C: OK, zero bytes available
    14:43:01.551 -> waitForACKResponse: timeout after 250 msec. No ack packet received.
    14:43:01.551 -> 
    14:43:01.551 -> Sending: CLS:CFG ID:SAVE Len: 0xC Payload: 0 0 0 0 FF 0 0 0 0 0 0 0
    14:43:01.551 -> sendCommand: Waiting for ACK response
    14:43:01.651 -> checkUbloxI2C: Reading 10 bytes
    14:43:01.651 -> Incoming: Size: 2 Received: CLS:ACK ID:1 Len: 0x2 Payload: 6 9
    14:43:01.651 -> packetAck now valid
    14:43:01.651 -> UBX ACK: Command sent/ack'd successfully
    14:43:01.651 -> waitForACKResponse: ACK received after 81 msec
    14:43:01.651 -> waitForACKResponse: New data successfully sent
    

    And there we have it! I2C command sent. Thanks to Paul Clark for help with this!

    Cheers,

    Adam](SparkFun_Ublox_Arduino_Library/src/SparkFun_Ublox_Arduino_Library.h at dbf4658d8ae906e1a6915d9b66065ed764ddd34a · sparkfun/SparkFun_Ublox_Arduino_Library · GitHub)