PSA: High-resolution encoder noise w/ WPILib Encoder class

After some more poring through characterization data and liaising w/ teams, it’s become apparent that some teams are getting swamped by noise on high-resolution encoders when used with the WPILib Encoder class.

It is important to note that the WPILib Encoder class measures rate by time per period, rather than pulses per time. Thus, an extremely high-resolution encoder (such as the REV through-bore encoder, which comes in at a whopping 2048 periods per revolution) will tend to have extremely noisy velocity readings when used with the default settings, due to running up against the resolution of the FPGA clock.

Fortunately, this is easily solvable:

If you are using a high-resolution encoder and the WPILib Encoder class, and want to avoid velocity measurement noise, be certain to set EncodingType to k1x and increase samplesToAverage (a value of 5-10 seems to work acceptably for a 2048-ppr encoder).

This is not an issue for position measurements.

Addendum: there are still a bunch of other not-as-of-yet-understood sources of encoder noise popping up in test data, particularly with magnetic encoders. If you’ve had extremely noisy frc-characterization readings, please message me with your diagnostic plots and a description of your robot setup to help us determine root causes!

12 Likes

Thank you so much this explains the throughbore noise we have been seeing on our shooter. Will test this tonight!

I couldn’t find anything on DecodingType. Do you mean EncodingType?

So code now looks like:

private final Encoder m_shooterEncoder =
      new Encoder(ShooterConstants.kEncoderPorts[0], ShooterConstants.kEncoderPorts[1],
                  ShooterConstants.kEncoderReversed, CounterBase.EncodingType.k1X);
.....
m_shooterEncoder.setSamplesToAverage(5);

Yes, I meant EncodingType.

Here is the result when I added these 2 lines to the characterization project:

It still doesn’t look right to me but significantly less noisy

How fast are you spinning the encoder? If this is on a shooter, you may want to increase samplesToAverage by a factor of 5 or so (the value I quoted was determined on a drive axle).

It can spin up to ~9k RPM. 775pro 2:1

Is samplesToAverage at 25 going to be enough then? 9k RPM is significantly more than 5 times higher than a drivetrain RPM.

Ah, if you’ve geared it up then you’ll need to increase it even more. Try 50.

Am I saying it backwards? We have geared the 775pro down so instead of spinning at 18k it is spinning at 9k

Oh, I figured you were using a Neo or a Falcon. Regardless, for a speed that high, start at 50.

1 Like

What matters is the slowest rate that you want to shoot at, the cycles per rev of the encoder and your PID loop rate. You want the samples to average to be less the the number of cycles counted in one loop. If your doing just p and f control I would want samples to average to be less then half the number of cycles per loop. If you’re using d, then you want to minimize phase lag and I’d shoot for less then 10% of the cycles counted per loop.

1 Like

Okay so lets say the lowest rate we want to shoot at is 5k RPM. 2048 cycles per rev and the loop rate is 20ms right?

So 5kRPMx2048 = 10240000 cycles per minute / 60 for seconds and by 50 for 20ms “loops” comes out to 3413 cycles per 20ms loop. So it looks like either way we can average more if needed?

I was planning on just P&F. Do you recommend adding D? Advantages/Disadvantages for this application? (I know what D does generally)

D is useless for a velocity control loop with a stationary setpoint.

1 Like

I started at 50 and went up to (after much debugging not realizing there was a limit) 127.

This still resulted in an odd characterization:

Am I doing something else wrong? I am running the first 2 tests do like 40 seconds eachand the second two for like 20 seconds each

Doubt you’re doing anything wrong. Unsure if the residual noise is still discretization error from the timer (unlikely, imo) or something else. You can probably drive it down to levels where it won’t ruin the kA by increasing the accel window.

What units are the accel window size anyway?

Samples.

Increasing it by how much? I don’t need exact numbers here but want to at least get a ballpark

You can pretty much “go ham” with it. Try doubling it repeatedly until the results seem reasonable.

2 Likes

This seems to be more reasonable:

When I use these numbers in our Shooter subsystem it calculates a feedforward of like 140. Which when put into a setVoltage constantly rails it