title: MPU9250 with STM32 - Magnetometer readings are constant
body: <p>Trying to use MPU9250 IMU sensor with my STM32G431RB NUCLEO board. The IMU's accelerometer and gyroscope are working fine. However, magnetometer gives constant values.</p>
  <p>I think magnetometers power mode is set to read-once or off. However, I did not understand what the problem was.</p>
  <p>On GitHub, I tried to implement the MPU9250 library that <em>kriswiner</em> wrote for Arduino. But I don't know whether I succeeded or failed.</p>
  <p>The original code I implemented:</p>
  <p><a href="https://github.com/kriswiner/MPU9250/blob/master/MPU9250BasicAHRS.ino" rel="nofollow noreferrer">https://github.com/kriswiner/MPU9250/blob/master/MPU9250BasicAHRS.ino</a></p>
  <p>The CubeIDE code I wrote for STM32, to configure and read magnetometer:</p>
  <pre class="lang-c prettyprint-override"><code>/* USER CODE END Header */
  /* Includes ------------------------------------------------------------------*/
  #include &quot;main.h&quot;
  #include &quot;i2c.h&quot;
  #include &quot;usart.h&quot;
  #include &quot;gpio.h&quot;
  
  /* Private includes ----------------------------------------------------------*/
  /* USER CODE BEGIN Includes */
  #include &lt;stdio.h&gt;
  #include &lt;math.h&gt;
  /* USER CODE END Includes */
  
  /* Private typedef -----------------------------------------------------------*/
  /* USER CODE BEGIN PTD */
  
  /* USER CODE END PTD */
  
  /* Private define ------------------------------------------------------------*/
  /* USER CODE BEGIN PD */
  
  //Magnetometer Registers
  #define AK8963_ADDRESS   0x0C&lt;&lt;1
  #define AK8963_WHO_AM_I  0x00 // should return 0x48
  #define AK8963_INFO      0x01
  #define AK8963_ST1       0x02  // data ready status bit 0
  #define AK8963_XOUT_L    0x03  // data
  #define AK8963_XOUT_H    0x04
  #define AK8963_YOUT_L    0x05
  #define AK8963_YOUT_H    0x06
  #define AK8963_ZOUT_L    0x07
  #define AK8963_ZOUT_H    0x08
  #define AK8963_ST2       0x09  // Data overflow bit 3 and data read error status bit 2
  #define AK8963_CNTL      0x0A  // Power down (0000), single-measurement (0001), self-test (1000) and Fuse ROM (1111) modes on bits 3:0
  #define AK8963_ASTC      0x0C  // Self test control
  #define AK8963_I2CDIS    0x0F  // I2C disable
  #define AK8963_ASAX      0x10  // Fuse ROM x-axis sensitivity adjustment value
  #define AK8963_ASAY      0x11  // Fuse ROM y-axis sensitivity adjustment value
  #define AK8963_ASAZ      0x12  // Fuse ROM z-axis sensitivity adjustment value
  
  #define WHO_AM_I_MPU9250 0x75 // Should return 0x71
  #define MPU9250_ADDRESS  0x68&lt;&lt;1
  #define INT_PIN_CFG      0x37
  
  /* USER CODE END PD */
  
  /* Private macro -------------------------------------------------------------*/
  /* USER CODE BEGIN PM */
  
  /* USER CODE END PM */
  
  /* Private variables ---------------------------------------------------------*/
  
  /* USER CODE BEGIN PV */
  enum Mscale {
    MFS_14BITS = 0, // 0.6 mG per LSB
    MFS_16BITS      // 0.15 mG per LSB
  };
  
  uint8_t Mscale = MFS_16BITS; // Choose either 14-bit or 16-bit magnetometer resolution
  uint8_t Mmode = 0x02;
  
  const uint16_t i2c_timeoutB = 100;
  /* USER CODE END PV */
  
  /* Private function prototypes -----------------------------------------------*/
  void SystemClock_Config(void);
  /* USER CODE BEGIN PFP */
  
  /* USER CODE END PFP */
  
  /* Private user code ---------------------------------------------------------*/
  /* USER CODE BEGIN 0 */
  int _write(int file, char *ptr, int len)
  {
      HAL_UART_Transmit(&amp;hlpuart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);
      return len;
  }
  
  float MagnetoX;
  float MagnetoY;
  float MagnetoZ;
  
  /* USER CODE END 0 */
  
  /**
    * @brief  The application entry point.
    * @retval int
    */
  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_LPUART1_UART_Init();
    MX_I2C3_Init();
    MX_I2C2_Init();
  
    /* USER CODE BEGIN 2 */
      printf(&quot;**************************** \r\n&quot;);
      printf(&quot;MPU9250 STM32 Implementation \r\n&quot;);
      printf(&quot;**************************** \r\n&quot;);
  
    //pre-def. vars
      uint8_t readData;
      uint8_t writeData;
  
      // Check MPU and Mag---------------------------------------------------------------------------------------------------
      //read MPU9255 WHOAMI
      HAL_I2C_Mem_Read(&amp;hi2c2, MPU9250_ADDRESS, WHO_AM_I_MPU9250, 1, &amp;readData, 1, i2c_timeoutB);
      printf(&quot;MPU WHO AM I is (Must return 113): %d\r\n&quot;, readData);
  
      //enable Mag bypass
      writeData = 0x22;
      HAL_I2C_Mem_Write(&amp;hi2c2, MPU9250_ADDRESS, INT_PIN_CFG, 1, &amp;writeData, 1, i2c_timeoutB);
  
      //read AK8963 WHOAMI
      HAL_I2C_Mem_Read(&amp;hi2c2, AK8963_ADDRESS, AK8963_WHO_AM_I, 1, &amp;readData, 1, i2c_timeoutB);
      printf(&quot;MAG WHO AM I is (Must return 72): %d\r\n&quot;, readData);
  
      printf(&quot;------------------------------------------------\r\n&quot;);
  
  
  
  
      //Init Mag-------------------------------------------------------------------------------------------------------------
      //Power down magnetometer
      writeData = 0x00;
      HAL_I2C_Mem_Write(&amp;hi2c2, AK8963_ADDRESS, AK8963_CNTL, 1, &amp;writeData, 1, i2c_timeoutB);
      HAL_Delay(100);
  
      //Enter Fuse ROM access mode
      writeData = 0x0F;
      HAL_I2C_Mem_Write(&amp;hi2c2, AK8963_ADDRESS, AK8963_CNTL, 1, &amp;writeData, 1, i2c_timeoutB);
      HAL_Delay(100);
  
      //Read the x-, y-, and z-axis calibration values
      uint8_t rawMagCalData[3];
      HAL_I2C_Mem_Read(&amp;hi2c2, AK8963_ADDRESS, AK8963_ASAX, 1, &amp;rawMagCalData[0], 3, i2c_timeoutB);
      float calMagX =  (float)(rawMagCalData[0] - 128)/256. + 1.;   // Return x-axis sensitivity adjustment values, etc.
      float calMagY =  (float)(rawMagCalData[1] - 128)/256. + 1.;
      float calMagZ =  (float)(rawMagCalData[2] - 128)/256. + 1.;
  
      printf(&quot;Mag cal off X: %f\r\n&quot;, calMagX);
      printf(&quot;Mag cal off Y: %f\r\n&quot;, calMagY);
      printf(&quot;Mag cal off Z: %f\r\n&quot;, calMagZ);
      HAL_Delay(100);
  
      //Set magnetometer data resolution and sample ODR
      writeData = Mscale &lt;&lt; 4 | Mmode;
      printf(&quot;writeData: %d\r\n&quot;, writeData);
      HAL_I2C_Mem_Write(&amp;hi2c2, AK8963_ADDRESS, AK8963_CNTL, 1, &amp;writeData, 1, i2c_timeoutB);
      HAL_Delay(100);
  
      printf(&quot;------------------------------------------------\r\n&quot;);
  
  
  
      //Read Mag-------------------------------------------------------------------------------------------------------------
      //Read Mag data
      uint8_t rawMagData[6];
      HAL_I2C_Mem_Read(&amp;hi2c2, AK8963_ADDRESS, AK8963_XOUT_L, 1, &amp;rawMagData[0], 6, i2c_timeoutB);
      float MagX = ((int16_t)rawMagData[1] &lt;&lt; 8) | rawMagData[0];
      float MagY = ((int16_t)rawMagData[3] &lt;&lt; 8) | rawMagData[2];
      float MagZ = ((int16_t)rawMagData[5] &lt;&lt; 8) | rawMagData[4];
  
      printf(&quot;Mag X: %f\r\n&quot;, MagX);
      printf(&quot;Mag Y: %f\r\n&quot;, MagY);
      printf(&quot;Mag Z: %f\r\n&quot;, MagZ);
      HAL_Delay(100);
  
      printf(&quot;------------------------------------------------\r\n&quot;);
  
    /* USER CODE END 2 */
  
    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
      /* USER CODE END WHILE */
  
          //Read Mag data
          uint8_t rawMagData[6];
          HAL_I2C_Mem_Read(&amp;hi2c2, AK8963_ADDRESS, AK8963_XOUT_L, 1, &amp;rawMagData[0], 6, i2c_timeoutB);
          MagX = ((int16_t)rawMagData[1] &lt;&lt; 8) | rawMagData[0];
          MagY = ((int16_t)rawMagData[3] &lt;&lt; 8) | rawMagData[2];
          MagZ = ((int16_t)rawMagData[5] &lt;&lt; 8) | rawMagData[4];
  
          //Print to Com port via STLINK
          printf(&quot;Mag X: %f\r\n&quot;, MagX);
          printf(&quot;Mag Y: %f\r\n&quot;, MagY);
          printf(&quot;Mag Z: %f\r\n&quot;, MagZ);
          printf(&quot;------------------------------------------------\r\n&quot;);
          HAL_Delay(1000);
  
      /* USER CODE BEGIN 3 */
  
    }
    /* USER CODE END 3 */
  }
  
  </code></pre>
  <p>UART tab for readings:</p>
  <p><a href="https://i.stack.imgur.com/9ZmxK.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9ZmxK.png" alt="UART screen for readings" /></a></p>
  <p>MPU9250 and Mag.'s WHOAMI readings are fine.</p>