A ₹1,500 robot that turns 90 degrees using a gyroscope instead of a timer. An MPU6050 module reports how fast the robot is rotating. The Arduino adds that up over time to get the turned angle, and stops the motors when the target is reached. The robot drives a square: forward for a set time, turn 90 degrees, repeat. The page includes the wiring, a complete sketch that reads the sensor directly over I2C, a drift calibration step, and a test plan that measures turn error.
Scope: intermediate. This is a design worksheet with illustrative costs. It has not been bench-tested by this site, and the register addresses and scale factor in the sketch should be checked against the MPU6050 register map and your module before you rely on the turns. A timed turn depends on the battery and the floor; a gyro turn depends on neither, which is the lesson of the build.
Why a timer is not enough
A turn of 450 ms at a fixed PWM value turns by a different angle when the battery is full, when it is half empty and when the floor changes. The gyroscope measures turn rate directly. At the sensitivity setting used here the module reports 131 counts for each degree per second, so dividing a reading by 131 gives degrees per second, and multiplying by the time step and adding it up gives degrees turned. The weakness is drift: a small constant error in the reading grows into an angle error over time, so the sketch measures that offset at start-up and removes it.
Bill of materials
| Part | Qty | Unit | Total |
|---|---|---|---|
| Arduino Uno R3 | 1 | ₹520 | ₹520 |
| L298N motor driver | 1 | ₹180 | ₹180 |
| MPU6050 module | 1 | ₹180 | ₹180 |
| TT gear motor with wheel | 2 | ₹110 | ₹220 |
| Acrylic chassis | 1 | ₹80 | ₹80 |
| 2×18650 holder with cells | 1 | ₹200 | ₹200 |
| Caster wheel and screws | 1 | ₹40 | ₹40 |
| Jumper wire set | 1 | ₹50 | ₹50 |
| Switch | 1 | ₹30 | ₹30 |
| Parts total | ₹1,500 | ||
Scroll the table sideways to see every column.
Prices checked Nov 2026. Shipping and tools are not included.
Prices are illustrative figures for Indian sellers in November 2026, before shipping, and have not been checked against current listings.
Pin map
| Part | Arduino Uno | Note |
|---|---|---|
| MPU6050 VCC / GND | 5V / GND | Most breakout boards have a regulator; check yours |
| MPU6050 SDA / SCL | A4 / A5 | I2C; the default address is 0x68 |
| L298N IN1 / IN2 | D5 / D6 | Left motor direction |
| L298N IN3 / IN4 | D12 / D13 | Right motor direction |
| L298N ENA / ENB | D3 / D11 | PWM speed. Remove the onboard jumpers. |
| L298N +5V | 5V pin | Powers the Uno from the driver’s regulator |
| All grounds | Common GND | Battery, L298N, Uno and MPU6050 |
The sketch
// Gyro-assisted 90 degree turns: Uno + L298N + MPU6050 (raw I2C, no library)
// Design worksheet: verify register addresses against the MPU6050 register map.
#include <Wire.h>
const int MPU_ADDR = 0x68;
const int IN1 = 5;
const int IN2 = 6;
const int IN3 = 12;
const int IN4 = 13;
const int ENA = 3;
const int ENB = 11;
const int SPEED = 130;
const int TURN_SPEED = 120;
const unsigned long LEG_MS = 1500;
const float GYRO_SCALE = 131.0; // counts per degree per second at the +/-250 setting
float gyroOffset = 0;
void setup() {
Serial.begin(115200);
Wire.begin();
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B); // power management: clear sleep bit
Wire.write(0);
Wire.endTransmission(true);
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x1B); // gyro config: +/-250 degrees per second
Wire.write(0);
Wire.endTransmission(true);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);
stopMotors();
delay(2000); // keep the robot still while this runs
gyroOffset = measureOffset();
Serial.print("offset=");
Serial.println(gyroOffset);
delay(1000);
}
void loop() {
forward();
delay(LEG_MS);
stopMotors();
delay(300);
turnByDegrees(90);
delay(500);
}
float readGyroZ() {
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x47); // GYRO_ZOUT_H
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 2, true);
int high = Wire.read(); // read the two bytes in a fixed order
int low = Wire.read();
int16_t raw = (high << 8) | low;
return raw;
}
float measureOffset() {
float sum = 0;
for (int i = 0; i < 500; i++) {
sum += readGyroZ();
delay(3);
}
return sum / 500.0;
}
void turnByDegrees(float target) {
float angle = 0;
unsigned long last = micros();
turnLeft();
while (fabs(angle) < target) {
unsigned long now = micros();
float dt = (now - last) / 1000000.0;
last = now;
float rate = (readGyroZ() - gyroOffset) / GYRO_SCALE; // degrees per second
angle += rate * dt;
}
stopMotors();
}
void forward() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, SPEED);
analogWrite(ENB, SPEED);
}
void turnLeft() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, TURN_SPEED);
analogWrite(ENB, TURN_SPEED);
}
void stopMotors() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
analogWrite(ENA, 0);
analogWrite(ENB, 0);
}The sketch compares the absolute angle with the target, so it works whichever way the gyro axis is signed. It has no timeout: if the sensor stops responding, the robot would keep turning. Add a time limit before you trust it near anything fragile. The robot keeps turning for a short moment after the motors are cut, so expect the real angle to overshoot slightly; measure it and stop a few degrees early.
Calibrate and check
- Offset: with the robot still, read the printed offset after power-up. Repeat three times. The values should agree closely; large changes mean the board is moving or loose.
- Drift test: leave the robot still for a minute with the angle running and note how far it creeps. This sets how long you can go between corrections.
- Scale check: turn the robot by hand through a marked 90 degrees and compare it with the sketch. A consistent ratio gives a corrected scale factor.
Test plan
- I2C: run an I2C scanner and confirm the module appears at 0x68. See I2C device not found if not.
- Motor direction: check the turn direction with the wheels off the ground.
- Single turns: mark the floor and measure ten 90 degree turns with a protractor. Record the mean and the spread.
- Battery: repeat with a fresh and a half-empty pack. The gyro turn should be less sensitive to the pack than a timed turn.
- Square: run four legs and four turns. Measure how far the robot ends from where it started.
- Floor: repeat on a rug or tiles; wheel slip changes the distance but should not change the turn angle much.
What usually goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| Offset changes a lot between runs | Robot moved during calibration, or loose sensor | Keep it still, fix the board firmly |
| Turn never ends | Sensor not responding, or axis wrong | Check wiring and axis; add a timeout |
| Turns about 80 or 100 degrees | Overshoot after cut-off, or a wrong scale factor | Stop a few degrees early and check the scale |
| Angle creeps while stopped | Gyro drift | Re-measure the offset more often, or fuse with another sensor |
| Readings jump when motors run | Vibration or supply noise | Mount the board on foam, use short wires, add a capacitor |
| Square does not close | Leg lengths vary with battery | Use encoders for the legs, as in the straight-line build |
Upgrades
- Heading hold: use the angle to drive straight by correcting any drift away from zero.
- Encoders: pair the gyro with wheel encoders for accurate square paths.
- Slow-down near the target: reduce turn speed in the last 15 degrees to cut overshoot.
- Library: move to a maintained MPU6050 library with calibration helpers once you understand the raw reads.
Cost and parts notes
The ₹1,500 total is an illustration for the parts above and does not include shipping. The L298N guide explains the voltage drop that makes a 7.4 V pack behave like a 5.8 V one at the motors. Use the cost calculator to compare sellers.
Common questions
Why does the gyro drift?
Every gyroscope has a small bias that changes with temperature and time. Adding up the readings turns that small bias into a growing angle error, so you measure and subtract it, and keep runs short.
Do I need the accelerometer for a turn?
No. A turn about the vertical axis uses only the Z gyro. The accelerometer matters for tilt and balancing.
Can I get a 360 degree heading from this?
Only a drifting one. For a lasting heading you need a magnetometer or other reference to correct the drift.
Why read the registers directly?
It keeps the sketch free of third-party code and shows what the sensor does. A library is a fine choice once you know what it is doing.
Last reviewed: November 2026. This is a design worksheet with illustrative costs. It has not been bench-tested by this site; register addresses and scale factors must be checked against the MPU6050 register map, and measurements from your build are welcome.