30% off your first 3 months

Get the deal

Fixing a robot that won't drive straight

by DuckyHelperNov 12, 20264 min read
Robotics

TL;DR:

  • Two identical motors are never identical. A small speed difference becomes a steady curve.

  • Measure first. Drive a known distance, record how far off to the side the robot ends up, and compute how big the difference is.

  • Fix the mechanics, then add feedback: compare wheel encoder counts and adjust the motor power to cancel the error.

You send both motors the same command and the robot drifts left anyway. This is the most common first problem in wheeled robotics, and it is not a sign that you built something wrong. It is the first time the real world disagrees with your code. The way through is to measure the problem before guessing at fixes.

Measure the veer

Mark a start line on the floor and a straight line 2 m ahead of it using a tape measure. Run the robot along it three times and measure how far off the line it ends, sideways. Write the numbers down. If the three are close, the cause is steady, like motors or wheels. If they scatter, think about slipping, loose parts or a battery that sags.

Worked example: how much faster is one wheel?

Say the robot drives 2.0 m and ends 0.15 m to the left of the line. It follows a gentle circle arc, and for a small sideways drift the geometry is y ≈ s² ÷ (2R), where s is the distance driven and R is the radius of the arc.

  1. Solve for the radius: R = s² ÷ (2y) = 4.0 ÷ 0.30 ≈ 13.3 m.

  2. Heading change over the run: s ÷ R = 2.0 ÷ 13.3 = 0.15 rad, about 8.6°.

  3. Wheelbase L = 0.20 m. For a differential drive, 1/R = (vR − vL) ÷ (L × v) where v is the average speed, so (vR − vL) ÷ v = L ÷ R = 0.20 ÷ 13.3 = 0.015.

  4. So the right wheel is faster by about 0.015 of the average speed: vR ÷ vL ≈ 1.015.

Check by running it forward: y = s² ÷ (2R) = 4.0 ÷ 26.7 = 0.15 m. That matches. The finding is useful: a left veer means the right wheel is running a little faster, and the difference is only about one and a half parts in a hundred. Small, but over a few meters it is plenty to miss a doorway.

Check the mechanics first

Before you change code, look for physical causes. Many of them are cheap to find.

  • Wheels. Different diameter tires, a wobbling wheel, or one wheel rubbing the body.

  • Caster or ball. A stiff or sticky front caster pulls the robot to one side.

  • Weight. A heavy battery on one side loads one wheel more.

  • Axle and gears. One gearbox with more friction than the other.

  • Wires. A cable dragging on one wheel.

Swap the two motors from one side to the other. If the veer flips direction, the motors are the cause. If it stays, the cause is in the chassis, the wheels or the floor.

Why motors differ

Two motors of the same model still differ a little in friction, in winding and in how they run in. Motor speed also depends on the voltage actually reaching the motor, and a motor driver can drop slightly different voltages on its two channels. A battery that is getting low changes both motors, and not always equally. That is why a fix that only adjusts a number in code (making the left motor 0.985 as strong) works one day and not the next.

The fix: closed-loop correction

Open-loop means you command power and hope. Closed-loop means you measure what happened and correct it. With an encoder on each wheel, you can count how far each side moved and nudge the power to keep the counts equal.

const int BASE = 150;
const float KP = 3.0;

void loop() {
  long error = rightTicks - leftTicks;   // positive: right is ahead
  int pwmR = BASE - KP * error;
  int pwmL = BASE + KP * error;
  setMotors(pwmL, pwmR);
  delay(20);
}

In one 20 ms interval, suppose the left encoder counted 49 ticks and the right counted 51. The error is 2, the correction is 3.0 × 2 = 6, so the right motor gets 150 − 6 = 144 and the left gets 150 + 6 = 156. The robot corrects itself a little each cycle, and the veer disappears. Increase KP if it still drifts, and lower it if the robot starts to snake left and right. This is a simple proportional controller, the first step of a full PID controller.

One more trap is the start. A robot that begins with one wheel pushing against a sticky caster will curve for the first half meter and then straighten, which looks like a motor problem but is not. Give the robot a short run-up before the measured line, and discard the first run after you change anything, since a new fix often needs the wheels to settle. When you record numbers, write the battery voltage next to each run: if the veer grows as the battery sags, the cause is partly electrical and feedback is the right cure, not a fixed trim.

Test and tune

  1. Repeat the 2 m test three times and record the sideways error before and after.

  2. Try a lower battery state, a different floor and a heavier load. A good fix survives all three.

  3. Reset the tick counts at the start of each run so old counts do not matter.

Stay safe

Lift the robot off the table when you test code that sets motor power, and keep your fingers away from the wheels while it is powered. When you swap motors, switch off the battery first.

Frequently asked questions

Can I just slow down one motor in code?

You can, and it is a decent first fix, but it only works while conditions stay the same. Feedback adapts to changes in battery, load and floor.

Do I need encoders?

They make the fix reliable. Without them you can use a gyroscope to keep the heading, or live with a manual trim.

Get started

DuckyHelper can
do more

It sees your screen and works in any app you use. Try it for 10 minutes, no card.

Get it for Mac, Windows or Linux

Share

Questions and jobs

Do anything

Ask it a question or hand it a job, in any app.

Doing jobs for you is in early access on Mac. Asking works on Mac, Windows and Linux.