CMPS14 - How does calibration work?

I’ve got a few issues with calibrating my CMPS14. I’ll start out by asking if someone can explain how the CMPS14 “calibrates”? (Maybe this is a general question for all electronic compasses.) If I can understand it, maybe I won’t need a subsequent post about my issues.

Calibration involves an instrument that measures a quantity that may have an error in its measured value, that is corrected by using the instrument to measure a KNOWN quantity, and then using the error term to derive a correction factor. For instance, if it’s an electronic thermometer, we would put the thermometer in a chamber that has a known temperature, measure the temp with the thermometer, and save the error in degrees, and apply a correction in all future measurements using this offset.

So what is CMPS14 (BNO080) calibration? Reading the literature and manuals, I see all kinds of statements like “make a couple random motions”, “background calibration”, “rotate in each axis by at least 180 degrees”, etc. No where do I see a well-defined calibration procedure, that has a start and end, and involves pointing the device in a known direction!!! How can this work? How can this device calibrate without a known direction?? I can only conclude that this is not calibration in a strict sense, but is some kind of internal compensation of some unknown quantity.

How does “background calibration” work without a known reference? Is this somehow compensating for local magnetic disturbances? What is the time scale of this? I assume the “profile” is saved in non-volatile memory and then when the device is re-booted, the background calibration continues where it left off?

1 Like

Since I’ve gotten zero replies at this point, I’ll share what I’ve been able to figure out after hours and hours of experiments. What may be glaringly obvious to others, was not to me! For references, I used the CMPS14 manual on Robotshop, and the BNO080 manual.

The term “background” calibration means that some kind of internal adjustment is occuring, that improves the accuracy. This is obviously not a “traditional” foreground calibration, where you intentionally point the compass in one KNOWN DIRECTION (or 4 directions), and send commands when the directions are achieved. It appears that when in “background calibration” mode, the actual calibration is initiated by moving the CMPS14 at large angles over all axis of rotation. It appears that if the device is relatively still, or is only rotated in one axis, it doesn’t do anything. The term “background” kind of applies to the fact that you can continue to poll the device for reports while you are calibrating. If you poll the calibration status (0x24) while calibrating, you can see the status change from 0->3 as you achieve a good cal by swinging the device around in a figure 8 pattern.

