Skip to content

Flywheel two-level supply current protection is disabled + missing voltage ramp #206

@markpete

Description

@markpete

@Jetblackdragon - Consider if we need to adjust these down or if your happy with these existing settings.

Summary

Two configuration bugs in Flywheels.java allow the flywheel motors to spike and hold
high supply current with no hardware-level throttling. This is a contributing cause of
the observed brownouts and the likely root cause of the failed flywheel motor.

Context: The flywheel is a two-motor (Kraken X60) primary scoring mechanism that fires
a sustained volley of up to 40–50 balls at 6–10 balls/second (one ball every 100–167 ms).
At this rate the inter-ball window is shorter than a single flywheel recovery burst, meaning
the motors are under essentially continuous high-load recovery for the full 4–8 second volley.


Affected File

src/main/java/frc/robot/subsystems/launcher/Flywheels.javaconfigureMotors(), lines 93–97


Bug 1: SupplyCurrentLowerLimit = 0 disables two-level supply protection

Current code

config.CurrentLimits.SupplyCurrentLimit      = 80;
config.CurrentLimits.SupplyCurrentLimitEnable = true;
config.CurrentLimits.SupplyCurrentLowerLimit  = 0;   // ← BUG: disables two-level protection
// SupplyCurrentLowerTime not set — defaults to 0 s
config.CurrentLimits.StatorCurrentLimit       = 100;
config.CurrentLimits.StatorCurrentLimitEnable = true;

Root cause

Phoenix 6's two-level supply limiting is described in the
CTRE docs:

"if the supply current limiter has been actively limiting for the SupplyCurrentLowerTime,
the limit will be reduced to the SupplyCurrentLowerLimit until supply current is below
that limit, preventing breakers from tripping."

Setting SupplyCurrentLowerLimit = 0 means the throttle-back threshold is never crossed
(supply is always ≥ 0 A), so the protection never activates. Both motors can sustain 80 A
supply indefinitely — directly contributing to bus sag and motor thermal damage during a
multi-second volley.

SupplyCurrentLowerTime is also unset and defaults to 0 s. Even with a corrected lower limit,
a LowerTime of 0 s would throttle supply immediately, starving recovery torque between shots.

Why stator limits should NOT be reduced

StatorCurrentLimit = 100 A is intentionally preserved:

"Stator current limits also restrict acceleration. It is important not to set stator current
limits too low, otherwise performance may be negatively impacted."
— CTRE docs

At 6–10 balls/second, stator current directly controls velocity recovery between each ball.
Reducing stator reduces recovery torque, which at this firing rate means velocity dips
accumulate across the volley rather than clearing between shots. The flywheel's rotational
inertia does most of the per-shot work; the motor's job is to continuously replenish that
kinetic energy. Starving stator current undermines the entire mechanism.

Choosing SupplyCurrentLowerLimit and SupplyCurrentLowerTime at 6–10 balls/second

At 6–10 balls/second the motor has no meaningful idle time between shots. Supply current stays
elevated for essentially the entire volley (~4–8 seconds for 40–50 balls). This changes how
the two-level window behaves:

SupplyCurrentLowerTime Effect at 10 balls/sec
0.5 s Throttle engages after ~ball 5. Most of the volley runs at the lower limit.
1.5 s Throttle engages after ~ball 9–15. First half of volley at full peak; second half at sustained limit.
4.0+ s Throttle never engages during a 40-ball volley. No sustained protection.

SupplyCurrentLowerTime = 1.5 s is the right balance: it allows the full 80 A peak
through the critical first 1–1.5 seconds of the volley (roughly the first 9–15 balls where
the flywheel is also coming up to stable operating temperature), then transitions to the
sustained limit for the remainder.

SupplyCurrentLowerLimit = 70 A is chosen — not 60 A — because at 6–10 balls/second
the sustained limit becomes the effective operating current for most of the volley. At
70 A supply with duty cycle ≈ 0.9 (motor near full speed), available stator ≈ 70 / 0.9
78 A — a strong recovery budget that maintains shot cadence. Dropping to 60 A would
yield ~67 A stator sustained, visibly degrading the shot rate in the second half of the volley.


Bug 2: No closed-loop voltage ramp on initial spin-up

Without a VoltageClosedLoopRampPeriod, the PID commands full voltage instantly when the
driver presses the launch trigger. This spike coincides with the drivebase, feeder, spindexer,
and turret all activating simultaneously — the combination causes the bus voltage sag that
produces brownouts on match start.

Note: This ramp only materially affects cold start (0 RPS → target). Mid-volley recovery
bursts are a small additional voltage push from an already ~90% output state; a 0.2 s ramp
on a ~10% swing takes ~20 ms, which does not affect shot cadence.


Bug 3: Motor temperature not monitored (critical for 4–8 s sustained volley)

At 6–10 balls/second, both motors run under continuous high-load recovery for 4–8 seconds.
The TalonFX has built-in thermal protection that will silently derate output when winding
temperature becomes excessive — causing unexplained velocity drops late in the volley and,
over repeated matches, motor failure.

Currently only velocity and supply current are logged to NT. Temperature is never queried.


Proposed Fix

Flywheels.javaconfigureMotors()

private void configureMotors() {
    TalonFXConfiguration config = new TalonFXConfiguration();

    // Supply current:
    //   Peak of 80 A per motor is available for the first 1.5 s of the volley
    //   (~9–15 balls at competition firing rate). After 1.5 s of continuous draw,
    //   throttles to 70 A sustained for the remainder of the volley.
    //
    //   At 70 A supply / ~0.9 duty cycle at speed → ~78 A stator available sustained.
    //   This preserves strong velocity recovery throughout the full voley.
    config.CurrentLimits.SupplyCurrentLimit      = 80;   // peak (unchanged)
    config.CurrentLimits.SupplyCurrentLimitEnable = true;
    config.CurrentLimits.SupplyCurrentLowerLimit  = 70;   // FIX: was 0 (disabled)
    config.CurrentLimits.SupplyCurrentLowerTime   = 1.5;  // FIX: was unset (0 s)

    // Stator: keep at 100 A. At 6–10 balls/sec stator current directly controls
    // velocity recovery cadence. Reducing this degrades the shot rate.
    config.CurrentLimits.StatorCurrentLimit       = 100;  // unchanged
    config.CurrentLimits.StatorCurrentLimitEnable = true;

    // Ramp: softens the 0 → full-speed voltage spike on initial trigger press.
    // Does not affect mid-volley recovery (motor already at ~90% output).
    config.ClosedLoopRamps.VoltageClosedLoopRampPeriod = 0.20; // FIX: was unset

    // Neutral mode and invert (unchanged)
    config.MotorOutput.NeutralMode = NeutralModeValue.Coast;
    config.MotorOutput.Inverted    = InvertedValue.Clockwise_Positive;

    // PID Slot 0 — spin-up (unchanged)
    config.Slot0.kP = 0.1;

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions