Beginning coder here! We are trying to figure out how to use PID control to control an arm. Our arm uses a REV Through Bore encoder in Absolute encoder mode, with 2 SparkMAX driven NEOs (facing opposite directions), with one in follower mode (inverted true). The lead motor has the sensor connected through a breakout board. We do have the physical chains for those motors removed, until we can test it for direction and speed (don’t want to tear things up).
We basically copied the REV Smart Motion example into our Arm subsystem, but whenever we try and change the setPoint in SmartDashboard (or ShuffleBoard) with the robot enabled, the code crashes and disables the robot.
As long as we don’t try to change those values, everything else on the robot works (drive base, intake and shooter motors). Using simple motor.set() methods, we did get the specified motors moving (verified that they moved the same way), and that doesn’t crash the code. We also aren’t sure of the best way to code setPoints to specific buttons on our second controller. We have tried looking at the various examples (WPILib and REV) but can’t seem to localize where our mistakes are. Code below:
Worst case scenario, we will code some simple if-thens to move our arm to certain encoder points (or do a manual joystick controlled arm, with encoder stop values, ew), but we were hoping to learn some basic PID control this year for smoother and more exact control.
Are you changing your P value on the smart dash? Or is it still 0 when you run setPostion()?
We have a similar Arm subsystem. Still a few bits that are work-in-progress, but we were able move to positions on an absolute encoder. Here’s the code.
We were leaving the P value at 0 initially; just trying to get movement on the motors (so that we could reconnect the arm) before we started tuning the PID values. Should we put it at an arbitrarily small value initially? What I’ve read seems to say you should start with it at 0 when tuning.
We tried using the example code from REV for SparkMAX closedloop position control, and were having similar issues (code immediately crashing/disabling the robot) whenever we tried to edit the setPoint in the SmartDashboard (or even when we pass a value using setReference()). Which is why we tried the SmartMotion, just to see if we could get the motors to spin at all. It isn’t a hardware issue (we think), because a simple motor.set() worked to spin the motors.
Will keep trying to rework it (another complete rewrite!), probably using the code from @DrewTheRat, but that will have to wait until tomorrow.
Those are the only Warnings. No errors or faults. The robot will be enabled, then we change the value on the Smart Dashboard, hit enter, and the light stops, the robot is disabled. I have 4-5 logs with the same (or very similar) warnings, because we would clear the Driver Station log, and try it again, with the same result.
I think one test we ran was commenting out all of the Smart Dashboard parts, and it didn’t crash, but we also didn’t have the ability to change the SetPoint (or PID and other values), since that is how the example REV code has it set to adjust the setpoint, I’m assuming for tuning purposes.
Thank you @DrewTheRat ! Your code made much more sense to me than the SpakMAX example codes. Still not sure what wasn’t working on my previous subsystem, I just created a new one modeled on yours, and I got it working. Now to just set the controller buttons and tune the PID values, and find our specific setpoints.
If you are running SmartDashboard on same laptop as driver station, pressing enter will disable the robot. Change a value in SmartDashboard and then click outside the text box. That should cause the value to be read/updated.
Generally I agree, and FWIW, CTRE’s aren’t much better. That said, REV’s MAXSwerve-Java-Template is a very good sample project. Their MAXSwerveModule class is a more useful example of both position and velocity closed loop control. We patterned our Arm code off the steering motor PID controller.
If you want to have functionality similar to Smart Motion is supposed to do (but doesn’t), and still take advantage of doing PID onboard the Spark, you could calculate a trapezoid motion profile on the RIO, then pipe the output of that to the Spark Max in regular position PID mode.
We’ve done the work of implementing this in our wrapper library PurpleLib.