Search code examples
stm32magnetometer

I2C with stm32f4 using HMC5883l


I've been trying to connect my HMC5883l board to stm32f4, however something is not working properly. I've initiated the i2c, sent the configuration bits to REGA, REGB and REGMR (Mode Register) and sent it back via USB connection with HAL_I2C_MEM_READ.

The results are:

  • xaxis and zaxis have the same value
  • main loop works only once, and to get another values i need to plug out the STM

enter image description here

  • I've been trying to check if there are changes in value (axis x) wtih oscilloscope but it showed no changes at all (rotating the board)

enter image description here

What am i missing in here? Is it possible that board is damaged?

 int main(void)
{
    /* USER CODE BEGIN 1 */
    /* USER CODE END 1 */

    /* MCU Configuration----------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */
    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_USB_DEVICE_Init();
    MX_I2C3_Init();
    /* USER CODE BEGIN 2 */
//  HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

    HAL_I2C_Mem_Write(&hi2c3, HMC5883l_ADDRESS, 0b00000000 , 1, HMC5883l_Enable_A   , 1, 100);
    HAL_I2C_Mem_Write(&hi2c3, HMC5883l_ADDRESS, 0b00000001 , 1, HMC5883l_Enable_B   , 1, 100);
    HAL_I2C_Mem_Write(&hi2c3, HMC5883l_ADDRESS, 0b00000010 , 1, HMC5883l_MR         , 1, 100);

    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        HAL_I2C_Mem_Read(&hi2c3, HMC5883l_ADDRESS, HMC5883l_ADD_DATAX_MSB_LSB, 1, DataX, 2, 100);
        Xaxis = ((DataX[1] << 8) | DataX[0]);
        magn_x_gs = ((float)Zaxis*MAX_RESOLUTION)/(float)INT16_MAX; // conversion

        HAL_I2C_Mem_Read(&hi2c3, HMC5883l_ADDRESS, HMC5883l_ADD_DATAY_MSB_LSB , 1, DataY, 2, 100);
        Yaxis = ((DataY[1] << 8) | DataY[0]);
        magn_y_gs = ((float)Yaxis*MAX_RESOLUTION)/(float)INT16_MAX;

        HAL_I2C_Mem_Read(&hi2c3, HMC5883l_ADDRESS, HMC5883l_ADD_DATAZ_MSB_LSB , 1, DataZ, 2, 100);
        Zaxis = ((DataZ[1] << 8) | DataZ[0]);
        magn_z_gs = ((float)Zaxis*MAX_RESOLUTION)/(float)INT16_MAX;
    }

Solution

  • Ok, I've created the correct version of the connection :)

    // variables for receiving DATA
    uint8_t DataX[2];
    uint16_t Xaxis = 0;
    uint8_t DataY[2];
    uint16_t Yaxis = 0;
    uint8_t DataZ[2];
    uint16_t Zaxis = 0;
    
    // adresses     
    // HMC5883l - ADDRESS
    #define HMC5883l_ADDRESS (0x1E << 1)
    // CONTROL REG A
    #define HMC5883l_Enable_A (0x78)
    // CONTROL REG B
    #define HMC5883l_Enable_B (0xA0)
    // MODE REGISTER
    #define HMC5883l_MR (0x00)
    // HMC5883l - MSB / LSB ADDRESSES
    #define HMC5883l_ADD_DATAX_MSB (0x03)
    #define HMC5883l_ADD_DATAX_LSB (0x04)
    #define HMC5883l_ADD_DATAZ_MSB (0x05)
    #define HMC5883l_ADD_DATAZ_LSB (0x06)
    #define HMC5883l_ADD_DATAY_MSB (0x07)
    #define HMC5883l_ADD_DATAY_LSB (0x08)
    // SUM (MSB + LSB) DEFINE
    #define HMC5883l_ADD_DATAX_MSB_MULTI (HMC5883l_ADD_DATAX_MSB | 0x80)
    #define HMC5883l_ADD_DATAY_MSB_MULTI (HMC5883l_ADD_DATAY_MSB | 0x80)
    #define HMC5883l_ADD_DATAZ_MSB_MULTI (HMC5883l_ADD_DATAZ_MSB | 0x80) 
    

    Inside of main() i've got to create variables to actually use the RegSetting etc.

    uint8_t RegSettingA = HMC5883l_Enable_A;
    uint8_t RegSettingB = HMC5883l_Enable_B;
    uint8_t RegSettingMR = HMC5883l_MR;
    

    And clear variables:

    Xaxis = 0;
    Yaxis = 0;
    Zaxis = 0;
    

    Initialize connection:

    HAL_I2C_Mem_Write(&hi2c3, HMC5883l_ADDRESS, 0x00 , 1, &RegSettingA , 1, 100);
    HAL_I2C_Mem_Write(&hi2c3, HMC5883l_ADDRESS, 0x01 , 1, &RegSettingB , 1, 100);
    HAL_I2C_Mem_Write(&hi2c3, HMC5883l_ADDRESS, 0x02 , 1, &RegSettingMR , 1, 100);
    

    And inside of while(1) loop:

    // RECEIVE X_axis
    HAL_I2C_Mem_Read(&hi2c3,HMC5883l_ADDRESS,HMC5883l_ADD_DATAX_MSB_MULTI,1,DataX,2,100);
    Xaxis = ((DataX[1]<<8) | DataX[0])/660.f;
    // RECEIVE Y_axis
    HAL_I2C_Mem_Read(&hi2c3,HMC5883l_ADDRESS,HMC5883l_ADD_DATAY_MSB_MULTI,1,DataY,2,100);
    Yaxis = ((DataY[1]<<8) | DataY[0])/660.f;
    // RECEIVE Z_axis
    HAL_I2C_Mem_Read(&hi2c3,HMC5883l_ADDRESS,HMC5883l_ADD_DATAZ_MSB_MULTI,1,DataZ,2,100);
    Zaxis = ((DataZ[1]<<8) | DataZ[0])/660.f;
    

    Since output data is a connection of MSB and LSB we've got (and LSB is 0x00) we've got to move Data[1] for 8 bits forward.

    Here are the STM Studio's results: link

    Best Regards :)