Skip to main content
Explorer II
April 24, 2024
Solved

Understanding Output Data from I3G4250D Gyro Sensor on STM32F411e-Discovery

  • April 24, 2024
  • 4 replies
  • 2512 views

Hello STM32 community,

I'm relatively new to STM32 development and I'm currently working with the I3G4250D Gyro Sensor on the STM32F411e-Discovery board. I've been using the stm32f411e_discovery_gyroscope.c file provided by STM32Cube to interface with the sensor.

I've managed to retrieve data from the sensor using the provided code snippet:

BSP_GYRO_GetXYZ(Buffer2);

Xval = Buffer2[0];
Yval = Buffer2[1];
Zval = Buffer2[2];

 

However, the output I'm getting seems to be raw data, and I'm not quite sure how to interpret it correctly. My understanding is that these values represent the raw sensor readings, but I'm unsure how to convert them into meaningful X, Y, and Z values.

Could someone please provide guidance on how to properly interpret and convert these raw values into meaningful data? Additionally, if there are any specific calibration steps or formulas that need to be applied to obtain accurate results, I would greatly appreciate any insights on that as well.

Thank you in advance for your help!

    This topic has been closed for replies.
    Best answer by Federica Bossi

    Hi @Duc ,

    To have data in mdps you need to multiply the raw data in LSB by the sensitivity reported in the datasheet according to your FS setting:

    FedericaBossi_0-1714637772473.png

    In addition, you could also look at our PID examples.

     

    4 replies

    Technical Moderator
    May 2, 2024

    Hi @Duc ,

    To have data in mdps you need to multiply the raw data in LSB by the sensitivity reported in the datasheet according to your FS setting:

    FedericaBossi_0-1714637772473.png

    In addition, you could also look at our PID examples.

     

    Visitor II
    May 7, 2025

    I got the same problem. In addition, I found that the output values keep varying even if the system is at rest (not moving at all). The output values are not zero

    Super User
    May 7, 2025

    @Kushal_Es wrote:

    I got the same problem. 


    So did you do as @Federica Bossi said to fix that?

     


    @Kushal_Es wrote:

    I found that the output values keep varying even if the system is at rest (not moving at all). The output values are not zero


    So what values are you getting?

    All measurements are subject to noise and offsets...

    Do the values change when the system is moving?

    Visitor II
    May 7, 2025



    As I'm using BSP drivers available in the BSP folder of STM32Cube, In the I3G4250D.c file the function is already defined and the sensitivity is being multiplied in this function already (as @Federica Bossi said):

    void I3G4250D_ReadXYZAngRate(float *pfData)
    {
     uint8_t tmpbuffer[6] = {0};
     int16_t RawData[3] = {0};
     uint8_t tmpreg = 0;
     float sensitivity = 0;
     int i = 0;
    
     GYRO_IO_Read(&tmpreg, I3G4250D_CTRL_REG4_ADDR, 1);
    
     GYRO_IO_Read(tmpbuffer, I3G4250D_OUT_X_L_ADDR, 6);
    
     /* check in the control register 4 the data alignment (Big Endian or Little Endian)*/
     if (!(tmpreg & I3G4250D_BLE_MSB))
     {
     for (i = 0; i < 3; i++)
     {
     RawData[i] = (int16_t)(((uint16_t)tmpbuffer[2 * i + 1] << 8) + tmpbuffer[2 * i]);
     }
     }
     else
     {
     for (i = 0; i < 3; i++)
     {
     RawData[i] = (int16_t)(((uint16_t)tmpbuffer[2 * i] << 8) + tmpbuffer[2 * i + 1]);
     }
     }
    
     /* Switch the sensitivity value set in the CRTL4 */
     switch (tmpreg & I3G4250D_FULLSCALE_SELECTION)
     {
     case I3G4250D_FULLSCALE_245:
     sensitivity = I3G4250D_SENSITIVITY_245DPS;
     break;
    
     case I3G4250D_FULLSCALE_500:
     sensitivity = I3G4250D_SENSITIVITY_500DPS;
     break;
    
     case I3G4250D_FULLSCALE_2000:
     sensitivity = I3G4250D_SENSITIVITY_2000DPS;
     break;
     }
     /* Multiplied by sensitivity */
     for (i = 0; i < 3; i++)
     {
     pfData[i] = (float)(RawData[i] * sensitivity);
     }
    }

     

    Visitor II
    May 8, 2025

    The solution provided by you is not able to solve my problem.
    I'm still getting unstable readings when the board is stationery.

    DucAuthor
    Explorer II
    May 8, 2025

    Here is my output when the board is stationary.

    Duc_0-1746711561368.png

    Please update my main.c file as follows:

    /* USER CODE BEGIN Header */
    /**
     ******************************************************************************
     * @file : main.c
     * @brief : Main program body
     ******************************************************************************
     * @attention
     *
     * Copyright (c) 2024 STMicroelectronics.
     * All rights reserved.
     *
     * This software is licensed under terms that can be found in the LICENSE file
     * in the root directory of this software component.
     * If no LICENSE file comes with this software, it is provided AS-IS.
     *
     ******************************************************************************
     */
    
    #include "main.h"
    #include "stdio.h"
    
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    
    uint32_t startTick, endTick, elapsedTime, previousTime = 0;
    uint16_t Timeinterval = 5;
    
    float Buffer2[3] = {0};
    float Xmag = 0.0, Ymag = 0.0, Zmag = 0.0;
    
    
    int main(void)
    {
    
    
     HAL_Init();
    
     SystemClock_Config();
    
     MX_GPIO_Init();
    
     I2C_Init();
    
     if(BSP_LSM303AGR_Mag_Init() == 0){
    	 printf("I2C Mag Sensor OK \n");
     }
     else{
    	 printf("I2C Mag Sensor Error \n");
     }
    
    
     while (1)
     {
    	 startTick = HAL_GetTick();
    
    	 if (startTick - previousTime > Timeinterval){
    
    		 Mag_GetData(Buffer2);
    
    		 Xmag = Buffer2[0];
    		 Ymag = Buffer2[1];
    		 Zmag = Buffer2[2];
    
    		 printf("Xmag: %.2f, Ymag: %.2f, Zmag: %.2f \n", Xmag, Ymag, Zmag);
    
    		 previousTime = HAL_GetTick();
    	 }
    
     }
    
    }
    
    
    
    /**
     * @brief System Clock Configuration
     * @retval None
     */
    void SystemClock_Config(void)
    {
     RCC_OscInitTypeDef RCC_OscInitStruct = {0};
     RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
     /** Configure the main internal regulator output voltage
     */
     __HAL_RCC_PWR_CLK_ENABLE();
     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
     /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
     RCC_OscInitStruct.HSIState = RCC_HSI_ON;
     RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
     RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
     RCC_OscInitStruct.PLL.PLLM = 8;
     RCC_OscInitStruct.PLL.PLLN = 50;
     RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
     RCC_OscInitStruct.PLL.PLLQ = 8;
     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
     {
     Error_Handler();
     }
    
     /** Initializes the CPU, AHB and APB buses clocks
     */
     RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
     |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
     {
     Error_Handler();
     }
    }
    
    /**
     * @brief GPIO Initialization Function
     * @PAram None
     * @retval None
     */
    static void MX_GPIO_Init(void)
    {
     GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* USER CODE BEGIN MX_GPIO_Init_1 */
    /* USER CODE END MX_GPIO_Init_1 */
    
     /* GPIO Ports Clock Enable */
     __HAL_RCC_GPIOE_CLK_ENABLE();
     __HAL_RCC_GPIOC_CLK_ENABLE();
     __HAL_RCC_GPIOH_CLK_ENABLE();
     __HAL_RCC_GPIOA_CLK_ENABLE();
     __HAL_RCC_GPIOD_CLK_ENABLE();
     __HAL_RCC_GPIOB_CLK_ENABLE();
    
     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(CS_I2C_SPI_GPIO_Port, CS_I2C_SPI_Pin, GPIO_PIN_RESET);
    
     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(GPIOD, Green_Led_Pin|Orange_Led_Pin|Red_Led_Pin|Blue_Led_Pin, GPIO_PIN_RESET);
    
     /*Configure GPIO pins : I2C_DRDY_Pin SPI_INT1_Pin SPI_INT2_Pin */
     GPIO_InitStruct.Pin = I2C_DRDY_Pin|SPI_INT1_Pin|SPI_INT2_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    
     /*Configure GPIO pin : CS_I2C_SPI_Pin */
     GPIO_InitStruct.Pin = CS_I2C_SPI_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
     HAL_GPIO_Init(CS_I2C_SPI_GPIO_Port, &GPIO_InitStruct);
    
     /*Configure GPIO pins : I2C_INT1_Pin I2C_INT2_Pin */
     GPIO_InitStruct.Pin = I2C_INT1_Pin|I2C_INT2_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    
     /*Configure GPIO pins : Green_Led_Pin Orange_Led_Pin Red_Led_Pin Blue_Led_Pin */
     GPIO_InitStruct.Pin = Green_Led_Pin|Orange_Led_Pin|Red_Led_Pin|Blue_Led_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
    /* USER CODE BEGIN MX_GPIO_Init_2 */
    /* USER CODE END MX_GPIO_Init_2 */
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
    /**
     * @brief This function is executed in case of error occurrence.
     * @retval None
     */
    void Error_Handler(void)
    {
     /* USER CODE BEGIN Error_Handler_Debug */
     /* User can add his own implementation to report the HAL error return state */
     __disable_irq();
     while (1)
     {
     }
     /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef USE_FULL_ASSERT
    /**
     * @brief Reports the name of the source file and the source line number
     * where the assert_param error has occurred.
     * @PAram file: pointer to the source file name
     * @PAram line: assert_param error line source number
     * @retval None
     */
    void assert_failed(uint8_t *file, uint32_t line)
    {
     /* USER CODE BEGIN 6 */
     /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
     /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */

     

    Visitor II
    May 18, 2025

    Here is the link for my code:
    https://drive.google.com/drive/folders/15S3WrOCoEQsf1KkbwdJvc2Yz634b_gxh?usp=drive_link

    If you can help me better by going through this. I'll be really grateful