I am working with a NUCLEO-F401RE board and I want to connect the accelerometer sensor MPU6050 (on a GY-521 module). The device can be connected to the board over I2C.
I connected the 3.3V of the board to VCC, GND to GND, SDA to PB9 and SCL to PB8.
I also tried to connect pull up resistor (10k) between VCC and SDA and VCC & SCL.
With the code below, I am trying to see if the device is connected however, the code desperately returns HAL_ERROR
status code 1.
More specifically, this line HAL_I2C_IsDeviceReady(&hi2c1, MPU6050_ADDR, 10, i2c_timeout)
return the code 1 that corresponds to HAL_StatusTypeDef
HAL_ERROR
I did try with 3 different devices and all behave the same way.
When I try to read WHO_AM_I_REG
(register 0x75) I am getting 0.
What am I doing wrong ?
#include "stm32f4xx_hal.h"
#include "uart.h"
#include <stdio.h>
#define SMPLRT_DIV_REG 0x19
#define GYRO_CONFIG_REG 0x1B
#define ACCEL_CONFIG_REG 0x1C
#define ACCEL_XOUT_H_REG 0x3B
#define TEMP_OUT_H_REG 0x41
#define GYRO_XOUT_H_REG 0x43
#define PWR_MGMT_1_REG 0x6B
#define WHO_AM_I_REG 0x75
I2C_HandleTypeDef hi2c1;
void i2c1_init(void);
void MPU6050_Init(void);
// Setup MPU6050
#define MPU6050_ADDR (0x68 << 1) // 0xD0
const uint16_t i2c_timeout = 100;
int main() {
HAL_Init();
i2c1_init();
uart_init();
MPU6050_Init();
while (1) {
}
}
void i2c1_init(void) {
/*
* PB8 --> I2C1_SCL
* PB9 --> I2C1_SDA
*/
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // alternate function - open drain
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Remap I2C1 pins
//__HAL_RCC_AFIO_CLK_ENABLE();
//__HAL_AFIO_REMAP_I2C1_ENABLE();
// Configure I2C
__HAL_RCC_I2C1_CLK_ENABLE();
__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(2);
__HAL_RCC_I2C1_RELEASE_RESET();
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // half-high, half low
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
printf("Error setting up the I2C !\n");
}
}
void MPU6050_Init(void) {
uint8_t check, Data;
HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(&hi2c1, MPU6050_ADDR, 10,
i2c_timeout);
if (status != HAL_OK) {
printf("Is Ready: %d \n", status);
}
// check device ID WHO_AM_I
HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);
if (check == 104) // 0x68 will be returned by the sensor if everything goes well
{
// power management register 0X6B we should write all 0's to wake the sensor up
Data = 0;
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &Data, 1,
i2c_timeout);
// Set DATA RATE of 1KHz by writing SMPLRT_DIV register
Data = 0x07;
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &Data, 1,
i2c_timeout);
// Set accelerometer configuration in ACCEL_CONFIG Register
// XA_ST=0; YA_ST=0; ZA_ST=0; FS_SEL=0 -> +: 2g
Data = 0x00;
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &Data, 1,
i2c_timeout);
// Set Guroscopic configuration in GYRO_CONFIG Register
// XG_ST=0; YG_ST=0; ZG_ST=0; FS_SEL=0 -> +/- 250 °/s
Data = 0x00;
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &Data, 1,
i2c_timeout);
}
}
void SysTick_Handler(void) {
HAL_IncTick();
}