1
\$\begingroup\$

TL;DR: I experience communication breaks while using GY-521 (MPU6050 based) with STM32F4 in I2C communication, and I am looking for the result of these breaks.

Also should I give a 5 V Vcc or 3 V Vcc to GY-521? Does it matter or not?

I am using GY-521, its schematic can be found here.

I use it with my STM32F4-DISC board, and the only connections I made are:

Vcc -> 3V GND -> GND SCL -> SCL SDA -> SDA

Where the left ones are the pins of GY-521 and others are STM32 pins.

The configurations about STM32 is probably fine because I can get values when it works.

Now, the question is if any disconnections happen, i.e a jumper is unplugged for example (scl, sda, Vcc, gnd do not matter), then the communication gets canceled and replugging that connection does not start it again. I am watching the communication using STMStudio (simultaneous variable tracker program) by the way.

So few guesses of mine, I am initiating the sensor by calling this function in main before while(1);

void MPU6050_Init() {

  uint8_t Data = 0 ;
  uint8_t check = 99;

  HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

  if (check == 0x68) {
    Data = 0;
    HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR , PWR_MGMT_1_REG, 1, &Data, 1, 1000);

    Data=0x07;
    HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR , SMPLRT_DIV_REG, 1, &Data, 1, 1000);

    // 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, 1000);

    // Set Gyroscopic 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, 1000);
  }
}

So one of my guesses is the MPU6050 resets itself when VCC or GND is disconnected because it loses its power. So I have to reset the MCU to initialize the sensor again. However, some observations conflict with this idea.

  1. Reset does not solve the issue.
  2. Without GND connected, there is still power on the GY-521 so the LED on it (I assume power LED) still shines but not as bright as with GND connected (And this is not happening always, sometimes the power goes down, sometimes it doesn't. This issue by itself is another question maybe you can answer).
  3. If it were a power lost/reset issue, then disconnecting SCL/SDA should not break the data communication, it should continue when I replug those jumpers.

And sometimes even when nothing is disconnected, if I press the reset button it breaks the communication, and sometimes it does not. (For example, I don't touch any connections, just tap the reset button, it resets and communication works for 2 presses but in the 3rd it gets broken. (2 and 3 aren't certain values just for one trial)).

So, in short, I could not find a logical reasoning system so that I could ask when I do that this happens. It's like randomly happening.

Edit : I have added a power an LED command in the if block of this init function for debugging purposes and observed that after the problematic resets, it actually does not enter the if and init the MPU6050. So may this be about poor cabling (breadboard, jumper instead of soldering)?

I am attaching the relevant code blocks.

void MPU6050_Read_Accel (void) {
  uint8_t Rec_Data[6];

  // Read 6 BYTES of data starting from ACCEL_XOUT_H register

  HAL_I2C_Mem_Read (&hi2c1, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, Rec_Data, 6, 1000);

  Accel_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data [1]);
  Accel_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data [3]);
  Accel_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data [5]);

  /*** convert the RAW values into an acceleration in 'g'
         we have to divide according to the Full-scale value set in FS_SEL
         I have configured FS_SEL = 0. So I am dividing by 16384.0
         for more details check ACCEL_CONFIG Register              ****/

  Ax = Accel_X_RAW/16384.0;
  Ay = Accel_Y_RAW/16384.0;
  Az = Accel_Z_RAW/16384.0;
}


void MPU6050_Read_Gyro (void) {
  uint8_t Rec_Data[6];

  // Read 6 BYTES of data starting from GYRO_XOUT_H register

  HAL_I2C_Mem_Read (&hi2c1, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, Rec_Data, 6, 1000);

  Gyro_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data [1]);
  Gyro_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data [3]);
  Gyro_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data [5]);

  /*** convert the RAW values into DPS (°/s)
         we have to divide according to the Full-scale value set in FS_SEL
         I have configured FS_SEL = 0. So I am dividing by 131.0
         for more details check GYRO_CONFIG Register              ****/

  Gx = Gyro_X_RAW/131.0;
  Gy = Gyro_Y_RAW/131.0;
  Gz = Gyro_Z_RAW/131.0;
}

The above are functions.

  MPU6050_Init();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1) {
    /* USER CODE END WHILE */
    MX_USB_HOST_Process();

    /* USER CODE BEGIN 3 */
    MPU6050_Read_Accel();
    MPU6050_Read_Gyro();
  }
  /* USER CODE END 3 */
}

And this is the relevant part of the main.

\$\endgroup\$
1
  • \$\begingroup\$ Supply voltage for the MPU6050 is 2.375V-3.46V (VDD) per the datasheet. I would suspect cabling or breadboard or I2C config. I've used many of the MPU6050, MPU9250 and MPU9255 with I2C and the communication is bulletproof. Direct sensor read or reading from the FIFO. Double check the connections. \$\endgroup\$ Mar 15, 2023 at 8:12

1 Answer 1

1
\$\begingroup\$

Well if your software is not handling communication errors, it won't work when you deliberately cause communication errors by unplugging wires randomly. At least you could check the return values if the I2C transactions are done correctly or not. Then decide what to do if it was succesful or not.

Also if you push the MCU reset button while data is transferred from sensor to MCU, the sensor does not know the MCU has been reset so it will wait for the MCU to continue data transfer. If sensor was transmitting a 0 bit on the data wire when MCU is reset, sensor is still keeping data wire low, and the MCU cannot start new transaction. It is again your responsibility to detect this situation and solve the problem by resetting the sensor somehow, perhaps with a i2c reset sequence or powering the sensor off for a while so that the bus is free again.

\$\endgroup\$
4
  • \$\begingroup\$ thanks for the answer, I will try to implement an error handling. So, do you have any idea about whether feeding the sensor's Vcc pin from 5V, 3V, or Vdd pins on the stm32 board makes a difference or not? \$\endgroup\$
    – muyustan
    Jul 24, 2019 at 10:56
  • \$\begingroup\$ I tried to reset the sensor by writing to one of its registers when the return status of the writing/reading is not OK, but I guess writing is the problem itself. So I cannot achieve a reset by this. \$\endgroup\$
    – muyustan
    Jul 24, 2019 at 11:13
  • \$\begingroup\$ If the I2C bus is stuck like described in the answer, master MCU can send 9 pulses on the SCl line to reset the bus. This should cause the slave devices to release the SDA line \$\endgroup\$
    – chamod
    Feb 2, 2023 at 1:42
  • \$\begingroup\$ @chamod If the slave is data receive mode and currently pulling low because it sends an ACK bit, after 9 clock pulses, it will be pulling low again for the next ACK bit. So in this case, exactly 9 clock pulses will not work. \$\endgroup\$
    – Justme
    Feb 2, 2023 at 5:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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