Writing my own PID

I rolled my own PID once, because I needed a PID which was based on conveyor ticks and not seconds.

One hard thing I noticed, was dealing with bouncing off the walls:

Say for example you are running steady at 99%CV.
You increase your error by 0.1, and (assuming no filter, guessing at your derivative gain, and also guessing your loop update rate) your derivative term causes a 10% increase in CV. Now the next scan, your error has not changed, so you decrease your CV by 10%. But... your PID clipped to 100% in the previous scan, so you are now running steadily at 90%CV! A similar effect can be seen by the proportional term, if your PV has any ripple.
For me the solution was to insist on a filter to the PV.

Also, use LREALs if available.

You could start with the source code for OSCAT BASIC FT_PID (or FT_PIDW or FT_PIDWL) instruction, which are written in ST, but maybe that overcomplicates it, as they put I and D in seperate Function Blocks.

Here is some code to get you started.

Code:
IF NOT Initialized THEN
    Initialized := TRUE;
    E_nminus2 := E;
    E_nminus1 := E;
END_IF

E := SP-PV;
IF Auto THEN
    CV := CV + Kp * (E - E_nminus1) 
             + Ki * (E)
             + Kd * (E - 2.0 * E_nminus1 + E_nminus2);
 END_IF


 CV := MIN(100.0, MAX(0,CV));

E_nminus2 := E_nminus1;
E_nminus1 := E;

according to our friends at www.dictionary.com, velocity can also mean more generally 'the rate of speed at which something happens'.

So because the velocity PID calculation calculates firstly the required change in CV, velocity is as good a term to describe it, as rose is for describing what an elevator just did.
 
Last edited:
What does the velocity form of PID have to do with velocity?



NO! What does the velocity form of PID have to do with velocity?
If you, or any body else, can't answer that then there is something wrong with term "velocity PID"


NO ;)!

I answered that. It is speed, sure, not velocity, but it is close enough.
 
Can't you locate build in AB PID and your manipulations for PID inside of AOI?


Haven't used AB plcs so not sure of this but thinking that it would be stupid if that is not possible.
 
NO ;)!
I answered that. It is speed, sure, not velocity, but it is close enough.
What does the speed have to do with it?


@AstralIan, what about the sampling time? The PID should never be running at 99% at steady state. There was a sizing problem.


Velocity implies a direction, speed does not.
Technically, velocity is a vector and speed is a scalar.
I know we are all sloppy and us the two interchangeably.



REALs should be good enough. There isn't enough resolution from the feedback or the output.


@ojz0r, I don't like the wait(dt). The routine should be in an interrupt. The wait(dt) will not return exactly when dt has expired. It will return sometime afterwards. Therefore most of the time you loops will be running slower than desired.


Anti windup code is simple if you THINK about it. Most people get this wrong. Also, if you are using feed forwards the integrator should never wind up.


The concept of writing ONE PID to rule them all is not good.
The should be variations. For instance some PID have derivative gains that only act on the rate of change in the PV. This removes the "derivative kick". It is also possible to have the proportional gain act on only the change in the PV too so that only the integrator gain is acting on the error.


In what I do, there must be a second derivative gain too.


The different forms of PID are good for different applications.
 
While I was programming PLCs I always used my own regulation algorithms. The reason is that when I started, in the late 1980s, PLCs had no PID instruction or floating point calculations.

The first PID algorithm worked only with integers.

The last one I used, using floating point, was not PID but only ID :p. It works great for regulating temperature regulation, also kiln pressure, and even conveyor travel distance

The regulation is totally floating, simplifying, if E0 and E1 are the last and the previous error, the algorithm varies the output as a function of E0 * IntegralFactor plus the square root of (E0 -E1) * DerivativeFactor
 
Velocity implies a direction, speed does not.
Technically, velocity is a vector and speed is a scalar.

Stated more accurately, speed is a magnitude scalar and cannot be negative; in this case, the "velocity" vector is one-dimensional.

So the "velocity" form of the PID equation expresses a finite difference wrt time (for the proportional term only, obviously).

If you do not see the semantic correlation between velocity and finite-difference-wrt-time, then there is no hope for you.
 
@ojz0r, I don't like the wait(dt). The routine should be in an interrupt. The wait(dt) will not return exactly when dt has expired. It will return sometime afterwards. Therefore most of the time you loops will be running slower than desired.


I fully agree. I copied that snipet from the wikipedia link in the post.
As it is labled as psudo code it is probably there for pseudo purpose instead of writing the less intuitive "interrupt(dt): ...."


The biggest reason for my post was to make the OP aware that he didnt do an integration in the "I" part of his code.
 
Thanks for the advice, everyone. Here's what I've got so far.

I pass an analog AOI as an inOut parameter. This gives me my process variable, my setpoint, and the Min and Max range of the process variable. I have the programmer specify the Min and Max range of the Controller Output.

I then calculate the error in PV units, and convert the error to a "raw" value where 0...1 = 0...100% of the PV range. So if the PV min/max scale is e.g. 50-100L/min, and my error is 5L/min, my error is 10% of the PV range, and my "raw" error is 0.1

I calculate "raw" values for my PV and my Bias in the same way, so that PVRaw 0...1 = 0...100% of the PV input range, and BiasRaw 0...1 = 0.100% of the controller output range.

My P value is kP * RawError
My I value is kI * RawError * LoopUpdateTime(ms) / 60000
My D value is kD * RateOfChange, where RateOfChange = (RawPV - RawPVLastScan) / 1000

Because I use the raw values in my calculations, P, I and D values are also "raw".

Now I move on to managing integral windup.


I have a "Cumulative_I" value. Each time my PID is executed, I add my new raw I value to the "Cumulative_I" value.

Next, I add together my raw P, D and Bias values. This should add up to a number between 0 and 1. I therefore determine that my "Cumulative_I" value cannot be greater than (1 - P - D - Bias), because that would cause my CO to exceed 100%. It likewise cannot be less than -1*(P + D + Bias), because this would cause my CO to fall below 0%. If the Cumulative_I value exceeds this limit, I clamp it.

Finally, I add together my P, Cumulative_I, D and Bias values. These are all raw values so I will get a value between 0 and 1. This value is scaled according to the CO Min and CO Max values input by the programmer, and becomes my CO.

I have added some more features, but I'll make a second post for them - I'd be interested to get some feedback on the "bare bones" of this PID attempt.
 
Last edited:
Maybe throw Bias into Cumulative_I (or vice versa), because they are the same thing. I.e. when transitioning from Manual to Auto, assign Cumulative_I = CV and get rid of Bias (or assign Bias = CV and get rid of Cumulative_I).


Also, you may need to clamp CV e.g. for the case where (P+D) is outside the range of [0:1], although the overage or underage could be carried in the Bias.
 

Similar Topics

I have 3 parameters for a product: Diameter Lengte Hoek (corner) all reals... I need some batching system with a batchlist. Something...
Replies
8
Views
2,743
Hi, I'm having an issue in crimson 3.0 when I create a programme using a case statement referencing a fault word that each bit needs to change the...
Replies
5
Views
262
Hello all, I'm currently working on a servo motor linear positioning system (ball screw). I'm all set up regarding communication between my HMI...
Replies
1
Views
101
Hello All: I have a Windows 10 PC running a FTView ME Station 10.00. I have a .mer file version 6.00. It has been running well on it for a long...
Replies
1
Views
174
My R55 Ingersollrand is tripping on motor overload and im falling to see the trip history it is writing Acquarring texts
Replies
0
Views
137
Back
Top Bottom