A ₹1,440 way to make a cheap robot drive “50 cm, then turn 90 degrees” without encoders. You measure how far it goes per second at one speed and how fast it turns, store those two numbers, and let the sketch convert distances and angles into times. The page also shows, with numbers, why it will always drift and how much.
Scope: beginner. This is a design worksheet with illustrative costs. It has not been bench-tested by this site. The drift table was computed by script. The speed and turn rate in the sketch are examples, not facts about your robot: you must measure your own, and they change with battery charge and floor. Open-loop driving drifts, so treat it as a teaching step before encoders.
How it works
At a fixed PWM a robot moves at a roughly constant speed. If you measure that it covers 100 cm in 3.3 seconds, its speed is about 30 cm/s, and driving 50 cm takes 50 / 30 = 1.67 seconds. Spinning on the spot at the same PWM turns the robot at a roughly constant rate, for example 150 degrees per second, so 90 degrees takes 0.6 second.
Wheels never match exactly. If the right wheel is just 1 percent faster than the left, the robot curves. The two wheel-speed difference over 1 m is 1 cm, spread across a 13 cm wheel base, which turns the robot by 1 / 13 radians, about 4.4 degrees, and leaves it about 3.8 cm to one side by the end of the metre. Calibration can trim this with a small correction factor on one wheel.
Bill of materials
| Part | Qty | Unit | Total |
|---|---|---|---|
| Arduino Uno R3 (or compatible) | 1 | ₹550 | ₹550 |
| L298N motor driver board | 1 | ₹180 | ₹180 |
| 2WD chassis kit with two gear motors and wheels | 1 | ₹450 | ₹450 |
| Battery holder with two 18650 cells | 1 | ₹210 | ₹210 |
| Tape measure and masking tape (for the test course) | 1 | ₹50 | ₹50 |
| Parts total | ₹1,440 | ||
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.
The numbers
| Wheel speed mismatch | Heading error after 1 m | Sideways offset after 1 m |
|---|---|---|
| 0.5% | 2.2° | 1.9 cm |
| 1% | 4.4° | 3.8 cm |
| 2% | 8.8° | 7.7 cm |
| 5% | 22° | 19 cm |
Example move times at 30 cm/s: 25 cm takes 0.83 s, 50 cm takes 1.67 s, 100 cm takes 3.33 s. At 150 degrees per second a 45 degree turn takes 0.3 s and 180 degrees takes 1.2 s. Replace these with your own measurements.
Power and wiring
| Part | Connects to | Note |
|---|---|---|
| L298N ENA / IN1 / IN2 | D5 / D7 / D8 | Left motor |
| L298N ENB / IN3 / IN4 | D6 / D9 / D4 | Right motor |
| Battery | L298N 12V input and Uno VIN | Check your pack voltage against the board limits |
The sketch
// Open-loop drive and turn calibration: Uno + L298N
// Design worksheet: measure CM_PER_S and DEG_PER_S on YOUR robot.
const int L_EN = 5, L_IN1 = 7, L_IN2 = 8;
const int R_EN = 6, R_IN3 = 9, R_IN4 = 4;
void drive(int left, int right) { // -255..255 per side
digitalWrite(L_IN1, left >= 0); digitalWrite(L_IN2, left < 0);
digitalWrite(R_IN3, right >= 0); digitalWrite(R_IN4, right < 0);
analogWrite(L_EN, constrain(abs(left), 0, 255));
analogWrite(R_EN, constrain(abs(right), 0, 255));
}
void motorsInit() {
pinMode(L_EN, OUTPUT); pinMode(L_IN1, OUTPUT); pinMode(L_IN2, OUTPUT);
pinMode(R_EN, OUTPUT); pinMode(R_IN3, OUTPUT); pinMode(R_IN4, OUTPUT);
}
const int DRIVE_PWM = 160;
const int TURN_PWM = 150;
float CM_PER_S = 30.0; // measured: distance covered per second at DRIVE_PWM
float DEG_PER_S = 150.0; // measured: spin rate at TURN_PWM
float RIGHT_TRIM = 1.00; // multiply right wheel PWM to fix a curve (try 0.97 to 1.03)
void driveCm(float cm) {
unsigned long ms = (unsigned long)(fabs(cm) / CM_PER_S * 1000.0);
int dir = cm >= 0 ? 1 : -1;
drive(dir * DRIVE_PWM, dir * (int)(DRIVE_PWM * RIGHT_TRIM));
delay(ms);
drive(0, 0);
delay(300);
}
void turnDeg(float deg) { // positive = clockwise (right)
unsigned long ms = (unsigned long)(fabs(deg) / DEG_PER_S * 1000.0);
int dir = deg >= 0 ? 1 : -1;
drive(dir * TURN_PWM, -dir * TURN_PWM);
delay(ms);
drive(0, 0);
delay(300);
}
void setup() {
motorsInit();
delay(3000); // time to place the robot
for (int i = 0; i < 4; i++) { // 50 cm square
driveCm(50);
turnDeg(90);
}
}
void loop() {}To measure CM_PER_S, drive for exactly 3 seconds on your test course, measure the distance, and divide by 3. To measure DEG_PER_S, spin for 2 seconds, measure the angle with a protractor drawn on the floor, and divide by 2. If the square does not close, change the numbers, not the logic, and repeat until it ends within a few centimetres of where it started. It will not close perfectly. The sketch has been proofread but not compiled on this site.
Test plan
- Straight line: drive 3 seconds along a taped metre line, measure the distance and any sideways drift, and compute CM_PER_S.
- Trim: adjust RIGHT_TRIM until the robot drives straight over the metre.
- Turn rate: spin for 2 seconds with a protractor on the floor, and compute DEG_PER_S.
- Square test: run the 50 cm square on a large sheet and measure how far from the start it ends.
- Repeat: run it five times and note how much the end point varies.
- Battery effect: repeat with a half-discharged pack and compare.
What usually goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| Curves left or right | Wheel speed mismatch | Adjust RIGHT_TRIM |
| Square does not close | Turn angle wrong or drift | Retune DEG_PER_S and the trim |
| Results change from day to day | Battery or floor changes | Recalibrate on each use |
| Different results on carpet | Wheel slip changes | Calibrate on the surface you will use |
| Turns are inconsistent | Static friction at start | Use a short ramp-up and longer turns |
Upgrades
- Encoders: add wheel encoders to measure distance directly.
- Gyro: use an MPU6050 for accurate turns.
- Odometry: track position from encoders, as in the differential-drive worksheet.
- Path list: store a list of moves and run them in sequence.
Cost and parts notes
The ₹1,440 total is an illustration and does not include shipping. Use the cost calculator to compare sellers.
Common questions
Why does the robot never drive exactly straight?
No two motors and wheels are identical, and even a 1 percent difference curves the path.
Why recalibrate when the battery changes?
Speed depends on voltage, so a drained pack makes the robot slower and the timed distances shorter.
Is it good enough for a maze?
For short, forgiving courses, yes. For anything longer, encoders or a gyro are needed.
What is open-loop?
Driving without measuring the result. The robot trusts its timing and never checks where it actually is.
Last reviewed: November 2026. This is a design worksheet with illustrative costs. It has not been bench-tested by this site; library names, pins and limits must be checked against your board and the current library versions, and measurements from your build are welcome.