Rajesh Anand
Hello, I wanted to use PID control for a process. The function block for PID doesn't have the upper limit, lower limit of final output of PID controller. 

Can I simply add that inside the Function block or I have to add the limits outside the PID function block?
Quote 0 0
thiagoralves
You can do either way. If you want to modify the current implementation of the built-in PID block, just create another function block from the current code and add your modifications. This is the current code:
(* Following taken directly from the IEC 61131.3 draft standard *)
(*
 * An IEC 61131-3 IL and ST compiler.
 *
 * Based on the
 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
 *
 *)
 FUNCTION_BLOCK PID
   VAR_INPUT
     AUTO : BOOL ;        (* 0 - manual , 1 - automatic *)
     PV : REAL ;          (* Process variable *)
     SP : REAL ;          (* Set point *)
     X0 : REAL ;          (* Manual output adjustment - *)
                          (* Typically from transfer station *)
     KP : REAL ;          (* Proportionality constant *)
     TR : REAL ;          (* Reset time *)
     TD : REAL ;          (* Derivative time constant *)
     CYCLE : TIME ;       (* Sampling period *)
   END_VAR
   VAR_OUTPUT 
     XOUT : REAL;
   END_VAR
   VAR 
     ERROR : REAL ;        (* PV - SP *)
     ITERM : INTEGRAL ;    (* FB for integral term  *)
     DTERM : DERIVATIVE ;  (* FB for derivative term *)
   END_VAR
   ERROR := PV - SP ;
   (*** Adjust ITERM so that XOUT := X0 when AUTO = 0 ***)
   ITERM (RUN := AUTO, R1 := NOT AUTO, XIN := ERROR,
          X0 := TR * (X0 - ERROR), CYCLE := CYCLE) ;
   DTERM (RUN := AUTO, XIN := ERROR, CYCLE := CYCLE) ;
   XOUT := KP * (ERROR + ITERM.XOUT/TR + DTERM.XOUT*TD) ;
 END_FUNCTION_BLOCK

The PID block uses INTEGRAL and DERIVATIVE function blocks to calculate the TR and TD terms. Just for reference, here are the codes for those blocks:
(* Following taken directly from the IEC 61131.3 draft standard *)
(*
 * An IEC 61131-3 IL and ST compiler.
 *
 * Based on the
 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
 *
 *)
 FUNCTION_BLOCK INTEGRAL
   VAR_INPUT
     RUN : BOOL ;       (* 1 = integrate, 0 = hold *)
     R1 : BOOL ;        (* Overriding reset        *)
     XIN : REAL ;       (* Input variable          *)
     X0  : REAL ;       (* Initial value           *)
     CYCLE : TIME ;     (* Sampling period         *)
   END_VAR
   VAR_OUTPUT
     Q : BOOL ;         (* NOT R1                  *)
     XOUT : REAL ;      (* Integrated output       *)
   END_VAR
   Q := NOT R1 ;
   IF R1 THEN XOUT := X0 ;
   ELSIF RUN THEN XOUT := XOUT + XIN * TIME_TO_REAL(CYCLE);
   END_IF ;
 END_FUNCTION_BLOCK


(* Following taken directly from the IEC 61131.3 draft standard *)
(*
 * An IEC 61131-3 IL and ST compiler.
 *
 * Based on the
 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
 *
 *)

 FUNCTION_BLOCK DERIVATIVE
   VAR_INPUT
     RUN : BOOL ;          (* 0 = reset                  *)
     XIN : REAL ;          (* Input to be differentiated *)
     CYCLE : TIME ;        (* Sampling period            *)
   END_VAR
   VAR_OUTPUT
     XOUT : REAL ;         (* Differentiated output      *)
   END_VAR
   VAR X1, X2, X3 : REAL ; END_VAR
   IF RUN THEN
      XOUT := (3.0 * (XIN - X3) + X1 - X2)
              / (10.0 * TIME_TO_REAL(CYCLE)) ;
      X3 := X2 ; X2 := X1 ; X1 := XIN ;
   ELSE XOUT := 0.0; X1 := XIN ; X2 := XIN ; X3 := XIN ;
   END_IF ;
 END_FUNCTION_BLOCK
Quote 0 0
thiagoralves
Additionally, you can check OSCAT Library here: https://openplc.discussion.community/post/oscat-basic-333-oscat-building-openplc-10284818?pid=1310418069

There are several different PID blocks available in there.
Quote 0 0
Rajesh Anand
Thank you for the links and information
Quote 0 0
Rajesh Anand
Hello, I have a simple doubt when declaring the variables to use in the OpenPLC editor.

1) If I want to use the equivalent of the Global variable in the declaration, should I use just the Local class? (My application requires 2 AI and 1 AO in unipi, so if I assign two variables as input class and one variable as output class, I'm not able to enter the address of the input ( %IW0.0, %IW0.1) and output (QW0.0). Any suggestions on that?
2) How about if I want to use the equivalent of the VAR in the OpenPLC editor, can I just use Local for that too?
Quote 0 0
Rajesh Anand
I'm running a piece of code, I have all values in real data type and when I get input in word data type, I convert and do the operations in real and finally I convert them to word for output. But im getting certain errors related to mismatch of data (for real data type operations):

