2024-02-16 06:48 AM - last edited on 2024-07-08 04:54 AM by Peter BENSCH
Hi everyone,
First of all, I use a STWINBX1 board, which include a MCU and several sensors. I try to get the magnetic field by reading the output of the magnetometer (IIS2MDC), but the output value seems false.
Please note that :
- I checked the PIN configuration on STM32 CubeIDE, and the PINs are well configured.
- I use HAL library to configure the chipset (IIS2MDC), and to use I2C protocol.
- I tested 2 differents methods of reading the output using I2C functions from HAL (HAL_I2C_Mem_Read and HAL_I2C_Master_Receive). Both method return me the same output, which is even more confusing for me.
- I have two differents boards of the same models that give me the same errors in the output.
- The slave address (of the Magnetometer) is 0011110b. I have two variable for read and write the slave, which are :
uint16_t IIS2MDCTR_ADDR_VAR_R = 0x3D; // 00111101b
uint16_t IIS2MDCTR_ADDR_VAR_W = 0x3C; // 00111100b
I store them inside a uint16_t as the HAL library need uint16_t address in functions that I use, but these addresses could fit in a single byte.
I am not used to these kinds of datasheet, so I have severals questions.
The datasheet of the magnetometer give an output x, y, z. Each axis are composed of two bytes. Its said that the output is expressed in "two’s complement".
Basically, that mean that the output will be a signed integer (that can be positive or negative) ?
As the output is given on two different bytes, I guess that the sign of the total output (combination of the two bytes) is the biggest bit of the MSB ?
Here is one of the two method I used to read the output of the magnetometer (on one axis, "x", for example) :
I removed errors managements of the code to make it clearer
int16_t getMagneticField(uint8_t LSB_addr){
char buffer_message[100];
uint8_t buf[2];
uint8_t buf_receive[2];
uint16_t slave_addr_read = 0x3D;
uint16_t slave_addr_write = 0x3C;
buf[0] = 0x60; // address of CFG_REG_A (used to configure how we use the magnetometer)
buf[1] = 0x81; // 1000 0001 bit configured to allow single mode
HAL_I2C_Master_Transmit(&hi2c2, slave_addr_write, buf, 2, HAL_MAX_DELAY);
HAL_StatusTypeDef ret = HAL_I2C_Mem_Read(&hi2c2, slave_addr_read, LSB_addr, I2C_MEMADD_SIZE_8BIT, buf_receive, 2, HAL_MAX_DELAY);
int16_t result = (((int16_t)buf_receive[1]) << | buf_receive[0];
return result * sensitivity;
}
For context, here is the configuration of the magnetometer :
void ConfigureMagnetometer()
{
uint8_t buf[2];
buf[0] = 0x60; // addresse du registre CFG_REG_A
buf[1] = 0x81; // 1000 0001 bit configured (enable temperature/single mode read)
HAL_I2C_Master_Transmit(&hi2c2, IIS2MDCTR_ADDR_W, buf, 2, HAL_MAX_DELAY);
buf[0] = 0x61; // addresse du registre CFG_REG_B
buf[1] = 0x12; // 0001 0010 bit configured (enable offset cancellation in single mode read)
HAL_I2C_Master_Transmit(&hi2c2, IIS2MDCTR_ADDR_W, buf, 2, HAL_MAX_DELAY);
buf[0] = 0x62; // addresse du registre CFG_REG_C
buf[1] = 0x10; // 0001 0000 bit configured
HAL_I2C_Master_Transmit(&hi2c2, IIS2MDCTR_ADDR_W, buf, 2, HAL_MAX_DELAY);
HAL_Delay(20);
}
So, my problem is :
When i read the first byte of data (the LSB), the value seem fine. She is updating as I move the board myself.
The other byte of data (the MSB), is always min value (0), or max value (255). He is sometimes equal to 1 or 254, but more rarely, which seems false. And it seem to exist a pattern with these value, with max, min or max -1, or min + 1.
In addition, I intepret the output x, y, z with a simple computing (sqrt of squarred x + squarred y + squarred z), and also this intepretation give me false results, as this result must be constant (when x, y and z change), but its not the case.
I tried to give you the more context I can. If you need any others information to understand my problem, feel free to ask, I'll answer you.
I don't know what I am doing wrong here. Thanks for your help, have a good day.
2024-02-20 06:40 AM
A little update if someone want to take informations from this post
- The documentation seems to say that continous mode (configurable in CFG_REG) automatically apply offset.
- Its also said (in application note => an5080-iis2mdc.pdf page 19/26 : If we use the sensors in single-mode instead of continuous mode.
"The computation of the hard-iron distortion field should be performed by an external processor."
I dont know why, but it seems that we need an external sensor to measure the offset if we want to use IIS2MDC in single mode.
If someone have more informations about that, feel free to share !
2024-02-20 07:36 AM
The readings from a magnetic field is difficult to use. If you want your equation to hold, your sensor must be calibrated to remove the offset and apply scaling factors. This calibration is nontrival. For example, here is a 30 page manual for how to do it on one device:
https://www.mouser.com/pdfDocs/MagneticCalibrationManual-2.pdf
On this device, calibration would be setting the OFFSET_X_REG values to the midpoint of the values obtained when rotating the sensor in a circle among all orientations.