Falcon FX, velocity PID, and stubborn error from GetClosedLoopError

We are using Falcon’s on our shooter, like many teams, and have one set as leader and one as follower. In our C++ code, we compare GetClosedLoopError to a threshold to know when the system is close enough to the requested speed to feed a powercell. After a year of operation, we’ve had to replace a Falcon because of the loctite issue (screws holding the output shaft in the motor backed out, until the last one left sheared off), and after replacing that motor and making other improvements, we noticed our error was always hovering around 3000 units, which is close to the threshold we set, and so our feed system was stuttering. We tried adjusting the PID numbers a bit, but the error always settles in around 3000. I read the thread from 2018 by @adrisj7 about having a consistent error that never closes, and we will continue to tune the PID numbers, but it seems like a very odd behavior for a velocity PID. Most recently we have removed the load on both motors, so they are spinning freely, and we still see GetClosedLoopError returning around 3000. This is with various set points, well below the maximum velocity, so it is not a matter of having the set point out of reach.

1 Like

So this sounds like you did not set a feedforward value due to having a constant error value. For Falcons/Talons, the value that you would set for kF is different from what the frc-characterization tool generates. I would refer you to this post which goes through the math in detail: Falcon 500 Closed Loop Velocity - Programming - Chief Delphi

We tried various values of kF between .1 and 1.5. Didn’t seem to change the steady error.

0.1 kF sounds high for TalonFx. Our kF is around 0.045 which is very close to the calculated value via kV from characterization tool.

Falcons have a max speed of around 6300 rpm with a command of 1023 (internally). This works out to a velocity of ~21,500 encoder units/100ms, so a kF of 1023/21,500, or about 0.05, should be enough to get the flywheel close.

Try zeroing the P I and D and setting up your kF to 0.05. Track the motor percent output and the speed and error. Tune kF to get you close to your target speed across a range of operating speeds, and then add your PID back in. I’d recommend retuning those at that point though, as you’ll be able to get away with more aggressive constants.

Make sure you firmware is updated on the new Falcon as well.

1 Like

Thank you @asid61 kF of .045 worked really well. We also used the characterization tool, but it produced kV of 0.108, which we translated to kF of 0.00158, which didn’t work well at all, and is almost 30 times lower than .045. Attached are our calcs to convert kV to kF. Wonder if there’s something wrong in our calcs?

We also found an odd bug with the characterization tool. The generated code had these lines:

static private int ENCODER_EDGES_PER_REV = 2048;
private double encoderConstant = (1 / GEARING) * (1 / ENCODER_EDGES_PER_REV);

Apparently the int type of ENCODER_EDGES_PER_REV causes encoderConstant to be zero, and all the data logged was zero as a result. Took us a while to find this. After changing type type of ENCODER_EDGES_PER_REV to double, it worked. Is this a known issue?

After thinking more about the issue of the integer vs double problem for encoderConstant, I’m guessing the special circumstances here is that GEARING is 1 for our shooter. Perhaps with a different GEARING, type conversions work out for this formula.

Yeah looks like another issue. This is revealed with the change I made here to stop it dividing by 4. The division by 4 before this would sometimes hide this issue.

Really underscores how much Unit Tests are needed for programs like this and how not having them costs everyone involved so much time. Sorry for not catching that when I made the quick PR!

Here is another PR to fix this issue!

1 Like