Control Requests#

Phoenix 6 provides an extensive list of flexible control modes through the use of strongly-typed control requests.

Note

For more information about control requests in Phoenix 6, see Control Requests.

Using Control Requests#

v5

// robot init, set voltage compensation to 12 V
m_motor.configVoltageComSaturation(12);
m_motor.enableVoltageCompensation(true);

// main robot code, command 12 V output
m_motor.set(ControlMode.PercentOutput, 1.0);
// robot init, set voltage compensation to 12 V
m_motor.ConfigVoltageComSaturation(12);
m_motor.EnableVoltageCompensation(true);

// main robot code, command 12 V output
m_motor.Set(ControlMode::PercentOutput, 1.0);

v6

// class member variable
final VoltageOut m_request = new VoltageOut(0);

// main robot code, command 12 V output
m_motor.setControl(m_request.withOutput(12.0));
// class member variable
controls::VoltageOut m_request{0_V};

// main robot code, command 12 V output
m_motor.SetControl(m_request.WithOutput(12_V));

Follower Motors#

v5

// robot init, set m_follower to follow m_leader
m_follower.follow(m_leader);
// m_follower should NOT oppose m_leader
m_follower.setInverted(TalonFXInvertType.FollowMaster);
// set m_strictFollower to follow m_leader
m_strictFollower.follow(m_leader);
// set m_strictFollower to ignore m_leader invert and use its own
m_strictFollower.setInverted(TalonFXInvertType.CounterClockwise);

// main robot code, command 100% output for m_leader
m_leader.set(ControlMode.PercentOutput, 1.0);
// - m_follower and m_strictFollower will also run at 100% output
// - m_follower will follow m_leader's invert, while m_strictFollower
//   ignores it and uses its own
// NOTE: if set(), neutralOutput(), or disable() is ever called on
//       the followers, they will stop following
// robot init, set m_follower to follow m_leader
m_follower.Follow(m_leader);
// m_follower should NOT oppose m_leader
m_follower.SetInverted(TalonFXInvertType::FollowMaster);
// set m_strictFollower to follow m_leader
m_strictFollower.Follow(m_leader);
// set m_strictFollower to ignore m_leader invert and use its own
m_strictFollower.SetInverted(TalonFXInvertType::CounterClockwise);

// main robot code, command 100% output for m_leader
m_leader.Set(ControlMode::PercentOutput, 1.0);
// - m_follower and m_strictFollower will also run at 100% output
// - m_follower will follow m_leader's invert, while m_strictFollower
//   ignores it and uses its own
// NOTE: if Set(), NeutralOutput(), or Disable() is ever called on
//       the followers, they will stop following

v6

// class member variables
final DutyCycleOut m_request = new DutyCycleOut(0);

// robot init, set m_follower to follow m_leader
// m_follower should NOT oppose leader
m_follower.setControl(new Follower(m_leader.getDeviceID(), false));
// set m_strictFollower to strict-follow m_leader
// strict followers ignore the leader's invert and use their own
m_strictFollower.setControl(new StrictFollower(m_leader.getDeviceID()));

// main robot code, command 100% output for m_leader
m_motor.setControl(m_request.withOutput(1.0));
// - m_follower and m_strictFollower will also run at 100% output
// - m_follower will follow m_leader's invert, while m_strictFollower
//   ignores it and uses its own
// class member variables
controls::DutyCycleOut m_request{0};

// robot init, set m_follower to follow m_leader
// m_follower should NOT oppose leader
m_follower.SetControl(controls::Follower{m_leader.GetDeviceID(), false});
// set m_strictFollower to strict-follow m_leader
// strict followers ignore the leader's invert and use their own
m_strictFollower.SetControl(controls::StrictFollower{m_leader.GetDeviceID()});

// main robot code, command 100% output for m_leader
m_motor.SetControl(m_request.WithOutput(1.0));
// - m_follower and m_strictFollower will also run at 100% output
// - m_follower will follow m_leader's invert, while m_strictFollower
//   ignores it and uses its own

Changing Update Frequency (Control Frame Period)#

v5

// slow down the Control 3 frame (general control) to 50 Hz (20ms)
m_talonFX.setControlFramePeriod(ControlFrame.Control_3_General, 20);
// slow down the Control 3 frame (general control) to 50 Hz (20ms)
m_talonFX.SetControlFramePeriod(ControlFrame::Control_3_General, 20);

v6

// class member variables
final DutyCycleOut m_request = new DutyCycleOut(0);

// slow down the control request to 50 Hz
m_request.UpdateFreqHz = 50;
// class member variables
controls::DutyCycleOut m_request{0};

// slow down the control request to 50 Hz
m_request.UpdateFreqHz = 50_Hz;

Tip

UpdateFreqHz can be set to 0 Hz to synchronously one-shot the control request. In this case, users must ensure the control request is sent periodically in their robot code. Therefore, we recommend users call setControl no slower than 20 Hz (50 ms) when the control is one-shot.

Control Types#

In Phoenix 6, voltage compensation has been replaced with the ability to directly specify the control output type.

All control output types are supported in open-loop and closed-loop control requests.

Open-loop Control Requests#

Phoenix 5

Phoenix 6

PercentOutput

DutyCycleOut

PercentOutput + Voltage Compensation

VoltageOut

Phoenix 5 does not support torque control

TorqueCurrentFOC (requires Pro)

Current closed-loop

This has been deprecated in Phoenix 6.

  • Users looking to control torque should use TorqueCurrentFOC (requires Pro)

  • Users looking to limit current should use supply and stator current limits

Closed-loop Control Requests#

Phoenix 5

Phoenix 6

Position

PositionDutyCycle

Velocity

VelocityDutyCycle

MotionMagic

MotionMagicDutyCycle

Closed-loop + Voltage Compensation

{ClosedLoop}Voltage

Closed-loop + Torque Control (not supported in Phoenix 5)

{ClosedLoop}TorqueCurrentFOC (requires Pro)