Hiya Everyone! We discovered an issue last summer that recently presented itself to another team at a local demo. I promised to send them an email about how to fix the issue, but decided posting a link here on chief might serve more people in the community.
The general warning: The .follow() method is not supported by TalonFX.
Problem Manifestation
Within a gear box containing 2 falcons (in this case for a drive pod), one of the two motors will get hot, while the other will remain cool. We believe this is due to the leader trying to drive while the follower is “along for the ride.” Note, even though it’s not matching the leader, our testing showed the follower will still blink the same corresponding red or green blink code to match the leader. This problem will not appear unless you can drive your robot around; there isn’t enough resistance by driving it on blocks for the issue to manifest.
There have been threads that discussed this in the past, such as this one and this one, but neither explicitly state the .follow method as the issue.
Upon further research, it can be found in the CTRE API Docs that .follow() currently supports following for VictorSPX and TalonFX
This method is the currently supported way, and should be used instead of .follow().
Note 2 things:
The set method takes in a double, so you must provide it with the TalonFX device id of the motor you wish to follow. This differs from .follow(), where you provided it the TalonFX object itself.
You only have to set this once. If you use the set function on the follower motor again, it will detach itself from the leader motor.
Hopefully this helps a few teams! Good luck everyone!
Yeah, I have a hard time believing the Falcon500/TalonFX has been out for a couple years without having .follow() properly implemented. As a software engineer, I can confidently state that documentation seems to always be outdated the moment it’s published.
I also don’t quite understand the issue. If it works fine on blocks, then follower mode (via .follow()) is working just fine. Has this been tested with 2 motors outside of a gearbox? The presence/absence of a mechanical link should not matter when testing that functionality. Now, if there’s extra resistance in the gearbox (improper tolerances, no grease, etc), that could certainly cause issues.
This is symptomatic of a bad documentation process. WPILib docs are built and published automatically from the current source, and we don’t accept PRs that do not update the documentation. There are still some lingering patches from the pre-open-source days that aren’t totally mapped yet, but progress can be made.
If I right-click on the follow() call to open its definition, it eventually ends up calling set(ControlMode.Follower, id), which suggests that the javadoc is simply outdated.
Getting the same LED patterns on the primary motor and the follower also suggests that the following basically works. There must be some other, mechanical explanation for the different workload of the two motors if one gets way hotter than the other.
Can you please verify that the leader motor is heating up and not the follower?
I ran into a similar issue back in 2019 using SRXs, where a follower controller was heating up unreasonably and as a result being thermal throttled and the motor plugged into it would barely spin.
Follow mode definitely works for TalonFX. I just tested taking two falcons and having one follow the other using the .follow API.
The API documentation doesn’t cover TalonFX because it got missed when we added TalonFX support, I’ve added a tracker to update it in the next release.
If you’re having issues with follow mode, take a self-test snapshot of the follower while it’s running. It provides useful diagnostics at to what the follower is trying to do and what control mode it’s in. If you want, send us the snapshot and we’ll help you interpret what’s going on so you can get the issue fixed.
Intriguing. I’ve interested to know why two separate robots had the exact same issue and were fixed with the same solution. Maybe there was an issue with a config somewhere?
Unfortunately can’t do that, we’ve fixed the issue. If my above post were correct, we should be able to replicate the issue by using .follow(), but it multiple other post seem to contest this.
I also want to note your solution snippet won’t work as-is, because the follower motor is ID 87, when we only support IDs up to 62. In addition, the follower control mode is sufficient for same device type controllers such as Talons to Talons and Victors to Victors, but will not work for inter-device following such as Victors to Talons. Just something to keep in mind if you’re using the suggested workaround.
Yeah, that specific quite was more tongue-in-cheek. Guess I didn’t make that clear enough.
You’re right though, there are absolutely ways to improve documentation, and automation as you describe is certainly one. I love the WPILib docs for that reason
We had a falcon heat up with some testing this weekend - just on one side of our shooter. We would do some things that would seem to fix it, but eventually it’d seem to just start heating up again.
It turns out we had some regular hex spacers between a pulley and the motor and not the falcon spacers. This meant the spacer was running up against the boss of the motor and basically friction welding in place. In the process of doing something (like deciding to remove belt to the hood rollers) we would probably break it free and think the problem was identified until we friction welded it some more.
Not saying it’s the same thing, but definitely worth checking mechanical assembly to look for other reasons why one side might get hotter than the other.
We are also having a problem related to a motor in follower mode that “falls out” of that mode. We do not use the .Follow() method, but do use the .Set() method and designate the master CAN ID. The follower will work many times but occasionally drops itself into PercentOutput mode with no warning. This has been confirmed with Phoenix Tuner using the self-test feature in both successful and failed states. Calls to the motor object from the robot code report that it is still in follower mode (GetControlMode) when self-test reports percentOutput and it has not received any resets (HasResetOccurred). We have tried to reinitialize the follower for each command, and that also seems to have no effect or change the actual motor behavior.
Either we are somehow unintentionally knocking the follower back into percentOutput mode, or it’s unhappy with some condition and doing so on its own. We do switch modes on the master from percentOutput to MotionMagic and back again without re-programming the follower. We want it to follow the master in any mode. The difficult part is that it only fails a small fraction of the times we test.
There are no errors reported on the CAN bus, and we have a utilization that averages around 50-60% with occasional spikes to about 90%.
Does exactly the same thing according the Phoenix documentation, and we get INTO follower mode using it just fine–almost all of the time. I can change the call to do .Follow() to prove the point, but the question is why are we falling out of follower mode.
Unless you mean with every mode change on the master–which we can try.
I’m saying that if you just set a motor to follow the master, then no matter the control mode, it will follow the master. Which seems like what you were looking for.
I can categorically say that works with the java implementation, that’s what we do on our drivetrain (and have for years) and have never had a motor fall out of follower mode.
And we have had the same solid experience–never witnessed a problem using the same follower calls on our drivetrain. All falcons all the way around. Just seems to be on this climber follower motor, and we can’t pin it to hardware (yet). Just silently drops out of follower mode yet says it’s still in it when we make API calls to check if resets have occurred or what mode it thinks it’s in.
Weird. Looking at the Java .class file, the implementation between .set() and .follow() is very similar, but not quite identical, at least right up until the JNI calls. Looking at the decompilation of course, not the byte code.
Though if there were some implementation bug based on ControlMode, wouldn’t really make sense that your drivetrain doesn’t have motors following out of follower mode (that you have seen) but your climber does…unless it’s a product of the particular mode of operation you use to climb versus drive.
Would be really interesting to know if .follow() works in C++ but not your set method style. Like I said, the java implementations are close, but not identical. Maybe the C++ library has a minor deviation as well.
Will be trying .Follow() tomorrow. Along with re-commanding follower mode every time we change the master mode from MM to percentOutput. It would be nice to know the cause, since the only way to know it’s fixed is to reboot the robot about 100 times and hope that it statistically covered it.
“Following” up in case someone else hits this.
Using .Follow() and re-commanding follower mode did not help.
We started looking at how our CAN bus wiring was done, and we had a single CAN stub out to the intake to reduce risk if it got severed. The length had crept up to about 24" (instead of the 18" allowed by the spec). When we remove the intake from the CAN bus, the follower in question enters and stays in follower mode consistently. When the intake stub is reattached, the follower drops into percentOutput more than 50% of the time. Behaves the same on both our robots.
So this doesn’t appear to be a software/.follow() mode at all. It’s a CAN stub wiring problem that affected the Falcon. The follower (early to middle of the CAN chain), sees something it does not like and drops into percentOutput mode as reported by Phoenix Tuner. We did not find any way to detect it using the Falcon API or force it back into follower mode with repeated commands. The CAN errors reported by the DS also did not show any problems.
Would be nice to know if something we missed in the Phoenix API could be used to detect the real state. And also exactly what conditions would cause a Falcon follower to do this. Maybe CTRE can comment?
In the meantime we just switched the intake to PWM and will keep going. Seems to be working now. Thanks for the thoughts in trying to solve this.