I was sent here from https://forum.sparkfun.com/viewtopic.ph … 71#p241471. To use Example7-I2C_Sensor_Offset, is uploading it enough, or do I have to take numbers from it and put those numbers into Example2-I2C_Digital_compass? If uploading it is enough, I’m assuming Example7-I2C_Sensor_Offset makes a change to the board/chip.
jremington:
The sensor offset program calculates corrective offsets (one value for each of the 3 axes) that you must enter into the digital compass program.
Thank you. The number 131072.0 appears six times in the digital compass code. Assuming the corrective offsets change each 131072.0, how do they change them? For example, do they replace them or are they added to them?
Assuming the corrective offsets change each 131072.0
Bad assumption. Three of those "131072.0" values are **scaling constants**, not offsets, which was the point of the discussion in the later part of this thread.
Subtract the three calculated X, Y and Z offsets from the raw X, Y and Z measurements.
jremington:
However, modifications to the sensor offset program are required, as suggested in the parallel thread, in order to print the calculated offset values.
I’ve been rereading the two threads and Example7-I2C_Sensor_Offset, trying to find out which line (out of the total of 171 lines in Exmaple7) I should go to in order to start making those modifications. Is it line 114, right after the comments about true offsets and scale factors?
If I understand correctly, inserting numbers into Example2-I2C_Digital_compass makes one type of correction, but there are other types of correction. Please confirm that inserting numbers into Example7-I2C_Sensor_Offset can’t make a type of correction that is necessary to enable a heading accuracy of plus-minus 0.5 degrees. And inserting three numbers into Example2-I2C_Digital_compass is enough to enable that heading accuracy.
Can the code in the reply (that the link, that was just quoted, goes to) do anything that Example7-I2C_Sensor_Offset (updated, on GitHub, last week) can’t do? I’m asking because I don’t know what Example7-I2C_Sensor_Offset can and can’t do.
You cannot expect heading accuracy of +/- 0.5 degrees with consumer grade magnetometers, unless extreme care is taken in all steps, including full 3D calibration in the final mounting.
jremington:
You cannot expect heading accuracy of +/- 0.5 degrees with consumer grade magnetometers, unless extreme care is taken in all steps, including full 3D calibration in the final mounting.
Thank you. What grade is SparkFun talking about when they say a heading accuracy of +/- 0.5 degrees, at https://www.sparkfun.com/products/19921 (on the pages that the DESCRIPTION and FEATURES tabs go to) and (the Hookup Guide) at https://learn.sparkfun.com/tutorials/qw … okup-guide? Do I not understand what they mean by the words “enable,” “enables,” and “enabling”? Are they implying extreme care?
jb’s_sf:
What grade is SparkFun talking about when they say a heading accuracy of +/- 0.5 degrees, at https://www.sparkfun.com/products/19921 (on the pages that the DESCRIPTION and FEATURES tabs go to) and (the Hookup Guide) at https://learn.sparkfun.com/tutorials/qw … okup-guide? Do I not understand what they mean by the words “enable,” “enables,” and “enabling”? Are they implying extreme care?
Please tell me how I sounded, talking about the part of this picture that is highlighted in yellow.
I know the “How to get assistance from a SparkFun Technical Support moderator” page (at viewtopic.php?f=59&t=49379) says “SparkFun does not offer assistance on custom modifications to our existing code,” but if the Example 7 sketch was modified once (to make the sketch at viewtopic.php?p=241251#p241251), maybe it can be modified again to work with MotionCal (which is described at https://learn.adafruit.com/adafruit-sen … -motioncal). If that is not the case, please let me know why. MotionCal seems to me to be easier to understand than The Cave Pearl Project (which is described at https://thecavepearlproject.org/2015/05 … r-arduino/), and I think MotionCal will also give me 9 numbers to make soft iron corrections (which, as far as I can tell, the modified Example 7 sketch doesn’t). MotionCal takes the following format from a sketch that I could use help making.
Serial.print("Raw:");
Serial.print(0); Serial.print(","); // I think these are 0s because there is no accelerometer or gyroscope
Serial.print(0); Serial.print(",");
Serial.print(0); Serial.print(",");
Serial.print(0); Serial.print(",");
Serial.print(0); Serial.print(",");
Serial.print(0); Serial.print(",");
Serial.print(int(scaledX * conversion)); Serial.print(","); // Numbers from magnetometer start here. "conversion" is used because I don't think "scaledX" can be used alone
Serial.print(int(scaledY * conversion)); Serial.print(",");
Serial.print(int(scaledZ * conversion)); Serial.println("");
A user told me that the abovementioned MotionCal (which I think can give me soft iron correction numbers which the modified Example7-I2C_Sensor_Offset can’t) needs values in the 1,000s or 10,000s range. However, because I’m not sure which variables I should use to get values in that range, I’ve been multiplying rawValueX and scaledX (from Example2-I2C_Digital_compass) and currentX, normalizedX, and scaledX (from Example7-I2C_Sensor_Offset and the modified one) by different numbers. It would save me a lot of time if someone told me which variable I should use and what I should do to it, and I might learn something if I was told why.
I’m not completely sure, but I think MotionCal is expecting values in milliGauss. I was expecting it to be microTesla, but that doesn’t seem to work.
If I replace the loop code in Example7 with this:
void loop()
{
// The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072).
// Use static variables to hold the offset. Set to 131072 initially.
static uint32_t offsetX = 131072;
static uint32_t offsetY = 131072;
static uint32_t offsetZ = 131072;
// Has the user pressed a key?
if (Serial.available())
{
updateOffset(&offsetX, &offsetY, &offsetZ); // Update the offsets
while (Serial.available())
Serial.read(); // Empty the Serial RX buffer
}
uint32_t currentX = 0;
uint32_t currentY = 0;
uint32_t currentZ = 0;
// This reads the X, Y and Z channels simultaneously
myMag.getMeasurementXYZ(¤tX, ¤tY, ¤tZ);
// The magnetic field values are 18-bit unsigned.
// The _approximate_ zero (mid) point should be 2^17 (131072).
// Here we subtract the offset, then scale each field to +/- 1.0,
// then multiply by 8000 to convert to milliGauss
double scaledX = (double)currentX - (double)offsetX; // Convert to double _before_ subtracting
scaledX /= 131072.0;
scaledX *= 8000.0;
double scaledY = (double)currentY - (double)offsetY; // Convert to double _before_ subtracting
scaledY /= 131072.0;
scaledY *= 8000.0;
double scaledZ = (double)currentZ - (double)offsetZ; // Convert to double _before_ subtracting
scaledZ /= 131072.0;
scaledZ *= 8000.0;
// Print the data in MotionCal format
Serial.print("Raw:0,0,0,0,0,0,");
Serial.print(scaledX, 0); // Print with 0 decimal places
Serial.print(",");
Serial.print(scaledY, 0);
Serial.print(",");
Serial.println(scaledZ, 0);
}
Before I do the updateOffset, I get data like this:
If I select COM1 in MotionCal (to disconnect from COM13), open the Arduino Serial Monitor, send a character to do the updateOffset, close the Serial Monitor, change the MotionCal port back to COM13 to reconnect, then I get this:
It did help. For some reason, with my calibration function, I could only get it to work when the y parameter was left of the x parameter. And sometimes MotionCal stops, so I have to open it again, but it eventually works.
Apologies for reopening this thread, but it seems to contain a lot of useful info (which I’ve read several times!)
I’ve got this Qwiic board connected successfully to a STM32 micro. I grabbed the code from Example7 for the offsets (I get e.g. 129971,130303,130991), and patched those into the DigitalCompass example:
double scaledX = 0;
double scaledY = 0;
double scaledZ = 0;
// The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072).
// Here we scale each field to +/- 1.0 to make it easier to calculate an approximate heading.
//
// Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true
// offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at:
// https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/
scaledX = scalarX * ((double)rawValueX - (double)offsetX);
scaledX /= 131072.0;
scaledY = scalarY * ((double)rawValueY - (double)offsetY);
scaledY /= 131072.0;
scaledZ = scalarZ * ((double)rawValueZ - (double)offsetZ);
scaledZ /= 131072.0;
// Magnetic north is oriented with the Y axis
// Convert the X and Y fields into heading using atan2 (Arc Tangent 2)
heading = atan2(scaledX, 0.0 - scaledY);
// atan2 returns a value between +PI and -PI
// Convert to degrees
heading /= M_PI;
heading *= 180.0;
heading += 180.0;
(The ‘scalar’ variables are all 1.0 at present).
First thing I’m confused about is that my headings are 180 out - I believe the mounting hole of the board is North? Maybe it’s as simple as “the hole is south”, the video https://www.youtube.com/watch?v=mlgslhsQ-L8&t=1027s does seem to confirm my assumption - chip pin 1 = SW.
atan2(0.0 - scaledX, scaledY) does fix this, I’m just checking I’ve not got something else wrong.
In addition to this, I reckon my results are about 15deg out :S I’ve started trying to understand whether I need to work out the gain cal, and have hooked up the MotionCal app, but not sure yet how to use its results!
Yep, I believe I’ve done the offset correction. Do I need to figure out gain calibration too? (I’m not looking for mega accuracy, less than about 5 degrees would be enough for my application)