Control Loop Tuning Problems
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.
Integral windup
Section titled “Integral windup”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):
- Reduce kI, often to zero -- most FRC mechanisms need no integral term at all. Tune the feedforward model instead.
- 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. - Cap the integrator with
setIntegratorRange().
controller.setIZone(5.0); // only integrate within 5 units of targetcontroller.setIntegratorRange(-2, 2); // clamp accumulated effortVoltage sag
Section titled “Voltage sag”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.
Actuator saturation
Section titled “Actuator saturation”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.
Missing or wrong feedforward
Section titled “Missing or wrong feedforward”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.
A disciplined process
Section titled “A disciplined process”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.
Key takeaways
Section titled “Key takeaways”- 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.
