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?
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.
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.
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.
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!
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.
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!
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?
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.