JM9 XRCU Tutorials 0.0.1a
Learn how to program XRCU
Loading...
Searching...
No Matches
Gyroscope: MPU-6050

A gyroscope (or "gyro" for short) is a sensor that knows how it is turning. With a gyro, a robot knows which way it is facing, even when it cannot see anything. Your phone has one too: that is how it knows when you turn it sideways!

In this chapter, we will use the MPU-6050 with XRCU. The MPU-6050 is a small chip with 2 sensors inside:

  • a gyroscope, which measures how fast it is turning,
  • an accelerometer, which measures which way is down (gravity).

It also has a tiny computer inside, which mixes the 2 sensors together and works out the angles for us.

Yaw, Pitch and Roll

We use 3 angles to describe which way something is facing. Imagine you are sitting in an aeroplane:

Angle The plane... Example on a robot
Yaw turns left or right the robot turns on the floor
Pitch points its nose up or down the robot drives up a ramp
Roll tips one wing up and the other down one wheel of the robot drives over a bump

Robots on the floor mostly care about yaw, because yaw tells the robot which way it is facing.

Wiring to a T Port

The MPU-6050 talks to XRCU using I2C (say "I-squared-C"). I2C is a way for chips to talk to each other using only 2 wires:

  • SCL (Serial Clock) carries a steady beat, like a drummer.
  • SDA (Serial Data) carries the data, in time with the beat.

On XRCU, the I2C ports are the T ports: T1 and T2.

Most MPU-6050 modules have 8 pins: VCC, GND, SCL, SDA, XDA, XCL, AD0 and INT. We only need the first 4. Use 4 jumper wires to connect the module to port T1:

MPU-6050 pin Connect to XRCU
VCC 3V3
GND GND
SCL T1A
SDA T1B

Leave XDA, XCL, AD0 and INT unconnected.

Warning
Always turn OFF XRCU before you connect or disconnect a sensor. SCL must go to the A pin, and SDA must go to the B pin. If you swap them, XRCU cannot find the sensor.

The gyro measures the turning of the module, not of XRCU. So the module must not wobble on its wires. Stick the module onto a book or a piece of cardboard with some tape, with the chip facing up. Then you can turn the book to turn the gyro. On a real robot, the module is screwed flat onto the robot.

Is the Gyro There?

First, include the Mpu_6050_dmp library at the top of your program:

#include <Mpu_6050_dmp.h>

(dmp is short for Digital Motion Processor: the tiny computer inside the MPU-6050 that works out the angles for us.)

Next, we create a gyro in our code, and tell it which port it uses:

Mpu_6050_dmp gyro(T1);

This line means: "make a new Mpu_6050_dmp gyro called gyro, on port T1". Just like Uts_gpio in the Ultrasonic Sensors chapter, write it above setup(), so that both setup() and loop() can use it.

Before we use the gyro, let's check that XRCU can find it. gyro.is_gyro_present() gives true if XRCU can talk to the gyro, and false if it cannot.

#include <Mpu_6050_dmp.h>
// Make a gyro called gyro, on port T1.
Mpu_6050_dmp gyro(T1);
void setup() {
Serial.begin(9600);
}
void loop() {
// Ask: can XRCU talk to the gyro?
if (gyro.is_gyro_present()) {
Serial.println("Gyro detected!");
} else {
Serial.println("Gyro not present! Check the wires!");
}
delay(500);
}

Checkpoint 9.1

Turn OFF XRCU. Connect your MPU-6050 to port T1 as shown above. Turn ON XRCU, then upload the code above and run it. Open the serial monitor. Do you see Gyro detected!?

Next, turn OFF XRCU and swap the SCL and SDA wires. Turn ON XRCU again. What does the serial monitor show now? Finally, turn OFF XRCU and connect the wires correctly again.

Record a video showing the wires and the serial monitor, for both the correct and the swapped wiring. Submit this video to your assignment portal at checkpoint 9.1.

Calibration

Every MPU-6050 is a little bit different. Even when it is perfectly still, it may think it is turning a tiny bit, or that it is tilted a tiny bit. These tiny errors add up very quickly, so yaw, pitch and roll all slowly move away from the true angles. This is called drift.

