Attempting to calibrate FXOS8700CQ without NXP MCU

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Attempting to calibrate FXOS8700CQ without NXP MCU

Jump to solution
2,656 Views
evanryker
Contributor II

Greetings,

I am working to design a robot that maps out relative heights on a circle approximately 4 feet in diameter. I'm using the FXOS8700CQ mounted on a small arm. The arm rotates ~360 degrees, and a small ball caster on the end of the arm allows it to pivot up and down with the changing height on the surface. We want to record the pitch of the arm from the FXOS8700CQ approximately every 3 degrees of rotation, to get roughly 120 readings.

We are using the sensor fusion library to filter the results from the FXOS8700CQ. This is returning more stable results that previous filters we've tried, but we're not quite getting the results we need yet. The filtered results are smooth, but they are moving (falling) without the robot moving (mostly the compass).

I believe this is due to the sensor not being properly calibrated. Previously we'd been using MotionCal software to calibrate the sensor (hard- and soft-iron matrices), but those values don't appear to work correctly with the fusion library. We want to use the Sensor Fusion Toolbox for calibration.

The issue here is that we're not using an NXP MCU, we're using an ESP32. We're also not writing the calibration matrices to the EEPROM, I'm simply writing them into the cal[] array in NXPMotionSense.cpp, like so:

cal[0] = 0; //accelerometer offsets
cal[1] = 0;
cal[2] = 0;

cal[3] = 0; //zero-drift for gyro
cal[4] = 0;
cal[5] = 0;

cal[6] = 30.32;  //hard-iron offsets
cal[7] = 7.19;
cal[8] = 72.75;

cal[9] = 45.74; //magnetic field

cal[10] = 0.988; //soft-iron map
cal[11] = 0.951;
cal[12] = 1.068;
cal[13] = 0.023;
cal[14] = 0.010;
cal[15] = -0.050;

Here is my question. I saw something about using Serial UART to communicate with the Sensor Fusion Toolbox if we were using something other than a NXP MCU. However, I was unable to figure out how to select a serial COM port, or what values the Sensor Fusion Toolbox expected from the sensor in order to perform a calibration. Could anyone point me in the right direction?

Labels (1)
0 Kudos
1 Solution
1,948 Views
evanryker
Contributor II

We're using the FXOS8700 + FXAS21002 9-DOF module. I like the proposal of using the gyro for greater pitch accuracy. Is there a way to tell SensorFusion to ignore the compass? It looks like FQWINITDD_9DOF_GBY_KALMAN modifies the impact the compass has, but I'm not sure this is what I'm looking for to modify.

View solution in original post

0 Kudos
5 Replies
1,948 Views
michaelestanley
NXP Employee
NXP Employee

Evan,

There are a number of issues to discuss here:

  1. Magnetic calibration occurs on the MCU, not within the Sensor Fusion Toolbox.  The toolbox can instruct the MCU to clear previously computed values, to write values to flash or to erase the flash.  The actual computations occur on the MCU.
  2. On the MCU side, we use a standard UART operating at 115,200 baud to implement the protocol (see control.c).  On NXP Freedom boards, RX/TX are routed to a secondary processor which implements the OpenSDA interface to the PC via USB.  On the PC side, there is an OpenSDA driver which reverses the process so that the communications link looks like a standard 115,200 serial, 8-bit, no parity, serial port.  The protocol is as per Chapter 7 of the user guide.  If you don't have an option similar to OpenSDA, the the easiest choice would probably be to purchase an inexpensive UART adapter for your PC to talk with an ESP32 UART.
  3. What materials are used in the construction of your robot?  And how close is the wiring to the FXOS8700?  In Chapter 11 of the user guide, I walk you through the theory behind magnetic compensation. A key requirement for these algorithms is that the source of magnetic interference be fixed spatially with respect to the sensor.  That means when the sensor rotates and moves, the source(s) of interference move with it.  Also, those interference sources need to be constant in time.  Are either of those assumptions violated by your robot?  Unless you paid particular attention to it during mechanical design, the odds are that simply by moving your robot arm, you are changing the magnetic environment seen by the sensor.  The drift you are seeing may be the result of the algorithms aging out old data points from prior arm settings and pulling in new data for new arm settings, and recomputing the magnetic compensation.  The only way around this is to keep your sensor properly spaced away from ferrous materials and current carrying conductors.

