How to control shooter rpm with Sparkmax?

So my team is using a neo motor with a sparkmax on the shooter, and I need to have a reliable way of setting the velocity. I tried using a bang bang controller in the code, but it quickly overshot by 2000 of whatever velocity units the sparkmax prints by default. I also attempted using a PID controller (wpilib), but the motor reverses when the velocity overshoots, which results in fairly rapid vibrations, with still a lot of overshoot.
What do you recommend? It would probably be best to use the SparkMax built in PID controller, but how do I get that to not have the same reversing issue that WPILib’s did? How do I tune my gains?

Thanks a lot for your help!

2 Likes

I would use the SparkMaxPIDController class. One of the students on the team used that for the climber, and I don’t recall him having the reversing issue you mentioned.

1 Like

The sparkmax PID class is designed to work with both position and velocity. Do you know if he was using it for position or velocity?

The integrated NEO encoder has an unavoidable measurement delay of ~110ms on velocity readings. This affects internal velocity loops, as well.

Use an external encoder if you want effective feedback on a NEO-powered flywheel.

3 Likes

What type of encoder do you recommend?

Have them set the output range with setOutputRange. This way the flywheel can only go forward.

2 Likes

For a flywheel, it really doesn’t matter - anything that won’t oversaturate whatever counter you plug it into (either the RIO or the SparkMax limit switch pins). When in doubt, read the specs.

2 Likes

Easiest if you have a hex shaft would be the rev through bore encoder

2 Likes

Here’s an example for a 2-wheel shooter if it helps. Doesn’t overshoot, reaches speed quickly and holds it. Your P Gain and F Gain will differ based on setup and weight.
It doesn’t allow reverse. Min 0/max 1
It’s LabVIEW but ports pretty directly to C/Java, since it’s primarily library calls.

3 Likes

Here is my team’s Shooter code from last year. Github
kFF (Feed Forward) works great for this use case because it rapidly increases the velocity of the motor when the current velocity is far away from the target velocity. kP (Proportional) is the reason the velocity will overshoot.

The PID coefficients I used were.
kP = 0.0004;
kI = 0;
kD = 0;
kIz = 0;
kFF = 0.00017; // .000015
kMaxOutput = 1;
kMinOutput = -1;
I hope that helps!

2 Likes

sorry, I accidentally posted as a reply. (:

Do you know if the NEO integrated encoder works well for just position control?

Yes, it is fine for position control.

2 Likes

Here are the PIDF Constants we used for our SparkMAX Shooter for Infinite Recharge using the integrated encoder.

IIRC, Like said above, That FeedForward, even as small as it is, helped a ton with the same issue of overshooting and reversing. Though we did also set the Min PID Output to 0.0 so it couldn’t reverse anyway, but even before we did that. The FF Helped a bunch.

and you can see our Launcher Subsystem this was part of here, but be warned they changed a few things in the REV API between then and now, so its not 1:1 on the types and methods anymore.

1 Like

Thank you everyone for your help! We set up the built in SparkMaxPIDController. The built in NEO encoder worked very well, and a combination of feedforward and min output of 0, made overshooting very minimal, error pretty small, and recovery time pretty fast. We ended up using only feedforward (constant was .00017 for both motors).
Thank you again for all your help! Good luck with your robots!

If you’re using only feedforward, the NEO encoder is really not doing anything at all (except reporting the estimated speed).

What do you mean it’s not doing anything? Isn’t the point of the encoder to report estimated speed into some sort of controller that controls voltage to the shooter?

Feedforward control is open-loop control. It does not rely on any sort of measurement.

Then how does it get the speed to the right number every time?

Because steady-state speed is a well-behaved linear function of rotor speed (this is what our feedforward equation is derived from…). The point of feedback is to keep you at that speed regardless of external disturbances.

If you are using a feedforward-only loop at a constant setpoint, that is equivalent to just giving the motor some constant voltage output that you know results in a speed near your setpoint.

We know for a fact that the NEO encoder is not very useful for feedback control, because we know how much measurement delay it has and can simulate the effect that measurement delay has on the maximal stable feedback gain. @calcmogul can run you through the math if you’re interested.

1 Like