[STM32] Cannot read data from MPU6500 using I2C - Page 1
Forum section: electronics / general

author: SpareFag
author_rank: Contributor
timestamp: March 31, 2023, 05:09:21 pm
content: Hello,I can't seem to read the WHO_AM_I from the MPU6500. I also tried on a MPU6050, so I think I can rule out the chip malfunction. The HAL_StatusTypeDef returns an HAL_ERROR. I also tried using different I2C pins.Notes:I can read the data using SPI just fine.I tried 1k and 2k pullup resistors.Here are the relevant defines:Code:#define MPU_ADDRESS 0xD0#define MPU_ADDRESS_READ 0xD1#define MPU_WHOAMI 0x75Here is the main loop code:Code:uint8_t data = MPU_WHOAMI,printdata;HAL_StatusTypeDef ret;while (1){ret = HAL_I2C_Mem_Read(&hi2c2, MPU_ADDRESS, MPU_WHOAMI, 1, &data, 1, 1000);if(ret == HAL_OK)sprintf(printdata, "OK\n");else if (ret == HAL_BUSY)sprintf(printdata, "BUSY\n");else if (ret == HAL_ERROR)sprintf(printdata, "ERROR\n");else if (ret == HAL_TIMEOUT)sprintf(printdata, "TIMEOUT\n");CDC_Transmit_FS(printdata, sizeof(printdata));HAL_Delay(1000);}

author: janoc
author_rank: Super Contributor
timestamp: March 31, 2023, 07:14:53 pm
content: Impossible to help you without knowing which STM32 (the I2C peripherals are very different between them and some have notorious bugs - e.g. STM32F103!), without seeing your actual board and the rest of the code, including clock set up and initialization.Put an oscilloscope/logic analyzer on the bus and check whether it is actually talking over I2C at all (and what exactly is being sent!) or whether there is some other problem. I would even suggest connecting something like an I2C eeprom and first making the STM32 code work with that instead of trying to fix both firmware and a potentially temperamental MPU at the same time.I2C configuration on STM32 is complex and it is easy to screw it up. Also HAL is not exactly bug free and issues like "forgetting" to actually turn the peripheral on by setting the necessary enable bit are very common in the HAL code - it will configure everything except turn the thing actually on. Do verify that whatever it writes into the registers actually matches what the datasheet says needs to be set!BTW, check whether HAL is converting between the read and write addresses itself or whether you need to pass the properly shifted address already (your code has MPU_ADDRESS_READ defined but you are reading from MPU_ADDRESS)FYI, these Invensense MPUs (MPU6500, MPU6050, MPU9250, etc ...) are notoriously finicky and love to hang/crash at the slightest provocation, e.g. whenever they don't like some configuration setting (and there are tons of those!). Also, if you don't properly pull-up/down (don't recall which out of top of my head) the pin that selects between the SPI/I2C modes it will randomly switch - typically in the middle of the I2C transaction! The documentation doesn't say anything about needing a pull-up there or this behavior and didn't show the necessary resistors on the pins in the reference circuits either. You will just get a hanging I2C bus and an IMU that stops talking to the CPU at random moments. That has costed me quite a few grey hairs in the past.

author: SpareFag
author_rank: Contributor
timestamp: March 31, 2023, 07:59:04 pm
content: Thank you, I'm going to try using I2C with another piece of firmware.Quote from: janoc on March 31, 2023, 07:14:53 pmAbout this... I defined both MPU_ADDRESS_READ and MPU_ADDRESS and tried both values. I'm a bit confused though... Could someone tell me if the HAL_I2C_Mem_Read function takes the "raw" address or do I need to left shift it? Beause the online examples are really confusing...

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 31, 2023, 08:27:45 pm
content: Quote from: SpareFag on March 31, 2023, 07:59:04 pmThe HAL I2C functions expect the 7-bit slave address shifted left,but there is no need to set the R/W bit explicitely as those functions handle it as needed, so only the address shifted left by 1 bit is required both for reads and writes. (Yes I know this is confusing, but to be fair, most I2C libraries out there use funky conventions regarding slave addresses and there is no two library with the same convention. Pretty horrific.)I suggest defining the constants like so: (explicit 7-bit slave address shifted left by 1 bit)Code:#define MPU_ADDRESS (0x68 << 1)in order to make it explicit in your code - so reading your code later on will not trigger a new hair pull.Your address (0xD0) should work though, as it's effectively (0x68 << 1), unless the AD0 pin of the MPU6500 is not pulled to ground. In I2C mode, AD0 defines the LSB of the 7-bit slave address.Since you fiddled with SPI, and AD0 is a shared pin with the SDO function, it's not unlikely AD0 is not pulled low appropriately.After checking that, and if it still doesn't work, you can always post your code for initializing I2C.