rodrigo_rolle
Hi,

I tried to set up a PID block but I think I was unable to declare the variables properly. I'm attaching the screenshot. Could someone please explain the right form to declare these variables or send an example?

Thanks!
att.png
Quote 0 0
thiagoralves
PIDs are complicated things. You must know exactly what you are doing with the KP, TR and TD variables, or you will easily saturate the output. 1.2 for KP and 22 for TR seems a lot to me. Also, your schematic has some errors that will prevent it from working:

1) You must add a time constant to the CYCLE input. This time constant needs to match the interval in which your program is called. You can check that in Config0->Res0->Tasks. For example, if your program is called every 50ms, it means that it will execute the PID block once every 50ms. Therefore, the CYCLE time constant will inform the PID block that it needs to perform the calculations for a 50ms time slot.

2) Your in and out variables are associated with digital I/O (%IX0.0 and %QX0.0). This doesn't make sense on the PID calculations because these values can only assume 0 or 1. Your input and output need to be an analog value (for example, the value of a temperature sensor, and the speed of the fan).

I attached here a little PID block I created for a temperature control system. The program controls the flow of water to refrigerate an equipment based on the temperature measured in the equipment. So, the higher the temperature, the bigger the flow of water.

Now, just a little dissertation about the PID block variables, that I see that causes a lot of confusion:

AUTO: Selects between automatic or manual operation. On automatic, the XOUT value is calculated according to the PID parameters. On manual, the XOUT value is equal to X0. If AUTO = TRUE, then the mode is automatic. If AUTO = FALSE, then the mode is manual.

PV: Process Variable, the value you want to control

SP: Setpoint. The target for your process variable

X0: Default value when AUTO = FALSE.

KP: Proportional constant

TR: Integral constant

TD: Derivative constant

CYCLE: Cycle time constant as explained above

XOUT: PID output
Quote 0 0
rodrigo_rolle
I got these PID parameters from a Simulink example that I didn't run yet. I'll try to use this OpenPLC PID block instead of Simulink's one. My main problem was that I didn't know how to set up the block, so your example helped a lot! Now I'm gonna check if I got the correct parameters by running the simulations and analyzing the differences between the blocks. Thank you very much! [smile]
Quote 0 0
rodrigo_rolle
Hello again, Thiago. Let me ask you another question. What kind of PID algorithm (parallel, series, ideal) does this block implement? I implemented a simple simulation on Simulink using a damped second order continous system and a parallel PID block whose parameters are: Kp = 2; Ki = 2 and Kd = 0.1.
Initially I calculated the parameters for the PLCOpen PID block as Kp = 2; Tr = 1.0 (Kp/Ki) and Td = 0.05 (Kd/Kp) but the system became unstable in the simulation.
I changed some things from that example that you attached. I didn't understand why the setpoint was declared as an output (%QW1) so I changed it to a memory word. In a future moment I intend to use the setpoint as an input word, in order to set the value directly from Simulink and send this value to the PID block using an UDP port. Is this possible?

I'm attaching the screenshot of the project I'm running. Thanks again for your support!


test.png 
Quote 0 0
thiagoralves
The setpoint was previously on a %QWx location because I was using Modbus to write to it. However, since %MDx locations are also writable by Modbus, it is actually better to have it on a %MDx location. You also can have it on a %IWx location and get the value from Simulink, using the information from the SimLink github:  https://github.com/thiagoralves/SimLink/tree/master/Example

The implementation of the PID block is exactly as defined in the IEC 61131-3 standard. I have it attached here, just search for PID and you will find the code for the block.
Quote 1 0
rodrigo_rolle
I checked this documentation but still coudn't solve my problem. I think the main problem in my case is the value scales I'm using. 2-byte messages can enumerate numbers from 0 to 65536, right? So I'm trying to understand the relationship between the constant values that I provide via Simulink constants (via UDP send) and the output from the OpenPLC.
I set up a simple simulation (picture attached), sending a constant value to %IW0, converting from uint to real and then real to uint (only for "processing" something in the PLC side) and getting the output to %QW0, but the output I get from the UDP Receive block is always zero. I followed your templates while building both Simulink and PLCOpen programs. Any thoughts on what I'm doing wrong? Thanks in advance.

