PID Algorithm Acting Weird

I am building a machine that feeds material into a cutter using a servo motor. The servo motor is a hybrid stepper with encoder feedback. This may be overkill for the application but I already had it. I am using the accelStepper library to run the stepper using the .runSpeed() method (quasi speed control). the motor is connected to a couple of drive wheels via a 2:1 timing belt. I have a quadrature encoder running on the actual material as it feeds through the machine to get an accurate position. I choose to NOT get the position from the motor due to slippage between the drive wheels and the material. I am running the PIDv2 library for position control.

For the most part, it is working quite well and tracks a position input. However, I started to notice that as I feed the material through the machine I get a steady-state error between the desired and actual position. At first, I thought I need more Pi term to force it to zero but the controller is actually trying to force the material to this offset position. I can try to force the material to the desired position but then the controller just pushes back.

I tried doing dynamic tuning (conservative and aggressive tuning terms

Processing: 2021-11-03
), tried changing the tuning, checked the encoder feedback, etc with no luck.

Any thoughts?

After further testing, the machine actually goes to the just takes a while. Why would the PID algorithm push back against me helping it get to the set point?

It sounds like a small coding mistake. Check how/where You add the correction.
Somehow this sounds wrong. If the PID constantly misses the target something ought to be adjusted before PID is called.
Any help?

Running PID and adding corrections later must be wrong....

I am manually adding the correction using my hand to force the material to where I want it to be bu the machine just pushes back to the offset position while it casually takes its time getting to the target.

Sounds like at least one of the tuning parameters is very far off, or a sign is wrong. The very slow creep back to the setpoint might be the integral term.

I would print out all the error terms for a variety of input conditions and try to decide if the values are sensible.

Keep in mind that the PID loop timing usually has to be constant and correct, and printing can upset that.

The I term is the only one that corrects offset. It also increases instability though, so be careful increasing it. Sometimes integral-windup can be a problem, especially for large step-changes in setpoint. Hint "integral windup PID" is a good search term.

Are you using proportional on error or proportional on measurement? Check the blog here and the response images ... proportional on error has quicker response but more overshoot. Therefore, it would be good to know how much overshoot your system can tolerate ... the more overshoot, the quicker the PID system will be able to reach setpoint (by carefully adjusting Ki).

I would start by adjusting Kp so that the overshoot is about 1/2 of what can be tolerated, then carefully adjust Ki to speed up the correction of offset error.

If windup is an issue, then perhaps give QuickPID a try. I plan on testing and implementing a back calculation approach for anti-windup sometime in the future, but am far to busy at this time to do any significant upgrades.

Oh, forgot to mention that the most important PID "tuning parameter" is actually the sample time. SetSampleTime(); defaults to 100ms. You may find that speeding this up to 50, 25 or even as fast as 10ms might make a significant difference and improvement. You'll definitely need to re-adjust Kp and Ki as they'll be in a lower range for suitable tuning performance.

1 Like

Thanks for the good tips. I have gotten closer to a solution, indirectly by way of the timing. I had a Serial.println in the main loop spitting out debug values. When I commented it out things started running a lot better. I assume that was just slowing the whole process down and causing issues with the tuning.