TalonFX Remote Sensors#

The TalonFX supports various remote sensors. Remote sensors allow onboard closed-loop functionality at rates faster than a traditional robot processor (~1Khz) by reading the remote sensor directly from the CAN bus. This allows supported motor controllers to execute closed-loop modes with sensor values sourced by supported sensors.

A list of supported remote sensors can be found in the API docs (Java, C++).

Remote sensors can be configured using Tuner X or via code. This document highlights how to configure a remote sensor in a robot program.

RemoteCANcoder#

A supported motor controller will update its position and velocity whenever the CANcoder publishes its information on the CAN bus.

var fx_cfg = new TalonFXConfiguration();
fx_cfg.Feedback.FeedbackRemoteSensorID = m_cancoder.getDeviceID();
fx_cfg.Feedback.FeedbackSensorSource = FeedbackSensorSourceValue.FusedCANcoder;

m_talonFX.getConfigurator().apply(fx_cfg);
configs::TalonFXConfiguration fx_cfg{};
fx_cfg.Feedback.FeedbackRemoteSensorID = m_cancoder.GetDeviceID();
fx_cfg.Feedback.FeedbackSensorSource = signals::FeedbackSensorSourceValue::FusedCANcoder;

m_talonFX.GetConfigurator().Apply(fx_cfg);

FusedCANcoder#

New in Phoenix Pro is a feedback sensor type called FusedCANcoder. FusedCANcoder will fuse another CANcoder’s information with the motor’s internal rotor, which provides the best possible position and velocity for accuracy and bandwidth. This is useful in applications such as swerve azimuth.

FusedCANcoder requires the configuration of several Feedback config group items, shown below.

Full example: Java, C++

51    /* Configure CANcoder to zero the magnet appropriately */
52    CANcoderConfiguration cc_cfg = new CANcoderConfiguration();
53    cc_cfg.MagnetSensor.AbsoluteSensorRange = AbsoluteSensorRangeValue.Signed_PlusMinusHalf;
54    cc_cfg.MagnetSensor.SensorDirection = SensorDirectionValue.CounterClockwise_Positive;
55    cc_cfg.MagnetSensor.MagnetOffset = 0.4;
56    m_cc.getConfigurator().apply(cc_cfg);
57
58    TalonFXConfiguration fx_cfg = new TalonFXConfiguration();
59    fx_cfg.Feedback.FeedbackRemoteSensorID = m_cc.getDeviceID();
60    fx_cfg.Feedback.FeedbackSensorSource = FeedbackSensorSourceValue.FusedCANcoder;
61    fx_cfg.Feedback.SensorToMechanismRatio = 1.0;
62    fx_cfg.Feedback.RotorToSensorRatio = 12.8;
63
64    m_fx.getConfigurator().apply(fx_cfg);
11  /* Configure CANcoder to zero the magnet appropriately */
12  configs::CANcoderConfiguration cc_cfg{};
13  cc_cfg.MagnetSensor.AbsoluteSensorRange = signals::AbsoluteSensorRangeValue::Signed_PlusMinusHalf;
14  cc_cfg.MagnetSensor.SensorDirection = signals::SensorDirectionValue::CounterClockwise_Positive;
15  cc_cfg.MagnetSensor.MagnetOffset = 0.4;
16  m_cc.GetConfigurator().Apply(cc_cfg);
17
18  configs::TalonFXConfiguration fx_cfg{};
19  fx_cfg.Feedback.FeedbackRemoteSensorID = m_cc.GetDeviceID();
20  fx_cfg.Feedback.FeedbackSensorSource = signals::FeedbackSensorSourceValue::FusedCANcoder;
21  fx_cfg.Feedback.SensorToMechanismRatio = 1.0;
22  fx_cfg.Feedback.RotorToSensorRatio = 12.8;
23
24  m_fx.GetConfigurator().Apply(fx_cfg);

Usage is the same as any status signal:

fx_pos.refresh();
cc_pos.refresh();

System.out.println("FX Position: " + fx_pos.toString());
System.out.println("CANcoder Position: " + cc_pos.toString());
fx_pos.Refresh();
cc_pos.Refresh();

std::cout << "FX Position: " << fx_pos << std::endl;
std::cout << "CANcoder Position: " << cc_pos << std::endl;