I'm trying to send data from the gyro in MPU6050 to the computer over UART, but for reasons unknown by me, I'm getting values twice as large as the maximum value of an integer (4294967247). I've checked the wiring and I'm certain that it's working fine.
Im using the SMT32F103C8:
MPU: VCC -> STM32: 3v3
MPU: GND-> STM32: GND
MPU: SCL -> STM32: PB6
MPU: SDA -> STM32: PB7
MPU: ADO -> STM32: GND
MPU: INT -> STM32: PB4
I know that I2C is working fine because I can write and read from the internal registers, such as the sleep register, I can set it to 1 and read 1 or set it to 0 and read 0.
This is some data that I logged, when I move it by hand:
Gyro X: 169
Gyro Y: 4294967177
Gyro Z: 4294967104
Gyro X: 61
Gyro Y: 4294967194
Gyro Z: 4294967079
Gyro X: 221
Gyro Y: 4294967243
Gyro Z: 4294967114
Gyro X: 247
Gyro Y: 4294967226
Gyro Z: 4294967100
Gyro X: 245
Gyro Y: 4294967224
Gyro Z: 4294967104
Gyro X: 255
Gyro Y: 4294967219
Gyro Z: 4294967091
Gyro X: 220
Gyro Y: 4294967234
Gyro Z: 4294967081
Gyro X: 302
Gyro Y: 4294967247
Gyro Z: 4294967100
Gyro X: 4294961910
Gyro Y: 11540
Gyro Z: 3815
Gyro X: 4294961799
Gyro Y: 4294952795
Gyro Z: 4294962484
Gyro X: 1215
Gyro Y: 11904
Gyro Z: 845
Gyro X: 4294960722
Gyro Y: 2173
Gyro Z: 9881
Gyro X: 118
Gyro Y: 4294949006
Gyro Z: 4294959017
Gyro X: 237
Gyro Y: 226
Gyro Z: 4294967131
Gyro X: 4,294,964,816
Gyro Y: 4294955893
Gyro Z: 4294964117
Gyro X: 756
Gyro Y: 4294966889
Gyro Z: 394
Gyro X: 544
Gyro Y: 4294967064
Gyro Z: 4294966905
Gyro X: 4294963519
Gyro Y: 3233
Gyro Z: 6166
Gyro X: 2485
Gyro Y: 4294962643
Gyro Z: 4294960238
Result Structure:
typedef struct {
int16_t Gyroscope_X; /*!< Gyroscope value X axis */
int16_t Gyroscope_Y; /*!< Gyroscope value Y axis */
int16_t Gyroscope_Z; /*!< Gyroscope value Z axis */
float Temperature; /*!< Temperature in degrees */
} MPU6050_GYROResult;
The important function:
HAL_StatusTypeDef MPU::GetRawGyro(MPU6050_GYROResult *result)
{
uint8_t I2C2_Buffer_Rx[6];
/*Read the 6 gyro registers from the device*/
HAL_StatusTypeDef statResult = this->I2C_BufferRead(MPU6050_DEFAULT_ADDRESS, I2C2_Buffer_Rx , MPU6050_RA_GYRO_XOUT_H, 6);
result->Gyroscope_X = (((int16_t)I2C2_Buffer_Rx[0]) << 8) | I2C2_Buffer_Rx[1];
result->Gyroscope_Y = (((int16_t)I2C2_Buffer_Rx[2]) << 8) | I2C2_Buffer_Rx[3];
result->Gyroscope_Z = (((int16_t)I2C2_Buffer_Rx[4]) << 8) | I2C2_Buffer_Rx[5];
return statResult;
}
CODE main:
static void MPU6050_Init(void)
{
mpu = new Core::MPU();
if(mpu->Initialize() != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
return;
}
mpu->EnableAllFIFOBit();
}
/*
..............
* stm32 initialize code (default)
*/
int main()
{
MPU6050_Init(); //init
while (1)
{
Core::MPU6050_GYROResult GyroData;
mpu->GetRawGyro(&GyroData);
printf("Gyro X: ");
printf("%u\n", GyroData.Gyroscope_X);
printf("\n\r");
printf("Gyro Y: ");
printf("%u\n", GyroData.Gyroscope_Y);
printf("\n\r");
printf("Gyro Z: ");
printf("%u\n", GyroData.Gyroscope_Z);
printf("\n\r");
printf("\n\r");
HAL_Delay(1060);
/* USER CODE END WHILE */
}
}
I2C init Code
HAL_StatusTypeDef MPU::I2C_init()
{
//Enable the clock for gpioc
__HAL_RCC_GPIOB_CLK_ENABLE();
//Enable clock for I2C1
__HAL_RCC_I2C1_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
/*Configure GPIO pins : MPU_I2C1_SCL_Pin MPU_I2C1_SDA_Pin */
GPIO_InitStruct.Pin = MPU_I2C1_SCL_Pin | MPU_I2C1_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
this->i2c1.Instance = I2C1;
this->i2c1.Mode = HAL_I2C_MODE_MASTER;
this->i2c1.Init.ClockSpeed = MPU6050_I2C_Speed;
this->i2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
this->i2c1.Init.OwnAddress1 = MPU6050_DEFAULT_ADDRESS;
this->i2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
this->i2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
this->i2c1.Init.OwnAddress2 = 0;
this->i2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
this->i2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_StatusTypeDef result = HAL_I2C_Init(&this->i2c1);
if (result != HAL_OK)
{
this->ModuleErrorHandle();
}
return result;
}
Initialize Code:
HAL_StatusTypeDef MPU::Initialize()
{
HAL_StatusTypeDef result = this->I2C_init();
if(result == HAL_OK)
{
result = this->SetClockSource(MPU6050_CLOCK_PLL_XGYRO); /* Set clock source as x gyro */
if(result == HAL_OK)
{
result = this->SetFullScaleAccelRange(MPU6050_GYRO_FS_250);
if(result == HAL_OK)
{
result = this->SetFullScaleGyroRange(MPU6050_ACCEL_FS_2);
if(result == HAL_OK)
{
result = this->SetSleepModeStatus(Sys_Disable); /*Take chip off sleepmode*/
this->isInitialized = (result == HAL_OK); /*Chip is initialized */
return result; //return our result
}
}
}
}
return result;
}
Set Clock source code:
HAL_StatusTypeDef MPU::SetClockSource(uint8_t source)
{
return this->WriteBits(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);
}
SetFullScaleAccelRange Code:
HAL_StatusTypeDef MPU::SetFullScaleAccelRange(uint8_t range)
{
return this->WriteBits(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
}
SetFullScaleGyroRange Code:
HAL_StatusTypeDef MPU::SetFullScaleGyroRange(uint8_t range)
{
return this->WriteBits(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range);
}
SetSleepModeStatus Code:
HAL_StatusTypeDef MPU::SetSleepModeStatus(Sys_StatusTypeDef State)
{
return this->WriteBit(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, State);
}
WriteBits Code:
HAL_StatusTypeDef MPU::WriteBit(uint8_t slaveAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data)
{
uint8_t tmp;
HAL_StatusTypeDef result = this->I2C_BufferRead(slaveAddr, &tmp, regAddr, 1);
if(result != HAL_OK)
return result;
tmp = (data != 0) ? (tmp | (1 << bitNum)) : (tmp & ~(1 << bitNum));
return this->I2C_ByteWrite(slaveAddr, &tmp, regAddr);
}
ReadBits Code:
HAL_StatusTypeDef MPU::ReadBits(uint8_t slaveAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data)
{
//I2C_BufferRead(uint8_t slaveAddr, uint8_t* pBuffer, uint8_t readAddr, uint16_t NumByteToRead)
uint8_t tmp;
HAL_StatusTypeDef result = this->I2C_BufferRead(slaveAddr, &tmp, regAddr, 1);
if(result != HAL_OK)
return result;
uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
tmp &= mask;
tmp >>= (bitStart - length + 1);
*data = tmp;
return result;
}
I2C_ByteWrite Code:
HAL_StatusTypeDef MPU::I2C_ByteWrite(uint8_t slaveAddr, uint8_t* pBuffer, uint8_t writeAddr)
{
/*Write data to MPU6050's internal memory*/
return HAL_I2C_Mem_Write(&this->i2c1, (uint16_t)slaveAddr, (uint16_t)writeAddr, I2C_MEMADD_SIZE_8BIT, pBuffer, 1, MPU6050_I2C_TIMEOUTLEN);
}
I2C_ByteRead Code:
HAL_StatusTypeDef MPU::I2C_BufferRead(uint8_t slaveAddr, uint8_t* pBuffer, uint8_t readAddr, uint16_t NumByteToRead)
{
/*Read data from MPU6050's internal memory*/
return HAL_I2C_Mem_Read(&this->i2c1, (uint16_t)slaveAddr, (uint16_t)readAddr, I2C_MEMADD_SIZE_8BIT, pBuffer, NumByteToRead, MPU6050_I2C_TIMEOUTLEN);
}