1

I'm working on a project based on MPU6050 GY-521 board connected to my PCB (running with an ATMega328P). The code was developed in Arduino.

The PCB is the second version. The first one works fine with the same accelerometer.

But with the second version I'm facing problems because it doesn't work and I can't understand the cause.

I did the following tests:

  1. Run the code in an Arduino Nano board connected to the GY-521 MPU6050 board. Works fine.
  2. Use other PCB to dismiss possible problem while soldering process. Doesn't work.
  3. Probe with other GY-521 MPU6050 board. Doesn't work.

Finally I decided to cut some parts of the code trying to understand what part of this crash. My final test makes an LED blink while the rest part of the code ran.

void setup() {
  Serial.begin(115200);
  Wire.begin();
#if ARDUINO >= 157
  Wire.setClock(400000UL);
#else
  TWBR = ((F_CPU / 400000UL) - 16) / 2;
#endif

  i2cData[0] = 7; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz
  i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
  i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
  i2cData[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g
  while (i2cWrite(0x19, i2cData, 4, false)); // Write to all four registers at once

  //line commented in the last test
  //while (i2cWrite(0x6B, 0x01, true)); 

  //line commented in the last test
  //while (i2cRead(0x75, i2cData, 1));
  if (i2cData[0] != 0x68) { // Read "WHO_AM_I" register
    Serial.print(F("Error reading sensor"));
    while (1);
  }

  delay(100); // Wait for sensor to stabilize

  //line commented in the last test
  //while (i2cRead(0x3B, i2cData, 6));
  accX = (int16_t)((i2cData[0] << 8) | i2cData[1]);
  accY = (int16_t)((i2cData[2] << 8) | i2cData[3]);
  accZ = (int16_t)((i2cData[4] << 8) | i2cData[5]);


  // It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
  double roll  = atan2(accY, accZ) * RAD_TO_DEG;
  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);

}

void loop() {
  /* Update all the values */
  //line commented in the last test
  //while (i2cRead(0x3B, i2cData, 14));
  accX = (int16_t)((i2cData[0] << 8) | i2cData[1]);
  accY = (int16_t)((i2cData[2] << 8) | i2cData[3]);
  accZ = (int16_t)((i2cData[4] << 8) | i2cData[5]);
  tempRaw = (int16_t)((i2cData[6] << 8) | i2cData[7]);
  gyroX = (int16_t)((i2cData[8] << 8) | i2cData[9]);
  gyroY = (int16_t)((i2cData[10] << 8) | i2cData[11]);
  gyroZ = (int16_t)((i2cData[12] << 8) | i2cData[13]);;

  double dt = (double)(micros() - timer) / 1000000; // Calculate delta time
  timer = micros();

  // It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
  double roll  = atan2(accY, accZ) * RAD_TO_DEG;
  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  double gyroXrate = gyroX / 131.0; // Convert to deg/s
  double gyroYrate = gyroY / 131.0; // Convert to deg/s
  double gyroZrate = gyroZ / 131.0; // Convert to deg/s

#ifdef RESTRICT_PITCH
  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
  if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {
    kalmanX.setAngle(roll);
    compAngleX = roll;
    kalAngleX = roll;
    gyroXangle = roll;
  } else
    kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter

  if (abs(kalAngleX) > 90)
    gyroYrate = -gyroYrate; // Invert rate, so it fits the restriced accelerometer reading
  kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);
#else
  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
  if ((pitch < -90 && kalAngleY > 90) || (pitch > 90 && kalAngleY < -90)) {
    kalmanY.setAngle(pitch);
    compAngleY = pitch;
    kalAngleY = pitch;
    gyroYangle = pitch;
  } else
    kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt); // Calculate the angle using a Kalman filter

  if (abs(kalAngleY) > 90)
    gyroXrate = -gyroXrate; // Invert rate, so it fits the restriced accelerometer reading
  kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter
#endif

  gyroXangle += gyroXrate * dt; // Calculate gyro angle without any filter
  gyroYangle += gyroYrate * dt;
  //  gyroXangle += kalmanX.getRate() * dt; // Calculate gyro angle using the unbiased rate
  //  gyroYangle += kalmanY.getRate() * dt;

  compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll; // Calculate the angle using a Complimentary filter
  compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;

  // Reset the gyro angle when it has drifted too much
  if (gyroXangle < -180 || gyroXangle > 180)
    gyroXangle = kalAngleX;
  if (gyroYangle < -180 || gyroYangle > 180)
    gyroYangle = kalAngleY;

  // leer el valor analogo que entra
  // filtrarlo
  // determinar si se enciende el led
  sensorValue = analogRead(sensorPin);
  filBattery = myFilterBattery.getFilteredValue(sensorValue);
  if (filBattery < 750) // hacer la prueba con este nuevo valor
  {
    digitalWrite(3, HIGH);
  }
  else
  {
    digitalWrite(3, LOW);
  }
  digitalWrite(5, HIGH);
  delay(500);
  digitalWrite(5, LOW);
  delay(500);
}

With this code the LED blinks fine, but the commented lines are critical to MPU6050 setup and operation.

If someone can help me to understand what happen to my PCB, I'll be grateful.

Thanks in advance

migrated from electronics.stackexchange.com Jan 10 '18 at 20:59

This question came from our site for electronics and electrical engineering professionals, students, and enthusiasts.

  • 1
    I've given a short answer, based on the information you've given, which seems to point towards a likely area for you to investigate. However there is lots of information that you haven't given e.g. (a) schematic diagram; (b) PCB layouts for v1 and v2; (c) explanation of why you changed from PCB v1 to v2; (d) details of what changes (if any) you were trying to make between PCB v1 & v2; (e) details of your troubleshooting so far using (e.g.) oscilloscope or logic analyser (a multimeter would only show "gross" mistakes on an I²C bus); (f) details of other suggestions you have already tried. – SamGibson Jan 10 '18 at 4:28
  • 1
    it is also possible that v1 pcb is actually the bad one. some mistake in the design is allowing the code to run. ... i have seen it happen with two pieces of computer equipment. the one that failed to work was actually the good one. – jsotola Jan 10 '18 at 5:24
  • @jsotola - True (+1). I've opted to start with the simple approach (e.g. in the USA, if you hear galloping hooves, first think horses not zebras). The lack of detail & context from the OP, and missing definition of "working" vs. "not working" etc. etc. makes deep analysis inefficient at this stage. Anyway, the comparison between "working" and "not working" as I recommended in my answer, is likely to make progress - even if that progress gives an unexpected result, as you said in your comment - and yes, over decades of troubleshooting, I've seen situations like you describe too :-) Fun! – SamGibson Jan 10 '18 at 5:33
  • 1
    @SamGibson, you are absolutely correct, the difference in the two versions is the key to the solution – jsotola Jan 10 '18 at 6:16
  • 1
    There has been a request to reject the migration from EE.SE. I'm not sure. We need more complete code (where is i2cData declared?). Also we need to see your debugging prints. Saying "not working" doesn't tell us much. – Nick Gammon Jan 10 '18 at 21:53
0

You have explained that PCB v1 works, and PCB v2 does not work. Therefore, it seems likely the problem is in your PCB design and not in the code.

In your code sample which blinks an LED on PCB v2, but does not communicate with the MPU6050, it seems that you have removed the I²C function calls. Therefore if removing those function calls is what allows your code to run, and if the "working" code used on PCB v1 does not run successfully on PCB v2, then it's logical that you have somehow broken your I²C bus on PCB v2.

I suggest you start by comparing your PCB v1 and v2 designs carefully, focussing especially on the I²C bus and the connections to the MPU6050.

  • 1
    Thanks to all people who take time to answer me. I found the error in the PCB v2. SamGibson, you are right, the error was in the I²C: the path was touching the GND plane. I separete this carefully and now works fine. Regards – Orlando Jan 11 '18 at 14:27

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.