Here is an extract from a previous blog posting I wrote on the topic of magnetic interference:

Consider impacts on magnetic field resulting from wires and traces on your PCB. We can use the Biot-Savart law to estimate the effect of wire and trace currents on sensor readings. For long wires and traces, Biot-Savart can be simplified to:

|B| = µ0 I / 2 π r (Equation 1)

where:

  • B = magnetic field in Teslas (T)
  • µ0 = 4 π E-7 T*m/A
  • I = current in amps
  • r = distance from wire/trace to sensor in meters

This can be re-arranged to:

I <= 5 r |B| (Equation 2)

where:

  • B = magnetic field in microTeslas (µT)
  • I = current in milliamps
  • r = distance from wire/trace to sensor in mm

If you know the field magnitude you can afford to ignore and the distance from your sensor to trace/wire, then you can use Equation 2 to calculate the maximum wire/trace current in mA.

Hopefully all of the above will give you some ideas of where to start.

Regards,

Mike

0 Kudos
1,948 Views
evanryker
Contributor II

Mike,

Firstly, thank you for such a prompt and well-detailed reply.

The fact that the NXP MCUs do the calibration makes sense--I actually don't feel like this is our biggest issue. I've used MotionCal to obtain what seem like appropriate soft- and hard-iron matrix coefficients.

The robot was indeed built to address the issue of producing adverse fields that could affect the magnetometer. The sensor is mounted on an all-aluminum arm about half a meter away from the body of the robot. The main body is ABS plastic with a single servo, battery pack, and ESP32. The arm with the sensor does rotate continuously, however, the base remains stationary and the sensor, robot body (including servo and batteries) and arm all rotate as a single unit. This way, any field produced from the robot remains constant to the sensor; the sensor's position does not change in relation to this field.

By now, I have gotten the compass (getHeading()) to function very nicely. The issue is with measuring the pitch. For our orientation, the pitch of the arm is measured from (-1) * getRoll(). When the arm is stationary, the values are quite good. However, once it begins rotating, the pitch tends to drift up or down, even while the actual pitch isn't changing.

I've read as many docs as I can and have a general understanding of how SensorFusion.cpp works, and the difficulty in decoupling  these values due to how they are calculated from accelerometer and gyro inputs. I realize we might not be able to fully decouple the heading/roll, but do you have any tips for anything that could help me? We are assuming a constant rotational velocity of the arm (in the x-y plane), with gentle fluctuations in the pitch (z-direction).

EDIT: One clarifying detail, the pitch will never exceed +/- 5 degrees.

0 Kudos
1,948 Views
michaelestanley
NXP Employee
NXP Employee

Evan,

It sounds like a fun project and that you've done the right things in your robot design.  Since you're happy now with the compass heading, let's focus on pitch.  I can't tell from the thread above if your system includes a gyro or not.  Or are you using the six-axis eCompass algorithm?  The latter includes a low-pass filter that will throw off dynamic measurements.  Also, errors in magnetic calibration can easily swamp out the accuracy you are looking for in tilt.

If you have a gyro in your system, I would suggest also running the 6-axis Kalman filter for tilt.  You'll get more accurate results by excluding the magnetometer.  We commonly run all six algorithms in parallel in our standard demos, and there's no reason you couldn't run both in order to optimize your precision.

If you don't have a gyro, you might want to experiment with the low pass filter timing.  See parameter FLPFSECS_3DOF_B_BASIC in filename fusion.h.

Regards,

Mike

0 Kudos
1,949 Views
evanryker
Contributor II

We're using the FXOS8700 + FXAS21002 9-DOF module. I like the proposal of using the gyro for greater pitch accuracy. Is there a way to tell SensorFusion to ignore the compass? It looks like FQWINITDD_9DOF_GBY_KALMAN modifies the impact the compass has, but I'm not sure this is what I'm looking for to modify.

0 Kudos
1,948 Views
michaelestanley
NXP Employee
NXP Employee

Evan,

Take a look at function fFuseSensors() in fusion.c.  You'll see we have 6 separate algorithms running.  You just need to read the values from the appropriate data structure.  See Section 4.9 of the user guide.

Regards,

Mike

0 Kudos