So now that we understand (sort of :slight_smile: background calibration, how specifically do we code this? A big question I had was, “Should I leave background calibration on all the time?” Depends on your application. The background cal can be used to recalibrate the unit when it goes to a different location. When you change locations, there may be different local magnetic interference, which I assume the cal takes care of. From this logic, it might makes sense to leave it on all the time, with the knowledge that all you have to do when you take the unit to a new hiking spot, is figure 8 it for 10 seconds to re-calibrate, and you are good to go. However, suppose you use the CMPS14 on a quadcopter, where the “figure 8” may not occur intentionally, and you do not want this to happen because it may change the relative directional calibration. In this case it would make sense to turn calibration off after the figure 8, and keep the calibration procedure under your control.

Steps to calibrate (I’m only using as a compass):

  1. in code, enable cal
    SendCommand(0x98);
    SendCommand(0x95);
    SendCommand(0x99);
    SendCommand(0x87);

  2. Do a real deep, twisty figure 8 for 10 seconds, while monitoring the cal status by sending 0x24. Do this until you get a “3” back for your parameters of interest. I look for magnetometer and system to reach 3

  3. in code, store the cal. This saves the “profile” to non-volatile memory. The unit can be powered down, and back up again, and will retain the cal:
    SendCommand(0xF0);
    SendCommand(0xF5);
    SendCommand(0xF6);

  4. Depending on your application, turn off the cal:
    SendCommand(0x98);
    SendCommand(0x95);
    SendCommand(0x99);
    SendCommand(0x80);

RANDOM NOTES:
I don’t use the accelerometer or gyroscope, so the above procedure needs to be expanded if you want to use these. There are specific enable and disable bits for each device, and different calibation motions. See the BNO080 manual and the CMPS14 manual. You can define each piece of the cal, and in your UI, put up the appropriate user prompts.

To erase the cal, in code:
SendCommand(0xE0);
SendCommand(0xE5);
SendCommand(0xE2);
If you are polling with 0x24, you will see all the values go to zero, and the compass direction may make a large shift back to the uncalibrated state.

Bit 4 of the cal register is to enable auto save. I have not messed with that. The word “periodic” scares me.

The BNO080 manual is really dense, and extremely complicated. So what has happened is various vendors have “wrapped” the device in either hardware or software to allow easier operation. The CMPS14 is wrapped with a microcontroller, and the result is the “API” you see in the CMPS14 manual. Other vendors wrap a naked BNO080 with software, like Arduino libraries or Python libraries.

I’m using the device with a C++ app that runs on Windows that communicates via USB->Serial.

1 Like

Hi @Randy7 !

Too bad that no one replied to your first post, but I am glad that you were able to find the answer :slight_smile:

There is a newer chip out, the BNO086. Interestingly, the data sheet shows this:

  • BNO086 only

    • 14-bit accelerometer fusion
    • Lower idle power
    • Interactive calibration

That last feature looks interesting!

1 Like

I seem to be up and running with the above cal procedure, although I suspect things might be better by calibrating each device (gyroscope, accelerometer, magnetometer) individually.

BNO08X Sensor Calibration Procedure (mouser.com)

This would involve setting and resetting bits 0-2 and performing each of the procedures in the above document.

1 Like

Here is a complete calibration procedure to put a “stake in the ground”. This procedure calibrates each internal device (magnetometer, accelerometer, gyroscope), individually. The ambiguity of this device’s calibration that is available on the internet drives me nuts. Feel free to comment and correct. Disclaimers: I’m using the CMPS14 for boat navigation. My goal was to get an accurate heading from the compass. I don’t directly need the gyroscope or accelerometer, although perhaps they are being used for the heading result. I tried to write the following procedure generically, I’m using C, but you can apply this to other languages. I run this procedure in a thread, monitoring the heading and cal status constantly. Cal status is monitored by sending 0x24 and checking the bits of the returned byte.

Key:
SendCommandTriplet(a,b,c) Sends 3 bytes, checking for 0x55 after each byte send
SendCommand(x) Sends single byte, checking for 0x55 to be returned
See the CMPS14 document here on Robotshop for how to physically move the device

So to calibrate:

// start with the magnetometer
SendCommandTriplet(0x98,0x95,0x99)
SendCommand(0x81)

Flip the CMPS14 as described in document…

// do the accelerometer
SendCommandTriplet(0x98,0x95,0x99)
SendCommand(0x82)

Set the CMPS14 on all sides as described in document…

// do the gyroscope
SendCommandTriplet(0x98,0x95,0x99)
SendCommand(0x84)

Hold the CMPS14 still as described in document…

// turn off the cal
SendCommandTriplet(0x98,0x95,0x99)
SendCommand(0x80)

// write the “profile” to flash
SendCommandTriplet(0xF0,0xF5,0xF6)

Note I turn off the cal after finishing. I do not know the implications of leaving the cal on all the time, so I turn it off. If you perform an “interactive”, intentional calibation, with reasonably well defined movements, wouldn’t it be better to stop potentially ambiguous motion from creating a suboptimal calibration?

Oddities:
If you perform a factory cal reset by using:
SendCommandTriplet(0xE0,0xE5,0xE2)

The device will reset, but enter cal mode. In other words, if you have turned off the cal, this willl turn it back on again. Seems odd to me.

While you are calibrating the magnetometer, if you monitor the cal status, the accelerometer cal status will change also. Seems odd to me.

This procedure seems to work well. If I factory reset the cal, the heading on one of my CMPS14s (I have 2) is off by about 45 degrees, so the factory cal is not very good.

1 Like

Thank you for sharing this with us!