Quote:
Start build in E:\NYU\GA\openPLC editor\TEP_U\build
Generating SoftPLC IEC-61131 ST/IL/SFC code...
Compiling IEC Program into C code...
"E:\NYU\GA\openPLC editor\OpenPLC Editor v1.0 - Windows\OpenPLC Editor\matiec\iec2c.exe" -f -l -p -I "E:\NYU\GA\openPLC editor\OpenPLC Editor v1.0 - Windows\OpenPLC Editor\matiec\lib" -T "E:\NYU\GA\openPLC editor\TEP_U\build" "E:\NYU\GA\openPLC editor\TEP_U\build\plc.st"
exited with status 1 (pid 20368)
E:\NYU\GA\openPLC editor\TEP_U\build\plc.st:129-26..129-31: error: Initial value has incompatible data type.
In section: PROGRAM TEP_U
0129: Cycle_Time : TIME := 0.0005;
E:\NYU\GA\openPLC editor\TEP_U\build\plc.st:140-19..140-42: error: Data type mismatch for '*' expression.
In section: PROGRAM TEP_U
0140: SIM_Xmeas07 := (1000*(SIM_Xmeas07_level)) + 2000;
E:\NYU\GA\openPLC editor\TEP_U\build\plc.st:141-23..141-42: error: Data type mismatch for '*' expression.
In section: PROGRAM TEP_U
0141: SIM_Xmeas10 := 0.5*(3*SIM_Xmeas10_level - 0.5);
E:\NYU\GA\openPLC editor\TEP_U\build\plc.st:143-24..143-38: error: Data type mismatch for '/' expression.
In section: PROGRAM TEP_U
0143: Purge_Output_Volt := Purge_Output/45;
4 error(s) found. Bailing out!

Error : IEC to C compiler returned 1
PLC code generation failed !


Any suggestions on what could be done about it?
Quote 0 0
thiagoralves
Check your expressions. IEC 61131-3 is very picky about data types (strongly typed language). Keep in mind that “1000” is automatically declared by the compiler as a static integer. Therefore, if you do “A_REAL_NUMBER * 1000” you will get data type mismatch. You need to use 1000.0.


About your last question, variable categories (input, output, etc) only make sense for function and function blocks. These categories determine if the variable will show up on the block as an input, output, or both, when you drop the block in your main program. They have nothing to do with the physical pins of the PLC. 
Quote 0 0
Rajesh Anand
Thank you. It worked. I have one more error 

Quote:
exited with status 1 (pid 1192)
E:\NYU\GA\openPLC editor\TEP_U\build\plc.st:129-26..129-31: error: Initial value has incompatible data type.
In section: PROGRAM TEP_U
0129: Cycle_Time : TIME := 0.0005;
1 error(s) found. Bailing out!


I'm running Hardware-in-Loop with the process working in Simulink and controller works in PLC. I have declared cycle time as real as I need to match the time with which PLC runs with Simulink. I have used Cycle_time = 0.0005 for PID controllers that I run in PLC as I need to use 0.0005 as my simulation time in simulink. But the PID control block is expecting Time data type for cycle time.

If I use declare cycle time as Real, compiler shows error in PID blocks I used whereas if I declare cycle time as time data type, compiler shows error as mentioned above (initial value has incompatible data type). Any suggestions on what could be done about this?

Thanks.
Quote 0 0
thiagoralves
REAL and TIME are different data types. The PID block expects the cycle time to be of type TIME. Time in IEC 61131-3 is initialized like T#5ms or T#15s, etc. Keep in mind that for the PID block to work, the cycle time input must be equal the cycle time of your program task (by default it is T#20ms)
Quote 1 0
Rajesh Anand
Hello. I have a small doubt.

I'm sending a constant 3V input to the Unipi (I can see the equivalent 19662 in Radzio Modbus simulator). When I write a program to just display the input to output, I'm not getting the required voltage (3V, in this case) but I can see 19662 in Radzio simulator. I checked across AO and GND as they have mentioned AOV is for external input. Is there a possibility that the output port got fried or I'm checking it wrong?
Quote 0 0
thiagoralves
Check UniPi documentation. I believe you need to supply some voltage to the analog output circuitry for it to work.
Quote 1 0
Rajesh Anand
Yeah. I was able to find about the Unipi Analog Output pin. I have a small query, I downloaded the OSCAT library for using PID Function block, but how do I import and use them in my program?

I tried to copy+paste the entire library in the project folder where I'm working on. But I couldnt see the functional blocks added. Is there any way to import and use the library. I need to use only the (23. Control modules) folder of the OSCAT Library.

Thanks in advance.
Quote 0 0
thiagoralves
You need to copy-paste each block you want to use in your project. Just open two editor windows, one with your project and the other with the library. Then copy and paste the blocks that you want to use. Keep in mind that some blocks have dependencies, so you might need to copy other blocks as well to which the block you need depends
Quote 1 0
Rajesh Anand
Hello, when I try to use a PID block along with additional ones (for extended functionality), I'm getting the following error.  

error: Function invocation in ST code is not allowed outside an expression. To allow this non-standard syntax, activate the appropriate command-line option.
In section: PROGRAM TEP
0459: CTRL_IN(
0460: SET_POINT := Pressure_SetPoint,
0461: ACTUAL := SIM_Xmeas07,
0462: NOISE := 0.0,
0463: OUT => Press_Out
0464: );

The one which I tried to code is according to the one mentioned in the picture. Take inputs through CTRL_IN block, feed the output of it into the PID block, the output of PID is fed into CTRL_OUT block. I get the above error when I try to run the code. Any suggestions on what could be the issue?

Thanks.
Quote 0 0
thiagoralves
Hard to know the issue without seeing you code
Quote 0 0