Motion Control: Master Arduino I2C and the MPU6050 Gyroscope

Motion Control: Master Arduino I2C and the MPU6050 Gyroscope


📑Table of Contents
What You'll Need 4 items
Arduino Uno R3
Buy
MPU6050 Accelerometer/Gyro
Buy
Breadboard
Buy
Jumper Wires
Buy

Affiliate links help support this site at no extra cost to you.

Welcome to Day 24. We successfully built a Radar Station (Day 23) using PWM and Analog inputs. Now, we are leveling up. To build advanced robots—like balancing bots, drones, or gimbal stabilizers—you need better sensors. You need sensors that speak a digital language. You need sensors that can tell you Up from Down.

Today, we master the I2C Protocol and the MPU6050 Accelerometer/Gyroscope. This is the same technology inside your smartphone that detects when you rotate the screen.

Intro: I2C Logic

The Protocol: What is I2C?

Up until now, everyone pin had one job (LED, Button, Servo). But chips are complex. You can’t have 100 pins for 100 features. Engineers invented I2C (Inter-Integrated Circuit) to solve this. It is a Bus. Think of it like a telephone line. You can connect up to 127 devices to the same two wires.

The Two Wires

  1. SDA (Serial Data): The wire where information travels.
  2. SCL (Serial Clock): The wire that sets the rhythm (Heartbeat).

The Arduino is the Master. The Sensors (Gyro, Screen, RTC) are the Slaves. The Master shouts a name (Address), and only that Slave answers.

I2C Bus Architecture

Physics: The “Open Drain” Concept

I2C is unique because the Master never pushes 5V onto the line. It only pulls it to GND (0V) or “Lets go” (Float). This is called Open Drain. To get 5V, we need Pull-Up Resistors (usually 4.7kΩ) connected to VCC.

  • Default State: The resistors pull the line UP to 5V (Logic 1).
  • Active State: The chip pulls the line DOWN to GND (Logic 0).
  • Why? This prevents short circuits. If two chips try to talk at once, one pulls down and the other lets go. No explosion.

Engineering Math: Calculating Pull-Up Resistors

Why do we usually see 4.7kΩ resistors? It’s a balance.

  • Too Weak (10kΩ+): The line rises too slowly. The “Square Wave” looks like a “Shark Fin”. High speed (400kHz) communication fails.
  • Too Strong (1kΩ): The chip has to work too hard to pull the line down to 0V. It wastes power (V=IR).
  • The Sweet Spot: 4.7kΩ allows for crisp edges at 100kHz-400kHz without wasting battery. Note: The Arduino Wire library enables the internal pull-ups, but they are weak (30kΩ). For robust robots, ALWAYS add external 4.7k resistors.

Open Drain Physics Diagram

The Sensor: MPU-6050

This little blue chip is a beast. It contains:

  1. 3-Axis Accelerometer: Measures gravity and force (X, Y, Z).
  2. 3-Axis Gyroscope: Measures rotation speed (Pitch, Roll, Yaw).
  3. Temperature Sensor: Internal thermometer.
  4. DMP (Digital Motion Processor): A tiny brain inside the sensor that does math for you!

Pinout:

  • VCC: 3.3V to 5V (It has a regulator).
  • GND: Ground.
  • SCL: Clock (Connect to A5).
  • SDA: Data (Connect to A4).
  • INT: Interrupt (Optional, tells Arduino “I have data!”).

MPU6050 Pinout Macro

The Wiring

It’s painfully simple. I2C is famous for being easy to wire.

  • VCC -> 5V
  • GND -> GND
  • SDA -> A4 (Uno)
  • SCL -> A5 (Uno)

Note: On Arduino Mega, SDA is pin 20, SCL is pin 21. On Leonardo, they are separate pins.

Wiring Diagram MPU6050

Addressing: Who are you?

Every I2C device has a 7-bit address. The MPU6050 usually lives at 0x68 (Hexadecimal). If you connect the AD0 pin to 5V, it moves to 0x69. This enables you to use TWO gyros on the same robot!

Binary to Hex:

  • Binary: 1101000
  • Hex: 0x68
  • Decimal: 104 (We usually use Hex because it’s shorter).

Address Binary to Hex

The Code: Reading the “Mailboxes” (Registers)

Inside the chip, there are typically 100+ “Registers”. Think of them as numbered lockers or mailboxes.

  • Register 0x3B: Acceleration X (High Byte)
  • Register 0x3C: Acceleration X (Low Byte)
  • Register 0x75: WHO_AM_I (Returns 0x68 so you know it’s alive).

Register Map Visualization

The Basic Sketch (Raw Data)

We don’t need a heavy library to verify it works. Let’s talk directly to the registers.

#include <Wire.h>

const int MPU_ADDR = 0x68; // I2C address of the MPU-6050

int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  
  // Wake up the MPU-6050 (It sleeps by default)
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x6B); // Power Management Register
  Wire.write(0);    // Wake up!
  Wire.endTransmission(true);
}

void loop() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B); // Start reading from register 0x3B (Accel X)
  Wire.endTransmission(false); // Restart connection, don't stop
  
  // Request 14 bytes (Accel X/Y/Z + Temp + Gyro X/Y/Z)
  Wire.requestFrom(MPU_ADDR, 14, true); 
  
  // Read byte-by-byte
  // We combine High Byte (<<8) and Low Byte (|)
  AcX = Wire.read() << 8 | Wire.read(); 
  AcY = Wire.read() << 8 | Wire.read();
  AcZ = Wire.read() << 8 | Wire.read();
  Tmp = Wire.read() << 8 | Wire.read();
  GyX = Wire.read() << 8 | Wire.read();
  GyY = Wire.read() << 8 | Wire.read();
  GyZ = Wire.read() << 8 | Wire.read();
  
  // Print to Serial Plotter
  Serial.print("AccelX:"); Serial.print(AcX);
  Serial.print(",");
  Serial.print("AccelY:"); Serial.print(AcY);
  Serial.print(",");
  Serial.print("AccelZ:"); Serial.println(AcZ);
  
  delay(100);
}

Deep Dive: Bitwise Math for Beginners

Line 35 is terrifying for new coders: AcX = Wire.read() << 8 | Wire.read(); What is happening here?

  1. The Problem: The acceleration value is a 16-bit number (e.g., 10,000). But I2C only sends 8 bits (1 byte) at a time.
  2. The Split: The chip cuts the number in half. Top half (High Byte) and Bottom half (Low Byte).
  3. The Reassembly:
    • Imagine holding two playing cards.
    • Wire.read() gets the first card (High Byte).
    • << 8 (Left Shift) moves it to the “Tens” place. It adds 8 zeros to the right.
    • Wire.read() gets the second card (Low Byte).
    • | (Bitwise OR) combines them. It pastes the Low Byte into those empty zeros. This is arguably the most common line of code in embedded engineering. Memorize it.

Physics: Accelerometer vs Gyroscope - What’s the difference?

They sound similar, but they measure totally different things.

  • Accelerometer (The Joulemeter): Measures Force.
    • If you sit still, it measures 1G (Gravity) pointing down.
    • If you accelerate a car, it measures the force pushing you back in the seat.
    • Problem: It is VERY noisy. Every vibration shakes the data.
  • Gyroscope (The Spinner): Measures Rotation Speed (Degrees per Second).
    • If you sit still, it measures 0.
    • If you spin the board, it measures 300 deg/sec.
    • Problem: It Drifts. If you integrate the speed to find the angle, small errors add up. After 1 minute, it might think “Down” is “Left”.

The Fix: Sensor Fusion (Complementary Filter)

To build a drone, you combine them.

  • Trust the Gyro for fast moves.
  • Trust the Accelerometer for long-term stability (Gravity always points down).
  • Angle = 0.96 * (Gyro_Angle) + 0.04 * (Accel_Angle); This one line of math is the secret sauce behind every Segway and Quadcopter.

Understanding 2’s Complement

You typically get values ranging from -17000 to +17000. Why negative? The chip uses Signed Integers (2’s Complement). If you tilt it Left, X is positive. Tilt Right, X is negative.

  • At rest flat on a table:
    • X = 0
    • Y = 0
    • Z = 16384 (This is Gravity! 1G).

Project: The Digital Spirit Level

Let’s make this useful. We will use 4 LEDs (Up, Down, Left, Right) to show tilt.

  1. Connect LEDs to Pins 8, 9, 10, 11.
  2. If AcX > 5000, light up RIGHT LED.
  3. If AcX < -5000, light up LEFT LED.
  4. If AcY > 5000, light up UP LED.
  5. If AcY < -5000, light up DOWN LED.

This is the exact same logic used in:

  • Game Controllers (Wiimote).
  • Drone Flight Controllers (Self-leveling).
  • VR Headsets.

The Logic Code

// Simple Threshold Logic
if (AcX > 4000) {
  digitalWrite(RIGHT_LED, HIGH);
} else {
  digitalWrite(RIGHT_LED, LOW);
}

if (AcX < -4000) {
  digitalWrite(LEFT_LED, HIGH);
} else {
  digitalWrite(LEFT_LED, LOW);
}
// Repeat for Y axis...

This is the exact same logic used in:

  • Game Controllers (Wiimote).
  • Drone Flight Controllers (Self-leveling).
  • VR Headsets.

Digital Spirit Level Project

Advanced: Hacking the Registers (Sensitivity)

By default, the MPU6050 measures up to ±2G (Gravity). But what if you strap it to a rocket? 2G is nothing. We can hack Register 0x1C (ACCEL_CONFIG) to change the sensitivity.

  • 0x00: ±2G (Default, most sensitive).
  • 0x08: ±4G.
  • 0x10: ±8G.
  • 0x18: ±16G (Least sensitive, but highest range).
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x1C); // Access Accel Config
Wire.write(0x18); // Set to ±16G
Wire.endTransmission(true);

If you do this, your raw math changes. Instead of dividing by 16384 for 1G, you divide by 2048. Engineering is about trade-offs: Range vs Precision.

Pro Tip: Using the INT Pin (Interrupts)

Polling the sensor in loop() is slow. The MPU6050 has a “Data Ready” interrupt pin.

  1. Connect INT to Arduino Pin 2.
  2. Use attachInterrupt(digitalPinToInterrupt(2), readData, RISING);
  3. The Arduino can sleep or do other math until the MPU wakes it up saying “I have new numbers!”. This is how phones save battery while tracking steps in the background.

History: From Apollo to iPhone

The MPU6050 is a marvel of MEMS (Micro-Electro-Mechanical Systems). In the 1960s, the gyroscope for the Apollo moon mission was the size of a bucket and cost millions. It used spinning metal wheels. Today, we etch microscopic silicon “tuning forks” onto a chip for $3. When you rotate the chip, the vibration of these forks changes due to the Coriolis Effect. We measure that change as capacitance. It is literally a machine running inside a piece of silicon.

Advanced Math: The Kalman Filter

I mentioned the “Complementary Filter” (Easy math). If you want to work at NASA or SpaceX, you use a Kalman Filter. This is a complex algorithm that:

  1. Predicts the future state of the system based on physics.
  2. Reads the noisy sensor data.
  3. Compares the two and guesses the true probability of the angle. It is computationally heavy for an Uno, but libraries like Kalman.h exist if you want absolute perfection.

Troubleshooting I2C

  1. System Hangs: The Wire.requestFrom never returns.
    • Cause: Loose wire. If SDA/SCL disconnects, the Arduino waits forever.
    • Fix: Check connections. Use generic “I2C Scanner” code to verify address.
  2. Values are erratic/noisy:
    • Cause: Electrical noise or Motor vibration.
    • Fix: Use a “Complementary Filter” (Math) or just average 10 readings.
  3. Address not found:
    • Cause: AD0 pin is floating? Connect AD0 to GND for 0x68.

Oscilloscope Waveform SDA SCL

Serial Plotter Fun

Open the Serial Plotter (Ctrl+Shift+L). Shake the board. You will see the waves react instantly. Try to tap the table—you will see a sharp spike (Impact detection). This is how your phone counts your steps (Pedometer)!

Serial Plotter Earthquake Data

The Engineer’s Glossary (Day 24)

  • I2C (Inter-Integrated Circuit): A 2-wire serial protocol for connecting low-speed peripherals.
  • Open Drain: An output type that can only pull voltage down to ground, requiring an external resistor to pull it up.
  • Register: A storage location inside a chip that controls configuration or holds data.
  • MSB / LSB: Most Significant Byte (Big end) and Least Significant Byte (Little end).
  • IMU (Inertial Measurement Unit): A device combining accelerometers and gyroscopes.
  • DMP (Digital Motion Processor): A proprietary engine inside InvenSense chips that calculates Quaternion angles (Euler X/Y/Z) without the Arduino helping.

Conclusion

You now speak specific dialect of “Chip Connect”. I2C is the industry standard for on-board communication. Because you know I2C, you can now use:

  • OLED Screens (Day 20)
  • RTC Modules (Day 19)
  • Pressure Sensors (BMP180)
  • Light Sensors (BH1750)
  • Output Expanders (PCF8574)

You are no longer limited by the pins on your Uno. You can chain 100 sensors together.

Next Up: We have inputs. We have outputs. We have protocols. Tomorrow, we learn Logic State. We will build a machine that remembers where it is in a sequence. See you on Day 25.

Comments