We currently have the Through Bore encoders on our swerve drive and we were wondering if there is a way to zero our internal encoders using the Through Bore ones in absolute mode or is it not possible for them to persist their count after power-cycle?
If I understand what you are trying to do, it is a bit complicated but possible. I think you are trying to use an incremental encoder built into a brushless motor to measure your swerve’s position, but you need to know where it is when it starts up and you have a Through Bore Encoder mounted either directly to, or 1:1, with the wheel itself.
First off, you might want to consider not doing this. If your motor for turning your module is a NEO or a Neo550, you can simply plug the Through Bore into the top port of the SparkMax using the Absolute Encoder Adapter. You can then read that value directly from the SparkMax and use it as an input on the SparkMax’s internal PID controller. This will all take place in “absolute space” and work very well.
If you can’t do that, perhaps because you are using a Falcon as your turn motor, you can do something nearly as good by plugging the Through Bore into the Rio and doing the PID there. This will still operate in “absolute space” but isn’t quite as good, as I’ve found the PIDs running in the Rio tend to not be quite as responsive and accurate as when running on the speed controller (presumably because of the faster feedback loop on the speed controller)
The third option, which is what I think you are trying to do, is possible but complicated and comes with a drawback. But here’s the approach. At startup time, get the absolute angle from the Through Bore, and then convert that into “relative space”. By that, I mean “how much must the turn motor have moved 0 in absolute space to get here.” This will involve multiplying the absolute number by your gear ratio, and converting to the right units for your turn motor’s built-in encoder. Next, take that number and call the appropriate “setPosition” method on the motor’s encoder so its relative position is in line with its absolute position. Lastly, as you target different angles during the game, you need to do that same conversion from absolute space to relative space to use as a PID input. But you need to be more careful now. Because let’s say that your module has made some full rotations in one direction. You need to add those full rotations into your PID set point, otherwise you’d find that it wants to “unwind” itself.
Lastly, a word of caution about this last approach: if your motor browns out or trips a breaker in the middle of a game, this gets all messed up for the rest of the game. That’s because your motor will reset its “initial” position when it comes back on, and you won’t have redone the the initial syncing described above.
What motors are you using on your swerve modules?
We are using Falcon 500s. We are currently trying to read the absolute position using the DutyCycleEncoder in WPILIb, but the absolute position doesn’t persist after a power cycle.
Currently, we are doing the third option: we have Falcon 500s and are using the DutyCycleEncoder to read the Through Bore Encoder and calculate the initial rotation of the wheel that way. The issue we are currently running into is that the reported value from the Through Bore encoder seems random every power cycle. Do you have any experience with this type of encoder?
You can record the offset of the Rev encoder as a constant in your code. We have a class for the through bore that scales it and holds an offset. RevThroughBoreEncoder.java
Does the .getDistance()
method on the DutyCycleEncoder report an absolute value that persists through power cycles?
We aren’t relying on the encoder persisting values, we store the offset of the encoder in our constantans .
No it does not, as you could conclude from reading the API here: DutyCycleEncoder (WPILib API 2023.4.2)
No, you must use getAbsolutePosition()