> For the complete documentation index, see [llms.txt](https://docs.revrobotics.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.revrobotics.com/first-global/fgc-pid.md).

# PIDF Tuning Guide

The Control Hub has preset PIDF values for the motors in the *FIRST* Global Kit of Parts, but they are based on a freely spinning motor. When that motor is a part of a mechanism that adds load, the PIDF values should be re-tuned, or else the motor will not perform optimally in RUN\_USING\_ENCODER mode or RUN\_TO\_POSITION mode. This guide will teach you how to set the PIDF values for your specific mechanism in your OpMode.

{% hint style="info" %}
For more information about PID and custom tuning using variables, check out the [guide here](https://docs.revrobotics.com/ftc-kickoff-concepts/decode-2025-26/programming-tips-and-tricks#using-pid-with-the-flywheel)!
{% endhint %}

## Required Reading

Read the [Encoder Basics for Blocks](https://docs.revrobotics.com/duo-control/hello-robot-blocks/part-3/using-encoder) and/or the [Encoder Basics for OnBot Java](https://docs.revrobotics.com/duo-control/hello-robot-java/part-3/using-encoder) programming guides before reading this guide. In addition, make sure that your Control Hub and Expansion Hub have been updated with the latest firmware (see [Updating the Control System](https://docs.revrobotics.com/duo-control/managing-the-control-system/rev-hardware-client)).&#x20;

## Basic PIDF Tuning

You can establish basic PIDF values for your mechanism by plugging a simple measurement into a formula. This will be sufficient for most use cases. The measurement you need is the maximum motor velocity of your mechanism. To get this, run a maximum velocity measurement OpMode with a full battery. In this OpMode, it is important that you set your motor’s mode to RUN\_WITHOUT\_ENCODER and the power to 1. Example velocity measurement OpModes are listed below.

### Maximum Velocity Measurement in Blocks

An OpMode like this will display the maximum telemetry for a motor to telemetry. You will need to create variables named maxVelocity and currentVelocity in the Variables section of the left toolbar. Note that you can find the velocity block under Actuators -> DcMotor -> Extended.

<img src="/files/pMIbGPYnJLqbdHWGgnJv" alt="" width="511">

### Maximum Velocity Measurement in Java

Here is the same OpMode written in Java:

```
package org.firstinspires.ftc.teamcode;

@TeleOp
public class MaxVelocityTest extends LinearOpMode {
    DcMotorEx motor;
    double currentVelocity;
    double maxVelocity = 0.0;

    @Override
    public void runOpMode() {
        motor = hardwareMap.get(DcMotorEx.class, "motor");
        motor.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);
        waitForStart();

        while (opModeIsActive()) {
            motor.setPower(1);
```

```
           currentVelocity = motor.getVelocity();
            
            if (currentVelocity > maxVelocity) {
                maxVelocity = currentVelocity;
            }
            
            telemetry.addData("Current Velocity", currentVelocity);
            telemetry.addData("Maximum Velocity", maxVelocity);
            telemetry.update();
        }
    }
}
```

### Calculating PIDF Values from Maximum Velocity

Once you have your maximum velocity (maxV), you can calculate the velocity PIDF values. Your F value is calculated like this:&#x20;

$$
F = 32767 \div maxV
$$

So if your max velocity is 2600 ticks per second (reasonable for a mechanism that uses the HD Hex Motor), then your F value should be about 12.6.

Then your P value is calculated from your F value:

$$
P = 0.1 \times F
$$

Then your I value is calculated from your P value:

$$
I = 0.1 \times P
$$

Your D value should be zero.

$$
D = 0
$$

So for a maximum velocity of 2600 ticks per second, your velocity PIDF values are:

$$
\begin{align}
\begin{split}\
\notag
P &=1.26\\
I &=0.126\\
D &=0\\
F &=12.6
\end{split}
\end{align}
$$

Regardless of your maximum velocity, you can set the position PIDF values to:

$$
P = 5.0
$$

Position-mode PIDF only requires a single value because it also uses the velocity PIDF values.

## Setting PIDF Values in OpModes

PIDF values are only remembered for the duration of the OpMode that they are set in, so you must apply them at the beginning of all OpModes that you want them to apply to.

**Blocks:**\
In Blocks, you apply velocity and position PIDF values using these blocks (found under Actuators -> DcMotor -> Extended).

![](/files/owe1dVMWrhRi1cnm2xYn)

When you run your OpMode, you may see an error that says `Fatal error occurred while executing the block labeled “call motor.setVelocityPIDFCoefficients”`. This indicates that you have not updated your Control Hub or Expansion Hub firmware.

**OnBot Java**: In Java, you can do the same thing with the following lines of code (your motor variable must be defined as a DcMotorEx instance).

`motor.setVelocityPIDFCoefficients(1.26, 0.126, 0, 12.6);`\
`motor.setPositionPIDFCoefficients(5.0)`

When you run your OpMode, you may see an error that says `User code threw an uncaught exception: UnsupportedOperationException - setting of pidf coefficients not supported`. This indicates that you have not updated your Control Hub or Expansion Hub firmware.

## Verifying PIDF Values&#x20;

You should test your PIDF values by switching to RUN\_USING\_ENCODER mode, setting the velocity to around half of the measured maximum velocity of your mechanism, and continuously printing the current velocity to telemetry. If the motor does not quickly get close to the specified velocity, you should ensure that you did the math correctly.&#x20;

## Custom PIDF Tuning&#x20;

### Velocity versus Position PIDF Values

For each motor, you are able to set PIDF values for velocity and position. The velocity PIDF values are used to help the motor target a particular speed in RUN\_USING\_ENCODER mode. In RUN\_TO\_POSITION mode, the position P value is used to find a target velocity for the motor, and the velocity PIDF values are used to target that velocity. Therefore, it is important to correctly tune your velocity PIDF values before tuning the position P value.&#x20;

### Tuning the Position P Value&#x20;

The simplest customization to make to your PIDF values is to tune the position P value. The higher the value is, the faster the motor will move towards the target. However, if the value is too high, then the motor will overshoot the target and begin to oscillate.&#x20;

### Tuning the Velocity PIDF Value

The F value is used to make a guess for what the motor power should be in a perfect system, based on the maximum velocity of your mechanism. Therefore, you should leave it at the value calculated in the section titled [Calculating PIDF Values from Maximum Velocity](https://docs.google.com/document/d/1FcbQiDUd3Grl_W08-etAeV-qIoBRynQvPjsCepygtGE/view#heading=h.61g9ixenznbx). The remaining values (P, I, and D) work as they do in any other PID closed-loop system. There are many ways to tune these, which you can research yourself. Remember that the target value is a velocity, not a position. This YouTube video made by Worcester Polytechnic Institute serves as a starting point: <https://www.youtube.com/watch?v=2Yif6PdXPWg.>
