Structured Text Rookie Help Request

Join Date
Apr 2016
Location
Appleton WI
Posts
30
Hey guys, was hoping someone could give me a bit of advice here in a couple spots. I'll start off with my dumb code and explain after

MNETC_Index_A := 1700;
Real_Index_A := 0;
For MNETC_Index_A := 1700 to 1742 by 2 do ;
FOR Real_Index_A := 0 to 21 do ;
COP (MNETC.DATA.ReadData[MNETC_Index_A],REALDATA[Real_Index_A],2) ;
END_FOR ;
END_FOR ;






COP (MNETC.DATA.ReadData[1700],REALDATA[0],2) ;
COP (MNETC.DATA.ReadData[1702],REALDATA[1],2) ;
COP (MNETC.DATA.ReadData[1704],REALDATA[2],2) ;
COP (MNETC.DATA.ReadData[1706],REALDATA[3],2) ;
COP (MNETC.DATA.ReadData[1708],REALDATA[4],2) ;
COP (MNETC.DATA.ReadData[1710],REALDATA[5],2) ;
COP (MNETC.DATA.ReadData[1712],REALDATA[6],2) ;
COP (MNETC.DATA.ReadData[1714],REALDATA[7],2) ;
COP (MNETC.DATA.ReadData[1716],REALDATA[8],2) ;
COP (MNETC.DATA.ReadData[1718],REALDATA[9],2) ;
COP (MNETC.DATA.ReadData[1720],REALDATA[10],2) ;
COP (MNETC.DATA.ReadData[1722],REALDATA[11],2) ;
COP (MNETC.DATA.ReadData[1724],REALDATA[12],2) ;
COP (MNETC.DATA.ReadData[1726],REALDATA[13],2) ;
COP (MNETC.DATA.ReadData[1728],REALDATA[14],2) ;
COP (MNETC.DATA.ReadData[1730],REALDATA[15],2) ;
COP (MNETC.DATA.ReadData[1732],REALDATA[16],2) ;
COP (MNETC.DATA.ReadData[1734],REALDATA[17],2) ;
COP (MNETC.DATA.ReadData[1736],REALDATA[18],2) ;
COP (MNETC.DATA.ReadData[1738],REALDATA[19],2) ;
COP (MNETC.DATA.ReadData[1740],REALDATA[20],2) ;
COP (MNETC.DATA.ReadData[1742],REALDATA[21],2) ;
//END_FOR ;


PQM_735.r_735G3.IA := REALDATA[0] /100.0;
PQM_735.r_735G3.IB := REALDATA[1] /100.0;
PQM_735.r_735G3.IC := REALDATA[2] /100.0;
PQM_735.r_735G3.IN := REALDATA[3] /100.0;
PQM_735.r_735G3.VA := REALDATA[4] /100.0;
PQM_735.r_735G3.VB := REALDATA[5] /100.0;
PQM_735.r_735G3.VC := REALDATA[6] /100.0;
PQM_735.r_735G3.VAB := REALDATA[7] /100.0;
PQM_735.r_735G3.VBC := REALDATA[8] /100.0;
PQM_735.r_735G3.VCA := REALDATA[9] /100.0;
PQM_735.r_735G3.W3 := REALDATA[10] /100.0;
PQM_735.r_735G3.U3 := REALDATA[11] /100.0;
PQM_735.r_735G3.Q3 := REALDATA[12] /100.0;
PQM_735.r_735G3.WA := REALDATA[13] /100.0;
PQM_735.r_735G3.WB := REALDATA[14] /100.0;
PQM_735.r_735G3.WC := REALDATA[15] /100.0;
PQM_735.r_735G3.UA := REALDATA[16] /100.0;
PQM_735.r_735G3.UB := REALDATA[17] /100.0;
PQM_735.r_735G3.UC := REALDATA[18] /100.0;
PQM_735.r_735G3.QA := REALDATA[19] /100.0;
PQM_735.r_735G3.QB := REALDATA[20] /100.0;
PQM_735.r_735G3.QC := REALDATA[21] /100.0;



Basically I'm turning modbus integers into a dint, then dumping them into a REAL, scaling appropriately, and putting them into a UDT. The bottom two large fields of COP and REALDATA scaling are the brute force method that works fine. Of course, I have to do this 23 times, so I'm hoping for something a bit more elegant.

I'm fairly certain the top pair of for loops is not going to work correctly as I have a loop that will go to MNETC_Index of 1500 and then put that into every Real_Index from 0-21, then go to 1502 and again go through the 0-21 index again, on and on and on.

Any advice to clean that up? I have always seemed to confuse myself when I end up nesting loop inside of loop and usually retreat to a brute force method.

The lowest section I'll alter as time goes on, the only variable there that will change is the r_735G3, and then the realdata 0-21 will become 50-71, 100-121, and so on. I'm pretty sure I could just do a COP or CPS of length 22 from REALDATA[0] into the individual r_735xx UDT's, as they are the same size and datatype.
 
try this


Code:
MNETC_Index_A  := 1700 ;
 Real_Index_A   := 0 ;


 For MNETC_Index_A := 1700 to 1742 by 2 do ;


     COP (MNETC.DATA.ReadData[MNETC_Index_A],REALDATA[Real_Index_A],2) ;
     Real_Index_A := Real_Index_A + 1 ;


 END_FOR ;
There is no need for the inner loop; the indices of the arrays MNETC.Data.ReadData and REALDATA need to advance in parallel and synchronously; not orthogonally and asychronously.


In fact, I think that the outer loop can be eliminated as well, and replaced by a single line of code:

Code:
COP (MNETC.DATA.ReadData[1700],REALDATA[0],42)
But that may or may not be the case, depending how the memory in MNETC.DATA is arranged; certainly my first example, or summat close, should work.



