Bang-Bang control and measurement lag on Falcon 500 / Talon FX

We’re running a bang-bang control system at 100Hz for our flywheel using the integrated Talon FX encoder and are seeing some odd behavior.

In this graph you can see the issue. The blue line is the measured RPM, the green line is the desired RPM, and the yellow line shows when the motor was on.

You can see that the speed continues to decrease even after the motor turns on, and also continues to increase after the motor turns off. The graph only makes sense to me if I shift that blue RPM line over to the left.

We believe that the measured RPM is averaging over a past period of time (documentation suggests 100ms), and so the controls are not responsive. By the time the integrated encoder measures that the flywheel is at the correct RPM it is in reality at a much higher RPM.

We’ve added an external encoder and have our bang-bang control working well now. Is there any advice on how to get the integrated Talon FX encoder to give us a more up-to-date RPM measurement? We’re aware that we can run a PID on the Talon FX itself - but we’re curious about why this happened and how we can fix it!

I can’t confirm until tomorrow, but based off the documentation, I agree that it appears as if “getIntegratedSensorVelocity” polls every 100ms.

Something which might work is to calculate the velocity yourself using getIntegratedSensorAbsolutePosition, this appears to use more current sensor data? Outside of that, I don’t see another way to get the integrated encoder velocity or change the averaging window in the documentation.

You can increase the frequency at which data is sent from the Talon by lowering the status frame period.

In your situation you’d want to lower the period for status frame 21 which by default is 100ms.

How would you set this in code? I’m trying setStatusFramePeriod() but there doesn’t seem to be a status 21 there. Would it be the quadrature sensor (status 3)?

That’s a good question, it actually appears to be missing from the api.


1 Like

It looks like there’s two issues going on. The first is the averaging that happens as part of the Velocity Measurement and Averaging Window configs, and the second is the rate at which you can get the sensor values from the API.

To solve the first, you can configure the TalonFX to use smaller averaging windows and sampling periods. The relevant documentation about where to start and how to determine what is “good” is here: Bring Up: Talon FX/SRX Sensors — Phoenix documentation

To solve the second, there is normally two ways, the first being to set the status frame period of the relevant frame, however…

I’ve added a tracker to include Status_21, so that should get picked up in the next release.

The other way to solve the update rate issue, and the way we recommend for most sensors, is to set the integrated sensor as your “selected sensor” and use the selectedSensor API, which default updates at 20ms and is available in the setStatusFramePeriod API under Status_2.
Documentation is available here: Bring Up: Talon FX/SRX Sensors — Phoenix documentation
Note: TalonFX by default selects the integrated sensor as its selected sensor

As a side note, since we’re discussing bang-bang control with the FX, I’d be curious if anyone has tried configuring the peak output values on their flywheel from [-1, 1] to [0, 1] and PID’ing on it with an extremely large P. Doing so would effectively replicate a bang-bang control on the Falcon’s internal PID, as the minimum value it can produce is 0 in that circumstance, and you get the benefits of the 1khz loop. As I understand, Bang-Bang control is more timing-dependent, so the 10x rate improvement could be beneficial, but I’ve never tried it myself.


Yes we are doing that currently. It seemed to work well (this was without the feedforward being well tuned so that would only make it better) but I didn’t dive into the graphs and such and quantify it.


Why not run the native talon velocity loop?

If you lock out motor reverse voltage (which you should do anyway), a P only controller with large P maths out the same as bang bang anyway.


You can do the math for how large you need to set your gain on the onboard controller for a desired response.

From Motor Controller Closed Loop — Phoenix documentation

  • Velocity is represented in encoder ticks per 100ms
  • PID output is represented in 1023 units per 100% output

We also know that the Falcon integrated encoder is 2048 ticks per revolution.

For example, if you want to saturate your output at an error of 0.01 RPM, you would first convert that to error to encoder ticks per 100ms.

0.01 revs / minute * 2048 ticks / rev = 20.48 ticks / minute = 0.0341333333 ticks / 100ms.

Then choose a P gain such that the controller output is 1023 when you see that error.
1023 / 0.0341333333 = 29970.7031543.

Does the CTRE API accept ‘Double.Positive_Infinity’ as a value for the proportional gain?

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.