Industry Online Support
Technical Forum
6/12/2012 12:32 PM  
Posts: 3 Rating: (0) 
Hello everyone, I have an S71200 1214C and have implemented an MPC control scheme for a plant in an SCL FC block. I have the following problem: the cycle time for running this code is tremendous, in the order of 4600 ms. The code isn't very complex and i use a Global DB for it, but in involves accessing a matrix of 400x400 which I stored as an array of 1600 Real values. Also, when i store the program withthis DB it takes up 71% of the work memory and if I set the option to load it only in load memory, the program cannot acces the values from it. My questions are the following: 1. Is there a faster way to make matrixvector calculations, via FB with dedicated memory or something else? 2. Can i store the required arrays in load memory and acces them from the program? 3. Has anyone tried to implement such an algorithm or a more complex one on this type of PLC, can the S71200 handle it? Help would be appreciated. The code for the FC SCL block is the following: FUNCTION "PCDM" : Void { S7_Optimized_Access := 'TRUE' } VERSION : 0.1 VAR_INPUT "x_0" : Array [0..3] of Real; "H" : Array [0..1599] of Real; "u" : Array [0..39] of Real; "L" : Array [0..1] of Real; "q" : Array [0..39] of Real; "u_max" : Array [0..39] of Real; "u_min" : Array [0..39] of Real; "K" : Array [0..7] of Real; "gamma_0" : Array [0..1] of Real; "iter_max" : Int; END_VAR VAR_OUTPUT "Gamma1" : Real; "Gamma2" : Real; "u_new" : Array [0..39] of Real; END_VAR VAR_TEMP "i" : Int; "j" : Int; "grad" : Array [0..79] of Real; "v" : Array [0..79] of Real; "k_1" : Int; END_VAR BEGIN FOR #i := 0 TO 39 DO #u_new[#i]:=#u[#i]; END_FOR; //compute the gradient FOR #k_1:=0 TO #iter_max DO FOR #i := 0 TO 39 DO #grad[#i]:=0.0; FOR #j := 0 TO 39 DO #grad[#i]:=#grad[#i]+2*(#H[#i*40+#j]*#u_new[#j]); END_FOR; #grad[#i]:=#grad[#i]+#q[#i]; END_FOR; //Compute v for subsystem 1 FOR #i := 0 TO 19 DO #v[#i]:=#u_new[#i](1/#L[0])*#grad[#i]; END_FOR; //Compute v for subsystem 2 FOR #i := 20 TO 39 DO #v[#i]:=#u_new[#i](1/#L[1])*#grad[#i]; END_FOR; //Project v on box constraints FOR #i := 0 TO 39 DO IF #v[#i]<#u_min[#i] THEN #v[#i]:=#u_min[#i]; END_IF; IF #v[#i]>#u_max[#i] THEN #v[#i]:=#u_max[#i]; END_IF; END_FOR; //Compute new u via convex combination FOR #i := 0 TO 39 DO #u_new[#i]:=0.5*#u_new[#i]+0.5*#v[#i]; END_FOR; END_FOR; //Select plant inputs #Gamma1:=#u_new[0]+#gamma_0[0]; #Gamma2:=#u_new[1]+#gamma_0[1]; //Update u for the following sampling time FOR #i := 0 TO 37 DO #u_new[#i]:=#u_new[#i+2]; END_FOR; #u_new[38]:=0.0; #u_new[39]:=0.0; FOR #j := 0 TO 3 DO #u_new[38]:=#u_new[38]+#K[0+#j]*#x_0[#j]; END_FOR; FOR #j := 0 TO 3 DO #u_new[39]:=#u_new[39]+#K[1+#j]*#x_0[#j]; END_FOR; END_FUNCTION 
6/12/2012 3:47 PM  
Joined: 7/7/2010 Last visit: 6/17/2021 Posts: 10855 Rating: (1784)

You need to understand something about the S71200  it is the current intro level PLC. It is not the fastest, and neither is that multilooped algorithm. Find a way to process once per scan instead of all at once. Are you generating all 400x400 pieces of data each scan? If so, I'd suggest a 300 level PLC to process, or push the data to a PC, have the PC crunch the data and push it back to the PLC. Looping and loops within loops is very time consuming in a logic scanning device, resulting in a somewhat unpredictable process as one scan might be 5 ms, and the next might be 4600 ms making your output state change very unreliable and inconsistent. One thing to check is that you are using FW2.2 and Portal V11 SP2 Update 3. That combination is supposed to fix a lot ofquirks in speed and SCL code efficiency. My strong suggestion however is to unravel your loops, divide up the math so you can do it a piece at a time over many scans of your logic, and at the end, put it all together. Since you want your scan time consistent, disable your big function, and see what the scan time is for that. The difference is what your block needs to run. What target scan time do you need? Do the math and find out how many pieces you need. Let's assume it's a very small number, then you need to break it down into 100 smaller chunks. Process a 4x4 each scan, make it a different 4x4 each scan, and after 100 scans, you have your answer after summarizing it. It might be something like : if firstscan then scan_count := 0; all_done := false; end_if; if all_done then scan_count = 0; all_done := false; end_if; scan_count := scan_count + 1; if scan_count := 1 then //do innermost loop A here elseif scan_count := 2 then //do innermost loop B here elseif scan_count := 3 then ... elseif scan_count := 100 then // do summary math here end_if;  note this may be unacceptable as well... Maybe change your algorithm to do the math as the data is generated, similar to how you would do a running average of 100 values by coming up with the simpler math each scan rather than wait for the 100 values, store all 100 values, then process all 100 at the end of each subsequent scan. If this is an odd concept, take a look at a good "numerical methods" reference textbook to solve this problem in a PLC rather than the straightforward simple but slow approach. 
science guy 

This contribution was helpful to1 thankful Users 
Follow us on