2
\$\begingroup\$

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);
            }
\$\endgroup\$
  • 1
    \$\begingroup\$ I suspect you're getting small (and reasonable) negative numbers. \$\endgroup\$ – Brian Drummond Aug 6 '17 at 21:41
4
\$\begingroup\$

You use int16_t as fields in your struct, but print %u. That's wrong – %u should be 32 bit on your platform, not 16.

\$\endgroup\$
  • \$\begingroup\$ Thar is correct! changing it to %d prints more sensible number (not more than the max output for the MPU. I re wrote the entire library thinking it was something wrong with it! The source of all my anger and anxiety has been because of one character, i completetly ignored it the printf because i was using it to print some values some time back but i never changed it for int16_t . But that is programming in a nutshell. Thanks for your help \$\endgroup\$ – kelvinmac Aug 6 '17 at 20:21
  • 1
    \$\begingroup\$ I'll say something sarcastic like: and that, kids, is why binary protocols often are easier to use than their only superficially more beautiful cousins, the clear text. \$\endgroup\$ – Marcus Müller Aug 6 '17 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.