ct.png 
Quote 0 0
thiagoralves
I wonder if your interface.cfg file for SimLink is correctly addressing the data types. Can you paste it here please? Also, check using a Modbus program, like Radzio Modbus, if OpenPLC is receiving this value correctly. You can check the %IW0 input at Input Status address 0, and the %QW0 output at the Holding Registers address 0.
Quote 0 0
rodrigo_rolle
Here is the interface.cfg and the parameters of the Simulink blocks:
2.png 
I also tried to use Radzio (you mentioned it in other posts so I decided to try it too). I can't see any changes on the input status when I change the constant value that is sent to the PLC, the values shown are always the same.
3.png 
Quote 0 0
thiagoralves
Your configuration seems to be correct, except for Radzio. I'm sorry, I said it wrong, you should look for Input Registers, not Input Status. Input Status displays %IX0.n variables (digital input). The variable you want to see is %IW0 (analog input), so you should select Input Register on Radzio. On Display options, leave Decimal checked and uncheck ASCII display Enable. Lets see if OpenPLC is getting the constant value from Simulink. Sometimes, if the communication is not working, you may need to just restart SimLink with everything running so that it can see both Simulink and OpenPLC and make the connection. Then you will see the constant value popping up on Radzio.
Quote 0 0
rodrigo_rolle
Still coudn't get the value. For any value I set on Simulink I get the same results on Radzio:
4.png 
I also tried to restart SimLink during the simulation but also didn't work. I usually open OpenPLC first, then run the simulation and after that I start SimLink. Yesterday I ran another example using only discrete in/out data and I was able to check the bits changing on Radzio. I got in trouble when I started trying to use analog data.
Quote 0 0
thiagoralves
There might be some problem with SimLink code. I will check it next week and let you know
Quote 0 0
thiagoralves
I modified the Hello World example with an analog input and it seems to be working fine:
Capture8.png 

The Hello World PLC program was modified just to add a analog variable at %IW0. I'm not doing anything with the variable on the program, just declaring it in the variables box. Also, I modified the interface.cfg file to reflect this new input:


num_stations = "1"
comm_delay = "100"
# ------------
#   SIMULINK
# ------------
simulink.ip = "localhost"
# ------------
#  STATION 0
# ------------
station0.ip = "localhost"
station0.add(analog_in) = "10003"
station0.add(digital_in) = "10001"
station0.add(digital_out) = "10002"
Quote 1 0
rodrigo_rolle
Great! It worked for me too. I did the same procedure you described and then I found out that the problem in my simulation was that uint16 conversion block that I was using before the UDP Send block. I removed it and everything worked properly. Now I will review my PID simulation scheme. Thank you very much!
Quote 0 0
rodrigo_rolle
Hello again! I've been testing this PID block with a simple transfer function (a damped second order system) in Simulink. Now I know that data is OK, but there's a weird situation here. Everytime I test, no matter what KP, TR and TD parameters I use, I always get the same kind of response... For instance, in this simulation I used Kp=0.2, Tr=2.0 and Td=0.0:
5 atual.png 
First of all: my setpoint is 4, but as soon as the communication starts, the PLC sends much higher values (60000-plus) to the output.

I tried Kp=0.2, Tr=0.5 and Td=0.0:
6.png 
Notice that the start is very similar and after that first step the response is almost random. Then I tried very high values (Kp=8, Tr=8 and Td=2):
3 (valores altos).png

It looks like nothing changes even when I use very different parameters, the response is not even close to the setpoint. The system is stable, notice that it stabilizes around the PLC response "steps" but I can't control it with the PID block. Any suggestions on how to proceed?

Here is my simulation scheme:
scheme.png
Quote 0 0
thiagoralves
That's weird. One thing that comes to my mind now is timing. Make sure that you have the correct time on everything. For example, if your simulation is expecting some response in the microsecond order, your probably won't be able to control it using OpenPLC and Simulink. The PLC response will just appear to be too slow, and in blocks. The fastest I could get using OpenPLC simulink drivers is around 1ms, and even then you must have a really decent hardware to do it. I would recommend to start with something slow, like 100ms scan time.

Adjust your scan time on your OpenPLC program config (config0->res0->task interval) to 100ms. After that, in your PID block, put a constant T#100ms in the CYCLE parameter to make sure it matches your scan time. Then configure the sample rate (comm_delay) to be slightly faster than that. This sample rate is the rate in which Simulink polls OpenPLC for data. If this rate is slower than your scan rate, your PLC program will be off sync with the simulation. Put something like 50 or 30 (the value is in milliseconds). Also, make sure that your UDP Send and Receive blocks on Simulink match that rate. Then try your simulation again
Quote 1 0