Can't get TalonFX to work in Position mode

Hi all.

We are revsing our Swerve code to work with Falcons for the rotational drive instead of Rev Neos, and we are running into an issue where we are unable to get the Position based code to work. We are able to get the drive module to spin if we use PercentOutput Control mode (and have checked the encoder is working in the Phoenix Tuner self test mode), but Position mode with any value does not move the motor at all.

Relevant code:

 //BR Swerve PID Config
// reset to factory default

// config feedback sensor for PID
fxBRswerve.configSelectedFeedbackSensor(FeedbackDevice.IntegratedSensor, loopIDX, timeOutMs);

// Config peak and nominal outputs
fxBRswerve.configNominalOutputForward(0, timeOutMs);
fxBRswerve.configNominalOutputReverse(0, timeOutMs);
fxBRswerve.configPeakOutputForward(1, timeOutMs);
fxBRswerve.configPeakOutputReverse(-1, timeOutMs);
// config P,I,D,F values
fxBRswerve.config_kF(loopIDX, f, timeOutMs);
fxBRswerve.config_kP(loopIDX, P, timeOutMs);
fxBRswerve.config_kI(loopIDX, I, timeOutMs);
fxBRswerve.config_kD(loopIDX, D2, timeOutMs);

fxBRswerve.set(TalonFXControlMode.Position, 1024);

Any thoughts would be most helpful. Changing the numeric value here does nothing, as well as changing the sensor phase, or the PID value variables. This line will work (Percent Output mode), and the drive will spin if enabled:

fxBRswerve.set(TalonFXControlMode.PercentOutput, 0.25);

Thanks in advance!

Is the loopIDX something other than 0? If so you’ll need to setProfileSlot or whatever it’s called to match the slot

To add on this, I think Loop index and Slot index are being confused here. The former is which PID Controller is used (so you can run two controllers at once) and the latter is a storage for PID constants

Correct, loopIDX is actually referring to the slot index in code, so that should probably be changed too. Good catch!

loopIDX is set to zero, which as I understand it is correct - set as “Primary closed-loop”?

If you are saying should be changed, changed to what?

In that case, I’d check a few things:

  • Make sure your CAN utilization isn’t consistently reaching 100%
  • See if it works on a different motor
  • Try Velocity mode (run at a low velocity (I.e 100) for safety)

We did try PercentOutput mode at 0.25, and that worked, but I can give velocity a try. Code with variables wasn’t working on all four motors. CAN seems ok (was working fine in competition with SparkMAX’s as swerve controllers), but I would have to check the utilization.


EDIT: Note that if the device is connected to a roboRIO, you’ll probably have to use the driver station to enable control anyways, since the device will automatically go into a FRC locked state.

An easy way to verify that the motor itself is working properly in closed loop, is to factory default the motor and then attempt to control it using Tuner. Alternatively, you can skip factory defaulting and just enable via driver station.

  1. First, navigate to Config and ensure your device is selected at the top dropdown box. Then press the Factory Default button at the bottom. This will reset your device to default. Alternatively, you can just enable your robot in driver station.
  2. Now configure your gains under Slot 0 (that is the default slot unless you changed the slot)


  1. Now navigate to the control page. In the middle of the application is a drop down button labeled Control Mode. Change that to Position. If you factory defaulted your motor, then ensure you press the top Robot Disabled button. If you didn’t factory default, open driver station and press the “Enable” button. Lastly, just press the bottom button in Tuner that says Control Disabled. Verify that the motor is attempting to reach it’s set point.

If none of the above works for you, I’d send a support request to CTRE with a Self Test and a copy of your device Config attached.