To fix this, we must calibrate the gyro before we read any angles. You have seen calibration before in the Analog Inputs chapter. During gyro calibration, XRCU measures the small errors of your gyro while it is perfectly still, so it can cancel them out later.

First, we start the gyro with begin() inside setup(). Then there are 2 functions for calibration:

Code What it does
gyro.cal() Measure the errors of the gyro. The gyro must be flat and still!
gyro.save_caled_vals() Save the calibration inside XRCU. (caled is short for "calibrated".)

After you save the calibration, gyro.begin() loads it automatically every time your program starts, even after you turn XRCU OFF. So you only need to calibrate once.

Warning
During calibration, the gyro must be flat on a table, with the chip facing up, and nobody may touch it or the table. If the gyro moves during calibration, the calibration will be wrong.

Here is a program that uses SW1 to start the calibration:

#include <Mpu_6050_dmp.h>
#include <Buttons.h>
// Make a gyro called gyro, on port T1.
Mpu_6050_dmp gyro(T1);
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
// Start the gyro.
gyro.begin();
// Step 1: Put the gyro flat on the table, then click SW1.
// This while loop waits until SW1 is clicked.
while (!button1.isClicked()) {}
// Step 2: Take your hands away. Wait 2 seconds, so nothing is shaking.
delay(2000);
// Step 3: Measure the errors. The LED is ON during calibration.
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("Calibrating... Do not touch!");
gyro.cal();
// Step 4: Save the calibration inside XRCU.
gyro.save_caled_vals();
digitalWrite(LED_BUILTIN, LOW);
Serial.println("Done!");
}
void loop() {
// Nothing to do here.
}

During calibration, you may see some strange symbols in the serial monitor, like >.....>...... These come from the library, and show that the calibration is working.

Note
The calibration is saved inside XRCU, not inside the MPU-6050. If you change to another MPU-6050 module, or another XRCU, you need to calibrate again.

Checkpoint 9.2

Upload the calibration program above and run it.

  1. Put the gyro flat on the table, with the chip facing up.
  2. Click SW1, then take your hands away. Do not touch the table!
  3. Wait until the LED turns OFF and the serial monitor shows Done!.

How long does the calibration take? Why do you think the program waits 2 seconds after you click SW1?

Record a video showing the gyro, the LED and the serial monitor during calibration. Submit this video to your assignment portal at checkpoint 9.2.

Reading the Angles

Now that the gyro is calibrated, we can read the 3 angles in degrees:

Code What it gives
gyro.get_yaw() Yaw, from 0 to 359.99 degrees.
gyro.get_pitch() Pitch, 0 when the module is flat.
gyro.get_roll() Roll, 0 when the module is flat.

The angles are numbers with decimal places, like 90.25. So we keep them in float variables.

This program has no calibration code. gyro.begin() loads the calibration you saved in checkpoint 9.2.

#include <Mpu_6050_dmp.h>
// Make a gyro called gyro, on port T1.
Mpu_6050_dmp gyro(T1);
void setup() {
Serial.begin(9600);
// Start the gyro. This also loads the saved calibration.
gyro.begin();
}
void loop() {
// Read the 3 angles in degrees.
float yaw = gyro.get_yaw();
float pitch = gyro.get_pitch();
float roll = gyro.get_roll();
// Print all 3 angles on the same line.
Serial.print("yaw: ");
Serial.print(yaw);
Serial.print(" pitch: ");
Serial.print(pitch);
Serial.print(" roll: ");
Serial.println(roll);
delay(100);
}
Warning
Do not forget gyro.begin(); in setup(). Without it, the angles always stay at 0.

Keep the gyro still for a few seconds after you turn ON XRCU. The gyro needs this short time to settle down.

When the program starts, the yaw is about 0. So yaw does not tell you where north is. It tells you how far the gyro has turned since it started.

With the chip facing up, look down at the gyro from above:

  • Turn it clockwise (to the right), and the yaw goes up: 1, 2, 3 ... 90 ...
  • Turn it anticlockwise (to the left), and the yaw goes down: 0, then 359, 358, 357 ... 270 ...

Yaw is just like a compass: after 359.99 degrees, it goes back to 0.

Checkpoint 9.3

Upload the code above and run it. Open the serial monitor with timestamps.

  1. Keep the gyro flat, and turn it by a quarter turn (90 degrees) to the right. Then turn it back, and turn it a quarter turn to the left. What yaw do you see each time?
  2. Tilt the gyro forwards and backwards, then left and right. Which angle changes each time: pitch or roll? Which way makes each one positive?
  3. Put the gyro flat on the table, and do not touch it for 1 minute. Use the timestamps to find 1 minute. How much do yaw, pitch and roll change during this minute?

Record a video showing the gyro and the serial monitor during steps 1 and 2. Then take a screenshot of the serial monitor at the start and at the end of step 3. Submit the video and both screenshots to your assignment portal at checkpoint 9.3.

Setting a New Zero

When a robot starts a game, it is usually facing the right way. So we want the yaw to be 0 when the robot faces forwards.

gyro.reset_heading() makes the way the gyro is facing now the new zero. (Heading means the way you are facing.) After that, get_yaw() measures from this new zero.

// Make the way we face now the new zero.
gyro.reset_heading();

Checkpoint 9.4

Change your program from checkpoint 9.3, so that:

  1. Clicking SW1 makes the way the gyro faces now the new zero.
  2. LED_BUILTIN is ON when the gyro faces less than 10 degrees away from the zero, to the left or to the right. Otherwise, the LED is OFF.

(Hint: 10 degrees to the right is a yaw of 10. What is the yaw when the gyro faces 10 degrees to the left? In an if, || means "or".)

Upload and run it. Turn the gyro a little bit, then click SW1. Is the LED ON? Now turn the gyro slowly to the left and to the right. When does the LED turn OFF?

Record a video showing the gyro, the LED and the serial monitor. Submit this video to your assignment portal at checkpoint 9.4.

Which Way to Turn?

Imagine your robot should face its zero, but it now has a yaw of 350. Should it turn left or right?

350 degrees to the right is the same as 10 degrees to the left. Turning 10 degrees is much quicker than turning 350 degrees! So it is easier to think of the yaw as a number from -180 to 180:

  • positive means the robot is facing to the right of zero,
  • negative means the robot is facing to the left of zero.

To change the yaw from "0 to 359.99" into "-180 to 180", we subtract 360 when the yaw is bigger than 180:

float error = gyro.get_yaw();
// Change 0 to 359.99 into -180 to 180.
if (error > 180) {
error = error - 360;
}

For example, a yaw of 350 becomes 350 - 360 = -10, which means "10 degrees to the left". We call this number the error: how far we are from where we want to face.

get_yaw() error Meaning
0 0 Facing zero.
30 30 30 degrees to the right. Turn left!
180 180 Facing backwards.
270 -90 90 degrees to the left. Turn right!
350 -10 10 degrees to the left. Turn right!

Checkpoint 9.5

Write a program that clicks SW1 to set a new zero (like checkpoint 9.4), and prints:

  1. Turn left when the error is bigger than 5.
  2. Turn right when the error is smaller than -5.
  3. Straight at all other times.

Print the error on the same line too.

Upload and run it. Click SW1, then turn the gyro to the left and to the right. Does it always tell you the shorter way back to zero? What happens when the gyro faces exactly backwards?

Record a video showing the gyro and the serial monitor. Submit this video to your assignment portal at checkpoint 9.5.

Summary

Code What it does
#include <Mpu_6050_dmp.h> Lets us use Mpu_6050_dmp.
Mpu_6050_dmp gyro(T1); Makes a gyro called gyro on port T1. Write it above setup().
gyro.is_gyro_present() true if XRCU can talk to the gyro, false if not.
gyro.begin() Starts the gyro, with the saved calibration. Call it in setup().
gyro.get_yaw() Yaw in degrees, from 0 to 359.99. Turning right makes it go up.
gyro.get_pitch() Pitch in degrees, 0 when flat.
gyro.get_roll() Roll in degrees, 0 when flat.
gyro.reset_heading() Makes the way the gyro faces now the new zero yaw.
gyro.cal() Measures the errors of the gyro. Keep it flat and still!
gyro.save_caled_vals() Saves the calibration inside XRCU.

Remember:

  • Connect SCL to the A pin and SDA to the B pin of a T port.
  • Fix the module flat, with the chip facing up.
  • Calibrate once on a still table before you read any angles. Without calibration, all 3 angles drift away quickly.
  • To decide which way to turn, change the yaw into an error from -180 to 180.