2025-02-26
7:43 AM
- last edited on
2025-02-26
8:08 AM
by
Lina_DABASINSKA
Hello everyone,
I'm contacting you today in order to understand my error during the calibration of my LSM303AGR sensor located on a PCB. The ultimate goal is to create a compass with tilt compensation but I try to get a good precision with magnetometer first. Of course, I took care to read up on the Internet before opening this post, but all the ideas seem to be divergent and I can't find my way around.
First, I got the raw acceleration and magnitude data from my sensor. So far, so good. As part of my calibration, I generated a data set during which I rotate the sensor in all possible directions to cover all angles. I then measured the hard iron to eliminate offsets on each axis :
def calculate_hard_iron(data):
max_vals = np.max(data, axis=0)
min_vals = np.min(data, axis=0)
return (max_vals + min_vals) / 2
Then I calculated the soft iron by normalizing my data while preserving the centering :
def calculate_soft_iron(data):
# Centering data
mean = np.mean(data, axis=0)
centered_data = data - mean
# Find the scaling factors for each axis
ranges = np.ptp(centered_data, axis=0) # peak to peak range
scale_factors = np.max(ranges) / ranges
# Normalize
corrected_data = centered_data * scale_factors
avg_radius = np.mean(np.sqrt(np.sum(corrected_data**2, axis=1)))
scale = 1.0 / avg_radius
# Apply final scaling
corrected_data = corrected_data * scale
transformation_matrix = np.diag(scale_factors * scale)
return corrected_data, transformation_matrix
I arrive at the following resultt :
Following this, I am able to identify my hard iron vector and my soft iron matrix :
Hard Iron Offset: [-368.0, 390.5, 185.5]
Soft Iron Matrix:
[[0.0020697, 0, 0]
[0, 0.00216311, 0]
[0, 0, 0.00205197]]
Apriori, I should be able to interpret a movement using the parameters calculated in the calibration step. So I decide to generate a dataset in which I perform a 360° turn on XY plan, and here is the result :
What stands out is that the offset problem in the data set subsequently caused a loss of information. However, I did deduce the data from the offset measured during the calibration phase. What did I do wrong ?
Thank you for your attention.
2025-03-06 11:05 AM
From your plot it is evident that hard-iron offset has not been compensated correctly. When you perform a rotation around the vertical, with the mag in the horizontal flat plan, the mag data points always describe a circle/ellipse in a 2D horizontal plane, all points will have the same Z coordinate.
When hard-iron is successfully compensated, the points in the X-Y plot will describe a circle/ellipse centered in the origin which is not the case looking at your plot. This is the biggest source of error (soft-iron effects are usually minor) and this is evident in your case: the scaling factors along the diagonal are very similar to each other. Note that the absolute scaling of the compensated mag does not matter because when computing the orientation (yaw/heading angle) only ratios matters (usually atan2 function is utilized on tilt-compensated data as explained in design tip DT0058).
The method to compute the hard-iron is ok but accuracy will highly depend on how good is the sweep on each axis. Similarly for the method used to compute the scaling factors. A more robust method is discussed in design tip DT0059.
2025-03-12 9:24 AM
Dear @Andrea VITALI ,
Thank you for your reply. I appreciate your help ! In fact, the last screens I shared were about a rotation on the XY plane with a tilt. That's why the z was not constant. However, the problem is the same with or without tilt.
I read DT0058 and DT0059 and tried to apply the approach. However, the result is the same even if it seems better than my version. The offsets are not fully compensated.
Here's the calibration step, which looks clean :
I can get the parameters required for my application :
- Hard-Iron : [-559.5, 373.5, 1081.0 ]
- Gain : [499.5, 529.5, 561.0 ]
Here is an example in a 360° configuration in 2D without tilt. I stopped the rotation every 90 degrees for few seconds. I get this :
Here is an example in a 360° configuration in 2D with tilt. I stopped the rotation every 90 degrees for few seconds. I get this :
If you have any ideas on how to solve this problem, I would be grateful.
Regards
2025-03-12 9:32 AM
The hard-iron is compensated when you do the calibration. But when you do the 2D rotation in the horizontal plane (no tilt) it is clear there is hard-iron.
Are you changing the location of the magnetometer?
The calibration should be performed in the same environment where the mag is utilized. Generally speaking, it is not possible to calibrate 'at the factory' and then utilize 'in the field' because the magnetic environment can be dramatically different.
Possible sources of hard-iron are: permanent magnets, ferromagnetic materials that become magnetized (iron, steel and such alloys), wires (including neighboring PCB tracks) that carry large currents.
Is there anything like that in the environment where you do the 2D rotation?
2025-03-13 1:48 AM
The LSM303AGR is located on a PCB, close to other components such as resistors and capacitors, but none of these should cause interference. It is placed on a daughter board, with the main board 2/3cm below. As for the calibration location, I have never tried to calibrate the sensor anywhere other than in my office. I isolated the system from disturbances, away from the computer, etc. I have never tried to calibrate the sensor at another location because I can't transport the system and read the data.
I will try to make some tests at another location to eliminate the suspicion of interference in my office.