Our team is running 4x Neo 550s on our shooter this year which are all, ideally, independently controlled. We decided to run the velocity PID loop onboard the SparkMax and are experiencing odd behaviour:
The graph shows the onboard controller for two of our SparkMaxes targeting 4000rpm solely with a feedfoward of 0.0001. As you can see the behaviour is inconsistent from run to run.
The behaviour becomes more sporadic as more SparkMaxes are ran; however, one SparkMax is always performing as expected. We observed this to be true regardless of which SparkMaxes are ran:
The default filtering settings on the spark max are bad which results in adding so much latency to the velocity measurements that the system is uncontrollable. The filtering can be adjusted to decrease the latency at the cost of more noise which is at least controllable but still terrible.
Thanks for your reply. I’m not sure this is the problem since the behaviour isn’t constant but only occurs when multiple motors are running. Would the velocity readings have an effect in this situation? I can try to play around with the encoder settings the next time I have access to the robot.
So, I’m running SparkMax SparkFlex and NEO Vortex’s on our shooter. Running a velocity PID onboard the SparkMax SparkFlex. Works reasonably well until we noticed something the last few days as we brought more of the Robot online.
We saw that as the battery voltage dropped we could no longer achieve our RPM targets.
Our issue seems to be that we are using a FF value in our PID along with values for P and D.
Turns out the SparkMax/Flex PID’s FF is reliant on Battery Voltage. So as the battery voltage decreases the voltage contributed by the FF also decreases.
So, when our air compressor turns on or other motors turn on then our shooter’s RPM will decrease. Just normal battery rundown does this.
Today I’ll try to redo the shooter’s programming to avoid this.
The 2 things to try are apparently enable voltage compensation on the SparkMax/Flex. This limits the max volts the motor will be driven but the FF term is now tied to the voltage compensation setting and not bus voltage. Not sure if this is true since REV documentation is so terrible in this regard.
The other solution I’ve seen is to not have a FF in the PID but to characterize the shooter motors using SYSID then use WPILib FeedForward classes to calculate the FF in every periodic loop and add this to the SparkMax/Flex PID as an Arbitrary FF value.
Voltage normalization allows you to account for battery sag as you drag down the battery voltage. This will help with the FF changing based on battery voltage. However - your P term should also be accounting for error if your speed isn’t where it needs to be. If it isn’t, then your P term probably isn’t high enough.
Just a feedforward term is not enough to do speed control. After all - that’s just open loop application of battery voltage. Your feedback (PID) closes the loop to eliminate the error.
This isn’t really true, either. Feedforward-only can work just fine for flywheels in many applications, as evidenced by the large number of teams reporting success with PID control onboard the Spark for the NEO with default settings.
Thanks. When we were in the build stage I had a mock up of the shooter.
So my test bed was just two shooter motors, nothing else.
I knew my target was 2000 RPM so all I had done so far was find a FF that got me close and set a P value that got me closer but didn’t over shoot or oscillate.
Doing that I got within 50 RPM of target and that has been good enough for a shooter that performs very well.
It wasn’t until this week when we were bringing everything together we noticed this RPM issue with the shooter.
Also, I mis-spoke, out shooter has SparkFlex’s so much better velocity control than the SparkMax. (I’ll edit my original post).
Not if it’s still controlling a NEO rather than a NEO Vortex - and the default filter settings for the Flex/Vortex are still quite bad for flywheels.
There are some easy-to-understand principles but no by-the-numbers “standard”.
You’re trading off between signal delay and noise. The total signal delay is about half of the filter’s total width (so, a 164ms filter - the default - introduces about 82 ms of delay in the signal).
If the signal delay is not smaller than the system’s time constant (you can find this w/ ReCalc or SysId), then you’ll have problems applying meaningful corrective feedback to your system. The max stable feedback gain shrinks exponentially as your signal delay grows past the system time constant.
The Flex/Vortex are currently having a bit of a bumpy rollout, and I’d avoid them this year on the principle of not trusting first-year motors/motor controllers. But with proper configuration the Vortex should be more than capable of doing really good velocity control on a flywheel. The default filter settings are poor, but they’re only defaults.
The MAX, too, is perfectly capable of “really good” velocity control on a flywheel - but you have to either use an external encoder or design your flywheel to be heavy enough to be controlled by the hall effect sensor.
In any case, you will need to adjust the filter settings. This isn’t exactly rocket science - it’s two API calls. Prior to Phoenix 6, you had to do this for CTRE devices as well.
Hello from Calgary. We find ourselves tackling the same issue. Our current setup involves utilizing SparkMax controllers, as Flex/Vortex is not within our budget.
We are open to any additional suggestions or strategies to alleviate this issue. It’s noteworthy that the problem manifests only when there are multiple motors in play. Your insights and guidance on potential solutions would be greatly appreciated.
Wish I was the OP so I could flag your reply as a “Solution”.
Turned on Voltage Comp on the shooter, re-tuned all the PID/FF values and we are good to go.
Way better than previous. We are hitting RPM targets spot on even with a battery that reads in the 11.5 volt range