SparkFun Micro Magnetometer - MMC5983MA (Qwiic)

I’m working with it indoors at present. I get same results, even when holding it at shoulder height in the middle of the room, with nothing (except me) within 1m.

I would try testing outdoors with nothing around if possible an if the discrepancy still stays after a re-calibration it might be a defective unit

Just to double-check: how is it mounted and what to?

Ive just repeated same results with the SF 5983 board taped to a (level) piece of wood in the middle of the lawn, the 4" qwiic cable soldered onto a Arduino-styley mcu module, and a 1m usb cable from that to laptop.
I have got a version of my f/w which seems to successfully inform MotionCal of readings. Maybe i need gain calibration as well as offsets? Not sure how to apply/factor its results to the 5983 example code tho…

Hello and thank you for everyone posting about calibrating the MMC5983MA. This was extremely helpful. If possible I would like someone to clarify a few things for me:
I used the altered version of example 7 to print out the offsets for all 3 axes.
Pressing any key initiates the updateOffset offset function. But all it does is to print them out and doesn’t store it permanently correct ?
If that’s correct I use those offset values in example code 2 for the digital compass to get the scaled values for the x and y axis : like this

    scaledX = (double)rawValueX - 132244.0;
    scaledX /= 132244.0;

    scaledY = (double)rawValueY - 129288.0;
    scaledY /= 129288.0;

    scaledZ = (double)rawValueZ - 130315;
    scaledZ /= 130315;

Note that I plugged the offset values in already instead of the original 131072 . This normalizes the value for scaledX based on the new offset for X.

I also got MotionCal to print the magnetic Offset, the magnetic mapping, which is the transformation matrix explained in this link: https://www.vectornav.com/resources/inertial-navigation-primer/specifications–and–error-budgets/specs-hsicalibration

Can someone explain to me where I implement those values from MotionCal ? It seems only the Adafruit sensorlab has a library for implementing hard iron and soft iron calibration, or am I missing something here and also in what units I have to convert those results. Sometimes Gauss is being used and sometimes Micro Gauss like in the altered Version of Example 7.
My suspicion is that this part of the code in example 7:

    *offsetX = (setX + resetX) / 2;
    *offsetY = (setY + resetY) / 2;
    *offsetZ = (setZ + resetZ) / 2;
    Serial.print("Offsets: ");
    Serial.print(*offsetX);
    Serial.print(", ");
    Serial.print(*offsetY);
    Serial.print(", ");
    Serial.print(*offsetZ);
    Serial.println();
  }

does the hard iron calibration.

On another note: Strangely MotionCal only works on my Mac and only after installing it in the terminal with some changes to the code.

Thanks for help in advance!

  1. Offset Function: Correct. The updateOffset function in the altered version of example 7 only prints out the offsets and doesn’t store them permanently. It calculates the offsets based on the SET and RESET operations, which helps eliminate thermal variation-induced offset errors

  2. Scaling in Example 2:
    Your approach to scaling the raw values using the calculated offsets is correct. This method helps to center the magnetometer readings around zero, which is part of the hard iron calibration proces

  3. MotionCal Output Implementation: The magnetic offset and mapping values from MotionCal are indeed for hard iron and soft iron calibration. To implement these:

  • Hard Iron Correction: Subtract the magnetic offset values from your raw readings.
  • Soft Iron Correction: Multiply the hard iron corrected values by the inverse of the magnetic mapping matrix

Here’s a general implementation structure:

// Hard Iron Correction
float x_hard_iron = raw_x - hard_iron_offset_x;
float y_hard_iron = raw_y - hard_iron_offset_y;
float z_hard_iron = raw_z - hard_iron_offset_z;

// Soft Iron Correction
float x_calibrated = soft_iron_matrix[0][0] * x_hard_iron + soft_iron_matrix[0][1] * y_hard_iron + soft_iron_matrix[0][2] * z_hard_iron;
float y_calibrated = soft_iron_matrix[1][0] * x_hard_iron + soft_iron_matrix[1][1] * y_hard_iron + soft_iron_matrix[1][2] * z_hard_iron;
float z_calibrated = soft_iron_matrix[2][0] * x_hard_iron + soft_iron_matrix[2][1] * y_hard_iron + soft_iron_matrix[2][2] * z_hard_iron;
  1. Units:
    The MMC5983MA datasheet specifies its output in milli-Gauss (mG). MotionCal typically works with micro-Tesla (μT). To convert:
    1 mG = 0.1 μT

  2. Hard Iron Calibration in Example 7: Correct. The code snippet you provided is performing a basic hard iron calibration by averaging the SET and RESET values for each axis

  3. MotionCal on Mac: The issues with MotionCal on Mac are known, and several users have reported similar problems. The solution you found (installing via terminal with code changes) is currently the best workaround for Mac users

1 Like

Got it! Thank you so much. With your help I was able to carry it over the finish line !

1 Like