Originally posted by scthor:
I was able to get my PID to give a pretty good output (oscillating less than 1%) but it's not centered at the setpoint,...
Let me guess. You got it to stop oscillating by setting your integral gain to a very low value (or zero) and setting your D gain to zero.
I write my own PID loops also. The native AB stuff just brings along too much baggage for my taste. But you do have to be careful what you do if you do it yourself. There is alot goi n on under the hood of the native PID instruction that you now need to babysit yourself.
First of all, feed forward. Feed forward terms are control outputs that are based on the setpoint and its derivatives. In your case, since the setpoint is not intended to be dynamic (changing continuously as a function of the process), you could get by with just setpoint feed forward. A PID filter is by definition a reactive construct. You need an error before it will generate a control output. If you know what control output is required based simply on your setpoint then you can generate that control output before the error even exists for the PID to react to. That is the idea behind feed forward terms. In your case there should be some known relationship between the setpoint value and the control output (drive velocity command). If you don't know that relationship now, figure it out. Generate that control output right away. Don't wait for the PID to come up with it.
As for your AOI, there are a couple things that stick out. The first is you are ding alot of data type mixing. Try and stay away from that. While the CLX native data type is a DINT, it will operate on floats almost as efficiently. When you mix data types the processor needs to perform data type promotion on the inferior data type, which takes time. More importantly, if you decided you needed a float anywhere in the calculation for precision needs you might as well stick with floats throughout. The case that immediately catches my eye is rung 6, the differential error calculation. You are subtracting the last error (a DINT) from the current error (a real). This will make the differential error signal REAL noisy. The LAST_ERROR tag should be a real.
Your integral limiting is likely causing you issues, especially if you have no setpoint feed forward. You clear your integral sum if you are not within 12% of your setpoint. So your proportional term needs to get you that close before you can even start providing integral action. I suspect your current tuning doesn't satisfy this requirement. You will likely want to change this so your integral can take control with a greater amount of error.
As was stated earlier your process probably doesn't need a differential gain term. many speed control processes like this don't because the tend to act like first order system at the responses we are trying to achieve and the actuators (in this case the drive/motor) are self-regulating. So unless you see something that points toward the need for a differential term, I would stay away from it.
Finally, how frequently are you calling the AOI? To make your control life easy you will want to call your loop at a rate 5 to 10 times faster than your process responds. So if it takes 5 seconds for your process to settle on a value you will want to call your control loop AT LEAST every 0.5 to 1 second. From the graph it looks to me like you are responding faster than that. There is no downside to calling the AOI more frequently than you need to unless you are trying to use the differential function or you call it so frequently that the input doesn't have a chance to update between calls or the motor hasn't received the new command yet. just make sure you are fast enough.
Keith