Skip to content

Control Loop Tuning Problems

learnfrc.com
learnfrc.comAuthor
Veer Bajaj
Veer BajajMaintainer

A mechanism that overshoots, oscillates, or never quite reaches its setpoint is almost always a tuning problem with a known cause. WPILib documents the recurring ones.

If kI is too large, the integral term accumulates error during a big setpoint change until it exceeds the maximum control effort – the mechanism blows past the target and takes a long time to settle. Fixes, in order of preference (these methods live on WPILib’s PIDController):

  1. Reduce kI, often to zero -- most FRC mechanisms need no integral term at all. Tune the feedforward model instead.
  2. Reset the integrator outside a tolerance band with setIZone() -- when the position error exceeds IZone, the accumulated error resets to zero, disabling integral until you are close again.
  3. Cap the integrator with setIntegratorRange().
controller.setIZone(5.0); // only integrate within 5 units of target
controller.setIntegratorRange(-2, 2); // clamp accumulated effort

Drawing current drops bus voltage, so a controller tuned at 13V behaves differently at 11V – the mechanism slows as the battery droops. Fix it by commanding voltage rather than duty-cycle percent so output is consistent regardless of bus voltage:

motor.setVoltage(feedforward.calculate(setpointVelocity));

Using setVoltage() (or the controller’s voltage-compensation feature) makes your gains battery-independent.

If gains are so aggressive that the mechanism demands more torque or acceleration than the motor can deliver, it saturates at maximum output and can become unstable – you can’t tune your way past physics. The fix is mechanical: change the gearing or move to a higher-power motor (e.g. NEO -> NEO Vortex, Falcon 500 -> Kraken X60) to gain control authority.

The single most common ‘bad PID’ is actually missing feedforward. A flywheel or drivetrain is feedforward-dominated; an arm needs kG that varies with the cosine of its angle; an elevator needs a constant kG. If you try to do the whole job with kP, you get sluggish tracking and steady-state error. Get kS/kV/kA from a SysId characterization run, add kG for gravity-loaded mechanisms, and let P handle only the residual.

Start from zero gains. Add feedforward until the mechanism roughly follows commands open-loop. Then raise kP until tracking is crisp; add a little kD only if it overshoots; reach for kI last and rarely. Throughout, watch the measured-vs-setpoint plot in AdvantageScope -- oscillation means too much kP or noisy kD; lag means too little kP or missing FF; steady offset means missing kG or FF. Change one gain at a time and re-plot.

  • Integral windup comes from too-large kI; prefer kI=0 with good feedforward, or bound it with setIZone()/setIntegratorRange() on WPILib’s PIDController.
  • Command voltage with setVoltage() so gains stay consistent as battery voltage sags.
  • Actuator saturation is a physics limit – fix it with gearing or a higher-power motor, not more gain.
  • Most ‘bad PID’ is missing feedforward; get kS/kV/kA from SysId, add kG for gravity, and diagnose with the AdvantageScope setpoint-vs-measured plot.

This lesson was adapted from learnfrc.com.