In the code in the OP the inner loop COPied a single pair of elements from the MNETC.DATA.ReadData array to a each and every READDATA array element. When the outer loop is done running inner loop the last time, the last pair of MNETC elements, 1742 and 1743, will have been copied to every REALDATA element.
 
I am not sure if COP size is correct. If REALDATA is DINT, then size must be 1, because COP size is always in Destination elements.

But correct solution is already posted:
COP (MNETC.DATA.ReadData[1700],REALDATA[0],42)
 
I am not sure if COP size is correct. If REALDATA is DINT, then size must be 1, because COP size is always in Destination elements.

But correct solution is already posted:
COP (MNETC.DATA.ReadData[1700],REALDATA[0],42)




d'Oh, nice catch! Assuming Logix: .Length is destination count cf. image below from https://literature.rockwellautomati...{"num":1884,"gen":0},{"name":"XYZ"},52,359,0]







and the final number should probably be 22 (if not 42;)), to copy 44 16-bit words into 22 DINTs.

xxx.png
 
Last edited:
d'Oh, nice catch! Assuming Logix: .Length is destination count cf. image below from https://literature.rockwellautomati...{"num":1884,"gen":0},{"name":"XYZ"},52,359,0]







and the final number should probably be 22 (if not 42;)), to copy 44 16-bit words into 22 DINTs.

You appear to be correct, set to 22 it is working out of just the single line. The 42 stemmed from it being the lower of the two INTS in the 22nd pair, 42 and 43, length two.

I was pleasantly surprised I didnt have to do the pair copies individually to put the data into the dint array. I'll have to keep that in mind.

Saves me a lot of time in the text editor, thanks. If i could trim down the scaling lines I'd really be cooking with gas.
 
Since you are using Modbus, make sure that initial INT array already used byte swap.
This is because Modbus uses different byte order.
Some Modbus clients will return RAW data, some will do correct byte swap.
Rockwell Modbus TCP AOI will do byte swap correctly.
 
Since you are using Modbus, make sure that initial INT array already used byte swap.
This is because Modbus uses different byte order.
Some Modbus clients will return RAW data, some will do correct byte swap.
Rockwell Modbus TCP AOI will do byte swap correctly.

I was able to catch that pretty quickly. Prosoft MVI56E-MNETC card. Ended up turning off the Enron Daniels thing for float, turning on word swap for each client command and mapping into the DINT with the ST above and things came up smooth. First time working with the Prosoft cards, and I have to say I like it a lot. Great manuals. Modbus is a little annoying because its so slow, but for the basic metering we're doing it serves its purpose.

I'm just glad to finally be back on an AB processor versus the GE **** these people cheap out on usually.
 
...If i could trim down the scaling lines I'd really be cooking with gas.




Well, you could go back to the single outer loop and do this:

Code:
J := 0;

FOR I2:=1700 TO 1742 BY 2 DO ;
   
    COP(WordArray[I2],RealArray(J),2);

    RealArray(J) := RealArray(J) / 100.0;

    J := J + 1;

END_FOR;
But that only saves 22 [/100]s in the other code. The really sweet thing to do would be to have all the reals in the UDT lined up in the same order as the word array and somehow be able to COP and divide by 100 into there just a few lines as well, but I don't think that will ever work in a PLC environment: you wisely traded that for the less error-prone access to dot notation (.IA, .IB, etc.).



Side issue: have you considered COP vs. CPW or CPS?
 
Last edited:
Well, you could go back to the single outer loop and do this:

Code:
J := 0;

FOR I2:=1700 TO 1742 BY 2 DO ;
   
    COP(WordArray[I2],RealArray(J),2);

    RealArray(J) := RealArray(J) / 100.0;

    J := J + 1;

END_FOR;
But that only saves 22 [/100]s in the other code. The really sweet thing to do would be to have all the reals in the UDT lined up in the same order as the word array and somehow be able to COP and divide by 100 into there just a few lines as well, but I don't think that will ever work in a PLC environment: you wisely traded that for the less error-prone access to dot notation (.IA, .IB, etc.).



Side issue: have you considered COP vs. CPW or CPS?
Yeah, my background is more fanuc robots, but I got a position at a place here doing primarily PLC / HMI development, so while I had a good base knowledge working with AB stuff, and did some smaller machines in the past, I'm no expert with regards to best practices. However, this project I have so many repetitive cells and repetitive drives that I've built out everything with UDTs and parameter files so my logic is fairly repetative find/replace and the HMI is primarily parameter list based, so once one component display works, they all work (in theory)

This place has not had a proper controls engineer in some time; the lead EE that normally takes care of coding was going to do this six racks, redundant PLC, communicate to multiple generators, and about 50 schweitzer relays, and do it primarily alias based (yikes).

I'm not familiar with CPW. I CPS might be more appropriate here normally, but I'm just reading a fairly slow updating group of modbus relays, so I guess I didn't worry about it too much.
 

Similar Topics

I have an expression in a structured text routine of a Logix controller that looks more or less like the following: ResultInteger := Integer1 *...
Replies
13
Views
374
Good evening. I display the step number of a SFC on a display. Sometimes, on a trip, it goes quickly through many steps and I need to prove to...
Replies
1
Views
113
I am trying to set up a piece of equipment with a Horner HE-X4R. I'd like to use structured text and so far I'm just trying to get a basic On/off...
Replies
0
Views
67
Good morning. I'm doing a rehab and I need to recycle some part of the old code that won't change and that I need. This is a calculation that...
Replies
22
Views
1,342
I'm writing some structured text that's handling a data structure that comes from a PC. The PC structure is in the "new" LREAL 64-bit floating...
Replies
3
Views
481
Back
Top Bottom