Sunday, 9 December 2018

embedded - Cannot read accelerometer values from MPU6050 Interfaced with STM32F303RE


I m working on a "self-balancing robot" with STM32F303RE.I m using STCubeMX to generate the MCU configuration code and then I added the main() to get the values from MPU6050 from the following code :


#include "main.h"
#include "stm32f3xx_hal.h"

/* Private variables-----*/
I2C_HandleTypeDef hi2c1;
uint8_t i;
uint8_t i2cBuff[8];

uint16_t ax,ay,az;
float Xaccel,Yaccel,Zaccel;
#define mpu6050Address 0xD0


int main(void)
{
HAL_Init();
/* Configure the system clock */
SystemClock_Config();

MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
for(uint8_t i=0 ; i <255;i++)
{
if(HAL_I2C_IsDeviceReady(&hi2c1,i,1 ,10) == HAL_OK )
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
break;
}

}


/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
i2cBuff[0]= 0x3B;

HAL_I2C_Master_Transmit(&hi2c1, mpu6050Address, i2cBuff, 1, 10);
i2cBuff[1] = 0x00;
HAL_I2C_Master_Receive(&hi2c1, mpu6050Address, &i2cBuff[1], 6, 10);

ax = -(i2cBuff[1]<<8 | i2cBuff[2]);
ay = -(i2cBuff[3]<<8 | i2cBuff[4]);
az = -(i2cBuff[5]<<8 | i2cBuff[6]);

Xaccel = ax/8192.0;
Yaccel = ay/8192.0;

Zaccel = az/8192.0;
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */

}


But, when I add ax,ay,az or Xaccel,Yaccel,Zaccel variables to watch it is always showing 0.What can be the problem?



Answer



I'm not sure whether this is your problem, but the HAL functions you're using are not the best for reading a register (sub-address) from a device. HAL_I2C_Master_Transmit() writes the specified data to the device and terminates the transmission with an I2C Stop bit. And then HAL_I2C_Master_Receive() starts a new exchange to read data from the device.


But the recommended I2C read sequence on page 36 of the datasheet is different from what your code does. The recommendation is to write the register address value and then send a Repeat Start bit (not a Stop) before reading the data bytes. You can't write, repeat-start, and read with HAL_I2C_Master_Transmit() or HAL_I2C_Master_Receive(). But you can do this with HAL_I2C_Mem_Read().


Try replacing your calls to HAL_I2C_Master_Transmit() and HAL_I2C_Master_Receive() with this single call:


HAL_I2C_Mem_Read(&hi2c1, mpu6050Address, 0x3B, I2C_MEMADD_SIZE_8BIT, &i2cBuff[1], 6, 10);

I'm not sure whether this will fix your problem because the way you're doing it may work for many I2C devices that remember the previous register sub-address from one exchange to the next. If you can read the device's WHO_AM_I register successfully then there may be another problem. For example, perhaps you need to enable or configure the accelerometer before you can read the accelerometer values.


No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...