Estoy tratando de enviar datos desde el giro en MPU6050 a la computadora a través de UART, pero por razones desconocidas para mí, estoy obteniendo valores dos veces más grandes que el valor máximo de un número entero (4294967247). He comprobado el cableado y estoy seguro de que está funcionando bien.
Estoy usando el 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
Sé que I2C funciona bien porque puedo escribir y leer desde los registros internos, como el registro de espera, puedo configurarlo en 1 y leer 1 o configurarlo en 0 y leer 0.
Estos son algunos datos que registré cuando los muevo a mano:
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
Estructura del resultado:
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;
La función importante:
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;
}
principal de CÓDIGO:
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 */
}
}
Código de inicio I2C
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;
}
Código de inicialización:
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;
}
Establecer código fuente del reloj:
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);
}
Código SetFullScaleAccelRange:
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);
}
Código SetFullScaleGyroRange:
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);
}
Código SetSleepModeStatus:
HAL_StatusTypeDef MPU::SetSleepModeStatus(Sys_StatusTypeDef State)
{
return this->WriteBit(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, State);
}
Código WriteBits:
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);
}
Código de ReadBits:
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;
}
Código I2C_ByteWrite:
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);
}
Código I2C_ByteRead:
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);
}