MPU6050 Programming with delays

Hey all, I’m brand new here and I thought I would see if any of you guys can shed any light on this subject.

I hope I have posted in the correct place, if not please do let me know.

I am working on an object avoidance robot with an ultrasonic sensor for distance measurements and an inertial measurement unit to determine the orientation of the robot.

Basically I have tried a number of different MPU6050 libraries and quite a few examples as well as watching a number of tutorial videos on YouTube but I still don’t really understand what is going on.

As far as I understand it, reading data from the MPU6050 and translating that into angles etc. is dependant on the time it takes for the loop to run. If I add a delay to the loop, the readings are affected and with a 1 second delay, they are so far off its as if it’s not moving anymore.

My questions is, why does the time it takes for a loop to complete effect the data produced by the MPU6050?

I can add my code if needed but this is a pretty broad question and I’m not sure it matter what code you use (at least as far as I can tell).

What readings are affected?

Consider that the gyros in a mpu6050 are rate gyros that show the rate of change of angular displacement. If the angular displacement is 2 degrees per second the mpu6050 will show you the rate of change but once the change has become steady there is no rate of change and nothing to report. Is one thing that is time dependent in reading those thingies.

Another thingy about time is that many mmu filters integrate time into their calculations.

OK that is starting to make more sense, because it seems to be the angle it is reading (in this case yaw) that becomes inaccurate. There is a time based calculation in the loop which understandable will effect the numbers if there is a delay added. I just wasn't sure what the need for the time based calculation.

Thank you, I guess I will have to get creative with my code and use loop counters instead of delays?

The MPU-6050 can't measure yaw, because it does not have a magnetometer.

It can only estimate a yaw angle relative to the starting orientation, and that will always drift, because the gyro offset is not constant.

Yes I found that out the hard way. I will eventually need pitch and roll info too and have a magnetometer on the way but for now, it will do to estimate rotation travelled for very short periods of time.

Right now I am only using it to determine roughly how far the robot has rotated and the yaw is set to 0 at the start of each rotation. It’s as close as I need it for the time being and is better than just telling the wheels to move for a period of time.

I tried doing something like this for some haptic gloves a while back, and you seem to have reached the same conclusion as me: MPU6050's can't reliable get rotation, but checking the direction of gravity and measuring acceleration works fine. I assume you mounted your MPU close or on the outside edge of your bot, so that you can get larger readings for tangential acceleration. The simple answer to the problem would be that with delays between reads, the environment can change without the sensor knowing. It's measuring angular displacement, not distance. Think of it as measuring the distance something has moved from a spot, initially it's 0 meters, but 10 seconds later it's still 0 meters away. There's no way to know if the object moved or not during those 10 seconds, if it remained at rest, or if it moved around and returned to the starting position. Your sensor code should be reading decently fast, but errors would still compound over time. Resetting the count is good, it should keep such errors from building too fast, and I would suggest using millis() for delays instead of loop counters, since lag could be generated by math or other functions in your code. Good luck with your project!

Thanks KingDubDub, that does make sense. Yes I have the MPU6050 mounted as central as possible to get the most accurate rotation possible. I do have a millis() delay in the code but this is for the calculation of the rotational output from the IMU.

What I would like to do is, for example, rotate a servo to a position, the servo is holding the ultrasonic sensor. This then reads the distance, and then moves to another position to continue checking distances.

The problem is that it takes time for the servo to reach its position and time for the ultrasonic sensor to send and receive an accurate ping.

Here is some old code I was using before I started playing with the IMU:

for (int i = 0; i <= 180; i = i + 45) // quicker to check less directions
{
  yawServo.write(i);
  delay(350); //wait for the servo to reach the position
  
  avgPing = 0;
  for (int d = 0; d < 2; d++)
  {
    //take three readings from the sensor
    avgPing += sonar.ping_cm();
  }
  avgPing /= 3;
  //choose the best distance
  if (avgPing > bestDistance)
  {
    //update the best direction distance and angle
    bestDistance = avgPing;
    pathAngle = i;
  }
}

So I know that’s a bit more complicated to achieve now because I can’t use the delays in this way.

Is it bad practice to use a second Arduino to read the MPU6050? Maybe I could use one for controlling the robot and just poll the second arduino for readings when they are needed? Is that even possible?

whiskylima:
Is it bad practice to use a second Arduino to read the MPU6050? Maybe I could use one for controlling the robot and just poll the second arduino for readings when they are needed? Is that even possible?

That’s a great idea, a little difficult if you don’t have a spare arduino, but definitely possible. You can send serial data from arduino to arduino, so one can drive your robot and the other can constantly run the acceleration checks, along with anything else that needs constant updates. You can also use I2C to communicate by making your reader a slave that reports to your master arduino.

I am torn between adding an arduino nano to the project and a magnetometer and using the nano to communicate all the readings across. The alternative is to wuss out altogether and just use the magnetometer. The pitch and roll values are far less important than the yaw but it would be nice to know if there is movement or if it has stopped..

I will have to give it some thought

A magnetometer has a constant reference point due to the earth's magnetic field, so just that and a nano would be good for your bot. You could keep the MPU if you wanted to check the tilt of your rover or acceleration. Do keep in mind that checking the acceleration only works when you are accelerating, which is a measurement in the change of speed. You'll get the same acceleration values (0 m/s^2) if your bot isn't moving or if it's going at a constant 100000 km/s. You'll still be able to check rotational acceleration, since rotating means you're changing your speed by changing the direction you are moving around a point. If you still need super-accurate tilt measurements, stick to using another nano for datalogging.

So I think I will settle for using the magnetometer for now and see if I have a use for the IMU at a later stage once this is working. I have my basic code setup for the magnetometer and it would seem it is a QMC5883L (not a HMC5883L as advertised) and after looking for some code to test it I found the MechaQMC5883 library. It looks like the two chips have different locations for the x y and z information from what I understand from the datasheet.

Anyway this will be accurate enough for what I need it to do for now, if I can get it working. So far it spits out some numbers which appear to change based on the position but it doesn't seem at all accurate at the moment. I'm guessing there must be some calibration I need to go through?

Anyway a little more playing around and once I have this reporting a vaguely accurate yaw reading I can move onto the fun stuff :)

EDIT:

I have just tried another library by gcmike and it's giving similar results. My heading in degrees always seems to be somewhere between 120 and 130 and doesn't change.. is it interference? I think I will remove the mounting bolt, probably a good start hu?

Hey guys, so I have been surfing around for assistance with the magnetometer. I am trying to calibrate it to get more accurate results. I removed the bolt I was using and that went a long way to getting good results but it's still way off.

Do you guys know of a good calibration method I can use in Arduino. I have found a couple of methods but I don't really understand how to implement them. Here is one such example:

http://sailboatinstruments.blogspot.com/2011/08/improved-magnetometer-calibration.html

I amusing the breakout board with the QMC5883L magnetometer.

Any help or advise would as always be appreciated