Gray Matter
WorkshopPID Tuning in Tuner X
WPILib 2027 is still in alpha: these pages change as the APIs settle.
LESSON 06

PID Tuning in Tuner X

The TalonFX runs the control loop itself. Tuner X sends the setpoint, plots the response, and saves the gains onto the motor.

14 minutes
You’ll need
  • Motor, encoder direction, and mechanism zero verified in Motor Setup & CAN IDs.
  • Tuner X connected to the CANivore, with CANivore USB on.
  • The mechanism, with a clear path to swing, and no obstacles.

What mechanism are you working on?

The lesson below is written for the one you pick. Switch back any time to read it for the other.

How to tune

CTRE has an excellent guide already that explains how to properly tune a PID loop. We strongly suggest following the steps in the guide.

After you follow this guide, come back here and we'll explain how to implement it.

CTRE: Manual PID tuning

CTRE tunes with a TorqueCurrentFOC request, so its gains are in amps. This course tunes with a voltage request, so the procedure carries over and their numbers do not.

Play with the gains

Drag a gain and watch what happens. Find out what too much kP looks like here, where it costs nothing, rather than on a real gearbox.

Switch between the three. The arm holds an angle, and gravity pulls on it everywhere except straight up and down. This arm is competition size, so it needs a real kG to hold. The 9 inch bench arm is light enough to need very little, so its feedforward is mostly kS. The flywheel holds a speed. Nothing drags it off target, but holding that speed costs output, and a game piece steals it at once. The elevator is the other gravity case, a constant pull.

Choose mechanism
loading playground…

Units and sizes

Every gain is output per unit of input. The request decides the output. A request ending in Voltage outputs volts, and one ending in TorqueCurrentFOC outputs amps. DutyCycle outputs a fraction of full power. CTRE's own examples put a position kP at 2.4 in volts and in the thousands in amps. A gain copied from a guide written for another request means nothing.

The input is mechanism rotations, never degrees. On the arm that is the arm shaft, because the CANcoder reads it there. The flywheel reads the motor's own sensor with no ratio set, so its input is rotations of the motor.

GainVolts perCTRE example
kP, positionrotation of error2.4
kP, velocityrps of error0.11
kD, positionrps the error changes by0.1
kS, kGnothing, a flat output0.1, for kS
kVrps of target velocity0.12
kArps² of target acceleration0.01

Rotations are why an arm kP looks big. An error of 0.01 rotations is 3.6 degrees, so a kP of 20 answers it with only 0.2 V. A geared arm in volts can land anywhere from about 1 to 100. A Kraken X44 needs about 0.093 V per rps of its own speed, so a flywheel kV in motor rotations lands a little above that.

SensorToMechanismRatio moves all of this. Set it to a gearbox's reduction and one rotation of input becomes one turn of the output. That multiplies kP and kV by roughly the reduction. Both bench builds leave it at 1, and Motor Setup & CAN IDsMotor Setup & CAN IDs says when to change it. Arm kG also needs the gravity type set to Arm_Cosine, which scales it by the cosine of the angle and expects 0 to be horizontal.

Tune the gains

Before running this, fully power cycle the CANivore and mechanism to prevent any old positions from being read.

  1. Open Signal & Control and add the TalonFX you are tuning.
  2. Plot two signals: the target and the measured position (or velocity for flywheels). Put target and measurement in one group so you can read the gap between them.
Note

Before you tune

In the control panel, pick a voltage-based position or velocity request and select Slot 0. Enter a small target: 0.1 rotations for position, 10 rps for velocity. The same requests come back in code in Mechanisms.

Run these steps on your actual mechanism. They are the CTRE procedure, in volts.

  1. Set every gain in Slot 0 to zero. Set Gravity Type to Arm_Cosine.
  2. Feedforward first. Raise kG to find the smallest and the largest values that hold the arm level. Set kG to the midpoint and kS to half the gap between them.
  3. Feedforward first. At a low target, raise kS until the wheel just turns. At a high target, raise kV until the measured speed meets the target with kP still at zero.
  4. Raise kP, doubling it each run, until the mechanism overshoots or oscillates. Then back off to about half of that value.
  5. Add kD in small steps until the overshoot stops. If the arm starts to buzz, you have gone too far.
  6. Leave kI at zero. Fix a steady gap with feedforward or kP first, and you will rarely need it.
  7. Try other targets in both directions, then apply the gains with the download button. A gain that was never applied never reaches the motor.

A tuned arm sounds like one motion and then silence. If the motor is still working after the mechanism stopped, kP is too high.

Three failure shapes

Nearly everything that goes wrong on a mechanism looks like one of these. Read the plot, not the mechanism.

Runs away
Wrong direction
Error grows instead of shrinking and output pins. Disable now. The sensor or the motor is inverted, so go back to Motor Setup.
Buzzes
Too much gain
Voltage chatters and the mechanism hums at rest. Cut kP before reaching for kD. Damping will not fix a loop that is too stiff.
Falls short
Not enough output (position control)
Error settles at a constant gap. Increase your kP to correct this, likely followed by a kD to dampen the overshoot.

When the plot looks like none of these, check the setup before the gains.

  • The request and the gains must both be on Slot 0. Gains in another slot do nothing.
  • A gain from an amps or duty cycle guide is meaningless in a voltage request.
  • A tired battery cannot reach the voltage a fresh one can. Re-check your gains on a charged battery.
  • A current limit that clips the output looks like too little gain. Watch for current sitting flat at the limit.
  • A runaway means the sensor or motor direction changed since Motor Setup & CAN IDs. Fix it there.
  • Gains that were never applied are lost. Power cycle, reopen the config, and confirm the numbers are still there.

Check your work

Drive the mechanism to its target in both directions, from a standstill, three times. You are done when all three runs look alike.

Check

You should see

  • The measured trace meets the target and stays there.
  • Closed-loop error settles near zero and does not drift back out.
  • Voltage is steady at rest, not chattering.
  • The same gains behave across the full range of travel.

Check yourself

You set every gain to zero, send a position target, and enable. The arm does nothing. What is wrong?

Your arm holds its angle perfectly at 90 degrees and sags badly at 30. Which term is wrong?

What order do you tune an arm in?

The arm reaches its target and then buzzes, sitting still. What do you reach for first?

Pick an answer for each.