Skip to content

Control Systems

How to hold a motor's speed with an encoder and PI

To hold a motor at a set speed, measure the speed with an encoder, compare it with the target, and adjust the drive: a speed loop. A good one has three parts. Feedforward puts in the drive that speed usually needs, P pushes in proportion to the error, and I builds up until a steady extra load, like a hill, is met with no error left.

Measure: ticks in a window

Count the encoder's ticks for a fixed time, then scale. With a 20-slot disc and a 50 ms window there are 1200 windows a minute:

rpm = count ÷ 20 × 1200 = count × 60

20 ticks in a window is 1200 rpm. A count is a whole number, so readings come in steps of 60 rpm: a wheel at 1230 reads 1200 or 1260. That's fine, because the wheel is heavy and the loop averages the jumps. A 100 ms window halves the step, but each reading then describes an older moment. Slow motors are better timed: measure the gap between ticks with micros().

The loop

pwm = 100 + 0.1 × error + 0.2 × integral

Every 50 ms: work out the speed from the count, error = 1200 − speed, add error × 0.05 s to the integral, then set the drive. The 100 is the feedforward: on the flat it already gives about 1200 rpm, so P and I have almost nothing to do.

Live experiment

Hold 1200 rpm up a hill

A wheel's encoder gives 20 ticks a turn, counted every 50 ms. Work the reading out as the raw count, × 20 and × 60, and watch the amber dots of what the loop thinks. Then drive up the hill with P only, PI, and a greedy PI.

Try it yourself: free lesson

“Hold the speed” is lesson 2 of 6 in Balance Bluffs, Control Systems World 3. Free with an account. Lessons unlock in order, so you’ll do the 15 before it first.

Why P alone droops

Up a hill the wheel needs more drive. P only adds drive while there's an error, so a P-only loop settles where the error pays for the extra: about 1036 rpm instead of 1200. The I term keeps adding the error up for as long as it lasts, so it grows until the hill's extra drive is all there and the error is gone.

Gentle on the I

The integral also adds up the error while the wheel spins up from rest. At Ki 0.2 that's a small surge, to about 1340 rpm, before it settles. At Ki 1.0 so much piles up that the wheel shoots past 1700 rpm. Keep Ki modest, and clamp the integral if the motor can hit full drive, or it winds up.

Where you'll meet it

Treadmills hold their belt speed as your feet land, and e-bikes, cordless drills, record turntables and 3D printer fans all count pulses from the motor and run a loop like this one. In a robot it's often the inner loop of a cascade, carrying out speed orders from a position loop.

Free lesson

Now build it yourself

Each lesson comes in three short parts: see the idea, try it on a live board, then build it yourself, with quick checks as you go.

Try it yourself: free lesson

“Hold the speed” is lesson 2 of 6 in Balance Bluffs, Control Systems World 3. Free with an account. Lessons unlock in order, so you’ll do the 15 before it first.

Or start from the very first lesson, no account needed

Practice questions

Three quick questions from the lessons. Pick an answer to check it.

  1. Question 1 of 3A count can only be a whole number. So one reading of speed is good to about…
    Show the answer

    Answer: ±60 rpm: one tick either way. One tick more or less in a 50 ms window is 60 rpm more or less. The wheel is heavy, so the loop averages the jumps out.

    • Why not “±600 rpm”? That would be ten ticks out. A count is only ever one tick off, which is worth 60 rpm.
    • Why not “Exactly right”? A wheel at 1230 rpm reads 1200 or 1260, never 1230. The count rounds it to whole ticks.
    • Why not “±1 rpm”? ±1 rpm would need a tick for every rpm. In a 50 ms window each tick is worth 60 rpm.
  2. Question 2 of 3Count over 100 ms instead of 50 ms, and each tick is worth…
    Show the answer

    Answer: 30 rpm: finer steps, but each reading is older. Twice the time, half the rpm per tick. The trade: a reading now describes the last 100 ms, which is lag.

    • Why not “60 rpm”? 60 rpm is the 50 ms figure. Twice the window, half the rpm per tick.
    • Why not “120 rpm”? A longer window makes each tick worth less, not more. 120 rpm a tick would be a 25 ms window.
    • Why not “Nothing changes”? The window sets the scale: 100 ms windows come 600 times a minute, not 1200, so each tick is worth half as much.
  3. Question 3 of 3pwm = 100 + 0.1 × error + 0.2 × integral. On the flat, holding 1200 rpm with no error, the integral is about…
    Show the answer

    Answer: 0: the feedforward alone already gives 1200 rpm. Feedforward does the usual work. The integral only builds up on the hill, to about 150, worth 30 more pwm.

    • Why not “1200”? 1200 is the target speed. An integral that big would add 240 to the drive and send the wheel racing.
    • Why not “−100”? A negative integral would take drive away, and the wheel would slow below 1200 on the flat.
    • Why not “100”? 100 is the feedforward, already in the formula. The integral only adds what the feedforward misses.
Keep practising: free lesson

“Hold the speed” is lesson 2 of 6 in Balance Bluffs, Control Systems World 3. Free with an account. Lessons unlock in order, so you’ll do the 15 before it first.

Questions people ask

How do you calculate rpm from encoder ticks?

rpm = ticks counted ÷ ticks per turn × windows per minute. With 20 ticks a turn and a 50 ms window there are 1200 windows a minute, so rpm = count × 60: 15 ticks in a window is 900 rpm.

Why use feedforward in a speed loop?

Most of the drive a motor needs is predictable: so much drive for so much speed. Putting that in directly leaves P and I only the difference to fix, so the loop responds faster and the integral stays small.

Should a motor speed controller be PI or PID?

PI is usually enough. Encoder speed readings come in steps, and a D term would amplify every jump between them. Add D only if the speed overshoots badly and the reading is smooth.

Every topic