Spark PID Controller, set tolerance?

in order to control an arm we decided to use the built in pid controller inside the spark max with a modified version of the code you can find here but we are searching for a way to set some sort of tolerance to the pid so it accepts some sort of position without always wanting to correct i searched everywere and i can’t seem to find anything

i think the “smart motion” mode is what you’re looking for.

I would avoid using smart motion if possible, and use a traditional PID loop instead. Because it is a velocity controller, not a position controller, it cannot correct for error. More info can be found on it here: Is Smart Motion ever going to be fixed?

4 Likes

Use a motion profile (like TrapezoidProfile in WPILib) and send the output to a Spark Max in regular position PID mode.

As previously stated DO NOT USE “SmartMotion”.

3 Likes

You should be able to tune your PID in such a way that it doesn’t oscillate wildly when it’s near the setpoint, and still has enough power to move the mechanism.

Might want to try tuning again. Zero out everything, and set P to something small like 0.01. Then you can start doubling P until the oscillation gets too high, and add some D. Generally you don’t need I.

Another thing to consider is, is there a lot of backlash in the system? That is, a lot of play between the output shaft and the motor shaft?

That can make PID more difficult to tune.

Unfortunately, REV doesn’t have a set tolerance method.

My biggest issue with setTolerence (even on CTRE or anywhere it’s implemented) is that when you use it, as soon as you get inside the tolerance band, control just stops. It ends up being that while the mechanism was controlled to the set point, it really always stops at the tolerance point. You really want a deadband around the point, like control to 1* accuracy, but restart the PID control at 3-5* again.

Our arms were really bad at this last year, since gravity always acted on them, they were effectively always at the bottom tolerance point, not at the setpoint.

I noticed that nearly fatal flaw of PID implementations. Your solution is better.

CTRE’s fix for the tolerance generally of no use was to remove it this year. Nobody missed it and they didn’t think it useful.

I suspect tolerance properly implemented could be of some use in some situations to mitigate backlash and not have the motor always hunting for the setpoint but it’s hard to know beforehand when it helps and when it hurts.

I decided to try not to fuss about the motor always chattering a little at the setpoint.

Im not sure what you mean by that

Not sure what part of the statement is unclear. Backlash or play or possibly a more technical term of the concept we are talking about is Hysteresis?

If you impose a force at one end of your mechanism, the other end doesn’t move until all of the little gaps in the machine are pressed together in the direction of the force. Grab the arm and wiggle it but the motor doesn’t move - that’s play. Or start the motor but the arm doesn’t move for an instant while all the gaps are “tightened”.

This lack of immediate action caused by parts not touching tightly is hard to account for in PID controls. (Delays for other reasons may not be hard to account for.)

Another way to get around this is to use the built-in NEO encoder for PID feedback instead of an external encoder. This prevents the Spark’s PID algorithm from seeing any backlash in the first place. This would require some zeroing process (either manual before turning on the robot, or some automated sequence that the robot executes), since the NEO encoder is a relative encoder, not absolute.

Delays for any reason are hard to account for, no matter what sort of feedback algorithm you’re running. Information becomes exponentially less-useful as it ages.

There’s usually no reason to have a “tolerance” for a linear controller - the output should smoothly fall to zero at your equilibrium point. If you need the nonlinearity introduced by the tolerance for good convergence, consider adding some other linearization term instead of deadbanding the controller.

You are right, of course, and to quote from a book “Time delays have always been among the most difficult problems encountered in process control.”

I avoided the absolute always statement for people who were going to point out some special control case, for example, “We know it takes 2 seconds to extend our arm so we put a waitSeconds(2.) in our command - easy!” And yes, we know that’s not a particularly robust control strategy especially if there are no sensors to indicate completion.

1 Like