Driving Precise Distances with Encoders
Turn inches into encoder ticks with a worked example, learn the encoder run modes, and write a `driveInches()` helper that uses `RUN_TO_POSITION`.
In this lesson you will
- Explain what an encoder tick is and where to find ticks per revolution for a motor
- Calculate ticks per inch from ticks per revolution and wheel diameter
- Choose the correct run mode:
STOP_AND_RESET_ENCODER,RUN_USING_ENCODERorRUN_TO_POSITION - Write a
driveInches()helper with a timeout and calibrate it with a tape measure
Lesson
An encoder is a sensor built into most FTC motors that counts how far the motor shaft has turned. It reports this as a number of ticks. If the count goes from 0 to 1000, the shaft turned a known amount, so the wheel moved a known distance. That is how a robot can measure distance instead of guessing from time.
Every motor has a fixed number of ticks per revolution of its output shaft. It depends on the motor and its gearbox, so look it up on the manufacturer's spec sheet. For example, one common goBILDA 312 RPM motor lists about 537.7 ticks per output revolution. Your motor may be different.
From ticks to inches
When a wheel makes one full revolution, the robot rolls forward by the wheel's circumference, which is pi times the diameter. Divide ticks per revolution by the circumference and you get ticks per inch. Here is a worked example with example numbers:
- 1Ticks per revolutionFrom the spec sheet: 537.7 ticks per output revolution (example motor).
- 2Wheel diameterA 96 mm wheel. Convert to inches: 96 / 25.4 = 3.78 inches.
- 3Circumferencepi x 3.78 = about 11.87 inches travelled per wheel revolution.
- 4Ticks per inch537.7 / 11.87 = about 45.3 ticks per inch.
- 5Target for 24 inches24 x 45.3 = about 1087 ticks. One field tile is 24 inches, so this drives one tile.
Encoder run modes
| Run mode | What it does | When to use it |
|---|---|---|
STOP_AND_RESET_ENCODER | Stops the motor and sets the tick count to 0 | At the start of each move, so you measure from zero |
RUN_USING_ENCODER | Uses the encoder to hold a steady speed for the power you give | Normal driving and IMU turns |
RUN_WITHOUT_ENCODER | Sends power directly, no speed control (the count can still be read) | Simple mechanisms, or when you do your own control |
RUN_TO_POSITION | Drives the motor to a target tick count and holds it there | Driving set distances, moving arms or lifts to positions |
Order matters with RUN_TO_POSITION. First reset the encoder, then call setTargetPosition(), then switch to RUN_TO_POSITION, and only then set the power. If you switch to RUN_TO_POSITION before setting a target, the SDK reports an error. The power you set acts as the maximum speed on the way to the target.
1static final double TICKS_PER_INCH = 45.3; // replace with your calibrated value
2
3private void driveInches(double inches, double power, double timeoutS) {
4 int target = (int) Math.round(inches * TICKS_PER_INCH);
5
6 leftDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER);
7 rightDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER);
8 leftDrive.setTargetPosition(target);
9 rightDrive.setTargetPosition(target);
10 leftDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION);
11 rightDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION);
12
13 ElapsedTime timer = new ElapsedTime();
14 leftDrive.setPower(Math.abs(power));
15 rightDrive.setPower(Math.abs(power));
16
17 while (opModeIsActive() && timer.seconds() < timeoutS
18 && leftDrive.isBusy() && rightDrive.isBusy()) {
19 telemetry.addData("Target", target);
20 telemetry.addData("Left / Right", "%d / %d",
21 leftDrive.getCurrentPosition(), rightDrive.getCurrentPosition());
22 telemetry.update();
23 }
24
25 leftDrive.setPower(0);
26 rightDrive.setPower(0);
27 leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER);
28 rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER);
29}
isBusy() returns true while a motor is still moving toward its target. The loop stops as soon as either motor finishes, the timeout runs out, or the OpMode is stopped. The timeout is your safety net: if an encoder cable is unplugged, the count never changes and the robot would otherwise drive forever. For a negative distance, the target becomes negative and the robot drives backward.
Calibrate with a tape measure
The calculated value is a starting point. Real wheels compress slightly and roll a little differently from the spec. To calibrate, drive 48 inches with your helper, measure the real distance and correct the value: new ticks per inch = ticks driven / inches actually travelled. Repeat until the robot lands within about half an inch, and write the final number in your engineering notebook.
Key terms
- Encoder
- A sensor on a motor that counts how far the shaft has rotated.
- Tick
- One unit of encoder count; a fixed number of ticks makes one full revolution.
- Ticks per inch
- How many encoder ticks the drive motors count while the robot moves one inch.
- `RUN_TO_POSITION`
- A motor run mode that drives the motor to a target tick count and holds it there.
- `isBusy()`
- A motor method that returns true while the motor is still moving toward its target position.
- Timeout
- A time limit that ends a move even if the target was not reached, so the robot never gets stuck.
Practical exercise
Calculate and calibrate ticks per inch
- 1Find the ticks per revolution for your drive motors on the spec sheet and measure your wheel diameter.
- 2Calculate ticks per inch on paper, showing every step like the worked example.
- 3Add the
driveInches()helper to an autonomous OpMode and drive 48 inches at power 0.4. - 4Measure the real distance with a tape measure, correct
TICKS_PER_INCH, and repeat until the error is under half an inch. - 5Test a backward move of 24 inches to confirm negative distances work.
TICKS_PER_INCH in your code.Knowledge check
Answer every question, then check your answers.