Writing my own PID

ASF

Lifetime Supporting Member
Join Date
Jun 2012
Location
Australia
Posts
3,921
I'm thinking of writing my own PID instruction for an AB PLC, because I'm constantly annoyed by how much I have to "help" the inbuilt PID instruction work the way I want. I know a few others have rolled their own PID instructions (and I'm sure Peter Natchwey could write one in his sleep) and am looking for (a) some general tips and things to watch out for from those who have done it before, and (b) some specific advice on calculating the derivative component.

Proportional gain is easy:
Code:
P = Error * Kp
Integral gain is also fairly straightforward. Assuming I make my units minutes/repeat, I perform the following calculation every loop update cycle:
Code:
I = Error * Loop Update Time in ms / 60000
...and add that to the P component.

The derivative I'm less certain of. For the purposes of this exercise, let's assume I'm using the derivative of the PV, not the error. My thinking is that every loop update cycle I perform the following calculations:
Code:
Rate of Change = (PV this scan - PV last scan) / Loop Update Time in s
...which gives me a rate of change in PV Units per second, and then:
Code:
D = Kd * Rate of Change
...which is then added to the P and I components.

Is it really as simple as that?
In this example, what are the units of my derivative gain? Seconds?

I appreciate any insights and assistance with the math - my career path did not include any university courses, just an electrical apprenticeship and a lot of learning-by-doing. So when it comes to the theoretical math behind the concept, I have a lot of gaps in my knowledge 👨🏻‍🏫
 
Just noted that my integral calculation should be:
Code:
I = Ki * Error * Loop Update Time in ms / 60000
...and that this should be added to the output each time the loop updates.
 
What exactly is wrong with an AB PID? For one, which PLC and which instruction?
The Logix platform, PID instruction. I've not played a lot with the PIDE because most of my customers require ladder logic.

There's just a lot of fiddling with things like scaling, when all of that could be done by looking at the scaling values I've already set up in the analog AOI's that represent my process variable. And things like having to turn on process variable tracking when I switch to manual to prevent integral windup - why should I have to do that manually? Surely the PID instruction should do that by itself? And then when I turn on PV tracking, it makes all my trends look funny, because my setpoint line follows the PV while the loop is in manual, instead of remaining constant. And the number of times I've had to uncheck and check that damn "PID Initialised" box...

I have no one application in mind, if I can get this working I'll use it across all types of loops.
 
Not all PIDs are the same. Some versions are better than others depending on the application.

There is nothing wrong with writing your own PID if the Rockwell PIDE doesn't do what you want. I have never been a fan of PIDs in any PLC. They don't handle the details well.

1. what is your application?
2. what doesn't the PIDE do that you want to do?

You probably know we sell motion controllers. The PID is probably the simplest/smallest part of the motion controller.
Writing a PID should be easy. The problem is writing the right one for your application and finding the correct controller gains.

I need to be awake to write a PID but I can tailor them to the application and computer the gains.

Over 20 years ago when we were writing code for the HYD02 and MO2AS we made changes the the existing cascaded PI code in those controller.
The PID part of the HYD02 and M02AS is only a few lines out of many hundreds.
 
Last edited:
Use velocity form of PID, so anti-windup is implicit in CV limits.

Cf. this link.
Why is that form of PID called the velocity form of PID?
Just trolling.

The "velocity", I prefer "incremental" form of PID is usually better as long as you are using the integrator gain.

drbitboy didn't mention that the "incremental" form of PID makes it easy to change the controller gains on-the-fly with out having a huge discontinuity in the control output.
 
There's really nothing that I want to do with this that the PID/PIDE can't do. I can get the results I want with those tools. It's just a matter of how much effort is involved in getting those results. I might compare it to taking the wheel off a car with a monkey wrench, vs a pneumatic rattle gun. The monkey wrench is certainly designed for that task, and can achieve it with nearly 100% success, but it's a whole lot easier to achieve the same thing with a rattle gun.

If I write my own PID AOI, I can integrate it with my existing analog AOI, by passing the process variable analog instruction into the PID instruction by reference, as an InOut parameter. That means I don't have to worry about writing code to tell the PID AOI to use the setpoint from my analog AOI. I don't have to worry about coding scaling parameters, because all of those are set in the analog AOI and I can just use those. I can implement various manual mode triggers into the PID AOI right off the bat, rather than manually coding each one (e.g. process variable sensor fault).

I want my PID to be a broadly generic PID for general process control like flow loops, temperature loops, pressure loops, etc. At this stage I'm not anticipating applying this to any motion control applications.

I have started work and come up with a few ideas for handling integration windup which I'll share once I fully flesh it out. I'm sure I haven't discovered any ideas that haven't been had before, I'm sure once I describe them drbitboy will come back with "oh yes that's the George Smith method published in 1995", to which Peter will reply "That method was developed way back in 1972 by Ronald Conker and is far inferior to the Fred Wenkel version published in 1981" :ROFLMAO:


Are either of you able to comment on my derivative calculation method?
 
Just noted that my integral calculation should be:
Code:
I = Ki * Error * Loop Update Time in ms / 60000
...and that this should be added to the output each time the loop updates.


You need to integrate the current error in the previous error, wikipedia has a pseudo code in this link.



Code:
previous_error := 0
integral := 0

loop:
    error := setpoint − measured_value
    proportional := error;
    integral := integral + error × dt
    derivative := (error − previous_error) / dt
    output := Kp × proportional + Ki × integral + Kd × derivative
    previous_error := error
    wait(dt)
    goto loop
However you will be disapointed by the result by your PID. This calculation is just the core, you definately want to implement some kind of anti-windup or you will have a big problem with stability.
Say that you want to control a flow with a valve. If demand is 0 but there is a slight leakage then the integration part will wind up (or down in that case) causing a greater delay when demand is rising.
 

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