Logix 5000 Question: Using Index in For loop for indirect addressing of an [array]

Liqa Macode

Member
Join Date
Aug 2011
Location
In a box
Posts
6
I've got a rung that uses the first pass bit to initiate a For argument.

In the Routine named 'Alarm' I have something like this...





S:FS ___________________FOR____
------||--------| FOR |--------
| |Routine Name: Alarm | |
| |Index: Fortag | |
| | 0 | |
| |Initial Value: 0 | |
| |Terminal Size: 10 | |
| |Step Size: 1 | |
| |_________________________| |
| |
| |
| __________________MID____ |
| |Middle String | |
|----|Source: default_string |----|
| '10000' |
|Qty: 4 |
| |
|Start: 2 |
| |
|Dest: Initstring[Fortag]|
| ?? |
|________________________|





There are actually ten different strings, each containing ten different array elements (eg. Initstring[0] - Initstring[9]). I'm wanting to initially populate all one hundred array elements with the string '0000'.
I checked with Rockwell to see if it'd work this way, or if I'd need to put the Mid commands in a different ladder, and also since the For command is looping 10 times before continuing on, will it populate the variables, or just the final element in each of the ten arrays? Tech support said to test it out and see what happens.
It'd be easy to change down the road, but I'd like to get it right the first time.
 
Last edited:
Welcome to the forum.

That will call the subroutine Alarm ten consecutive times, incrementing the Index variable each time it runs Alarm. Then it will execute the MID instruction once.

To use the ladder FOR instruction you need to have a subroutine for the FOR instruction to loop through. You can alternatively build your own FOR loop using the JMP/LBL instructions and your own index.
 
Probably faster to do the following

Making some A$$umptions about your data types
Datatype InitString String[10]

Set the first String using your favorite method

Use COP InitString[0], InitString[1],9
This copies the first string to the rest of the array

If you are using a UDT array then this will also work - Initialise the first UDT then perform the COPy
 
For this kind of looping, I like to use Structured Text. I know no everyone has this oprtion. But use the right tool for the right job.
 
For this kind of looping, I like to use Structured Text. I know no everyone has this oprtion. But use the right tool for the right job.
That particular tool carries a hefty price tag.

Can't you just put a COP in the loop to tighten it up? Only requires one string constant? Const_Array_CLEAR="0000" then FOR, MOV with indirect destination, NEXT.

I don't like the MID function inside the loop like that.

I wonder, does each repeat of the loop with the S:FS bit affect scan time? I know instructions have false execution times, but I would think that the loop never refers that far back in the instruction list to make a difference if you used a copy of that system bit instead.

Are you wanting to preserve some of the characters? and only put characters into specific positions in the strings?

EDIT: Doh! Didn't see MichaelG had it whooped:
http://www.plctalk.net/qanda/showpost.php?p=438186&postcount=3
 
Last edited:
Thanks for the feedback... I looked closely at the COP instruction, cause I use them as part of a history.
I could be misunderstanding...

If I had stringa as an array of 10 elements stringa[0] to stringa[9], and I did a:
cop stringa[0], stringa[1], length 9... it would effectively copy the string contained in stringa[0] to stringa[1], but since stringa[1] through stringa[8] don't have a string, then they wouldn't get initialized.

I can definitely see that if I had initialized a string array of 10 elements (say stringa[0] to stringa[9]) and wanted to initialize another array of 10 elements (stringb[0] to stringb[9]) then the cop would work fine.
I'd just cop stringa[0] to stringb[0], length 9.. and it'd work great. Would a FLL statement work instead for filling out an array once the first element is created?
FLL stringa[0] stringa[1], length 9.



I've made a change in the ladder logic... and now I'm wondering if this would work?
The first pass bit still trigger the For argument (in the routine Alarm). However the For argument engage the routine StringInit. This routine will get cycled ten times. Though that's the other question...
In reading the For instruction, it say it does not pass on parameters to the routine.... it sounds like I can't use the index value to address an array indirectly.

However since I'm initializing the first string in all ten arrays, would using a For loop to cycle through this routine once should be enough to initialize the first element in the arrays, and then use a FLL for the remaining nine?


Thanks again to everyone for all the help. I think I was inspired to use the For loop from when I dabbled in C. If I remember correctly that's a common way to work through arrays.



oh.. and in regards to the looping 10 times or 11, I wasn't sure if the initial time through the loop the index would remain at 0, or if it would have already been stepped to 1. The instructions say that each time the For loop executes the routine the index is incremented... however.. does the increment pre or post? Before reading rung 0 in the target routine, or after reading the final rung in the target routine?
 
Last edited:
COP is a For NEXT Loop

The COP function in RS Logix works as follows

COP SourceArray[0] , DestArray[0], 4
For index = 0 to 4 -1
DestArray[0 + Index] := SourceArray[0 + Index];
Next


Examples when you use the same array as Source and Destination
Initial Values
MyArray[0] = 10
MyArray[1] = 11
MyArray[2] = 12
MyArray[3] = 13
MyArray[4] = 14

COP MyArray[1] , MyArray[0], 4

and you get

MyArray[0] = 11
MyArray[1] = 12
MyArray[2] = 13
MyArray[3] = 14
MyArray[4] = 14
All moved down 1 Index - Great for tracking and FIFO Stacks

now for your usage

COP MyArray[0] , MyArray[1], 4

and you get
MyArray[0] = 11
MyArray[1] = 11
MyArray[2] = 11
MyArray[3] = 11
MyArray[4] = 11

Hope that this is as clear as Mud
 
Thank you! I currently use the cop function to track a 10 even history. I've greatly simplified the code and now it's:

Cop default_string ("0000"), dest_string[0], length 10.

One thing I'm still puzzled about is defining default string values. I've gone to the tags themselves and keyed in the values. I'd like to be able to load the default values into the default strings during the first scan, but I'm not sure how to go about this in ladder logic?

The COP function in RS Logix works as follows

COP SourceArray[0] , DestArray[0], 4
For index = 0 to 4 -1
DestArray[0 + Index] := SourceArray[0 + Index];
Next


Examples when you use the same array as Source and Destination
Initial Values
MyArray[0] = 10
MyArray[1] = 11
MyArray[2] = 12
MyArray[3] = 13
MyArray[4] = 14

COP MyArray[1] , MyArray[0], 4

and you get

MyArray[0] = 11
MyArray[1] = 12
MyArray[2] = 13
MyArray[3] = 14
MyArray[4] = 14
All moved down 1 Index - Great for tracking and FIFO Stacks

now for your usage

COP MyArray[0] , MyArray[1], 4

and you get
MyArray[0] = 11
MyArray[1] = 11
MyArray[2] = 11
MyArray[3] = 11
MyArray[4] = 11

Hope that this is as clear as Mud
 
I believe it is possible to write to the individual SINTs within a ST data type, but I am not 100% sure. There is no such thing as a literal string AFAIK either, so just saving the project with the right data will suffice as long as the tag you use can't be changed by something external.

I don't have access to software today, but someone who does may be able to tell us if it's possible to MOV the ASCII code for each position into the string data and set the length.
 
In logix 5000 there is a dtos argument (dint to string)... which takes a numerical value (base 10) and converts it to a string... however, I'd have to 'concat' four '0' strings to create a '0000' string. Plus, I wouldn't be able to place hex letters into a string using dint. Even if I have the dint set up as hex, when the panelview+ reads it I'll get a decimal value.
My current work around is to create a string containing the hex value, mid string the values from the hex string to intermediate strings and then concat the intermediate strings together to form the hex string display.
It's actually a fun challenge, and I'm looking forward to seeing it working properly.
 
Last edited:
If you can write to the positions from two DINT literals, that's four characters...and separately set the LEN field. I think there is a concatenate instruction...but can't you have a few COP or MOV instructions before the logic to initialilze the "STring_CLear" constant?

To programmatically create constants in a SLC, I have used MOV and/or COP with literal INTs to my reserved strings individual characters. Then i copied from there to my dynamic data files as needed.

Look at the string tag from the tag editor and expand all the bits and pieces of its data type for clues on addressing.
 
Last edited:
If you can write to the positions from two DINT literals, that's four characters...and separately set the LEN field. I think there is a concatenate instruction...but can't you have a few COP or MOV instructions before the logic to initialilze the "STring_CLear" constant?

To programmatically create constants in a SLC, I have used MOV and/or COP with literal INTs to my reserved strings individual characters. Then i copied from there to my dynamic data files as needed.

Look at the string tag from the tag editor and expand all the bits and pieces of its data type for clues on addressing.

forgive me, but I don't follow how two dint literals of 0 would equal a sting containing four 0's.

I used a Cop instruction to move my fault string '0000' and filled out the arrays. It took ten COP statements, but it's now occurring during the first scan.

What I'm doing is converting decimal to hex and creating string arrays (for history). The most interesting part is going to be taking the the values the conversions and constructing the strings. It will need to be done ten times (one for each set of variables), and since there are two different sets of alarm codes, there will need to be two different types of conversion routines... I've got the extended version 90% worked out. I got sidetracked with wanting to populate the strings with an initial default value...
 
OkiePC's right, the best way to initialize a string value is going to be setting the sint's to the ascii decimal equivalent.

I'm working on a similar project that deals with a lot of strings. I'm sending text messages to our mechanics when there are alarms in utilities. You'll want to read up on the CONCAT and INSERT instructions for building your strings from different "parts".

I'm using structured text to do the initialization, you can modify it to ladder (st is going to be cleaner though imho).
Something like this:

//Initialize string values
//Area
Ascii_Area.LEN := 4;
Ascii_Area.DATA[0] := 65;
Ascii_Area.DATA[1] := 114;
Ascii_Area.DATA[2] := 101;
Ascii_Area.DATA[3] := 97;
for index := 4 to 81 do
Ascii_Area.DATA[index] := 0;
end_for;

//Colon
Ascii_Colon.LEN := 1;
Ascii_Colon.DATA[0] := 58;
for index := 1 to 81 do
Ascii_Colon.DATA[index] := 0;
end_for;

//Carriage return + Line feed
Ascii_CR_LF.LEN := 2;
Ascii_CR_LF.DATA[0] := 13;
Ascii_CR_LF.DATA[1] := 10;
for index := 2 to 81 do
Ascii_CR_LF.DATA[index] := 0;
end_for;

//Equipment
Ascii_Equip.LEN := 9;
Ascii_Equip.DATA[0] := 69;
Ascii_Equip.DATA[1] := 113;
Ascii_Equip.DATA[2] := 117;
Ascii_Equip.DATA[3] := 105;
Ascii_Equip.DATA[4] := 112;
Ascii_Equip.DATA[5] := 109;
Ascii_Equip.DATA[6] := 101;
Ascii_Equip.DATA[7] := 110;
Ascii_Equip.DATA[8] := 116;
for index := 9 to 81 do
Ascii_Equip.DATA[index] := 0;
end_for;

An Ascii table comes in handy:
asciifull.gif
 
Last edited:
Structured text looks like fun, but unfortunately I'm using ladder logic. There doesn't appear to be a way to create alpha characters.
If there is a way to initiate a string with 'abcdef' using ladder logic, I'd be very interested. My concern is that memory is fallible, and I'd rather not trust a value to be retain during various power issues. I've seen pid settings flip values, timers/counters reset, etc...
The way I'm approaching it now is rather backwards... I'm comparing the value of the hex string against a numerical constant... if it's neq then I'll give an alarm notification to check the hex string. It's not an ideal solution, but it's better than nothing at this point.

Thanks for the table, that's pretty neat.

OkiePC's right, the best way to initialize a string value is going to be setting the sint's to the ascii decimal equivalent.

I'm working on a similar project that deals with a lot of strings. I'm sending text messages to our mechanics when there are alarms in utilities. You'll want to read up on the CONCAT and INSERT instructions for building your strings from different "parts".

I'm using structured text to do the initialization, you can modify it to ladder (st is going to be cleaner though imho).
Something like this:

//Initialize string values
//Area
Ascii_Area.LEN := 4;
Ascii_Area.DATA[0] := 65;
Ascii_Area.DATA[1] := 114;
Ascii_Area.DATA[2] := 101;
Ascii_Area.DATA[3] := 97;
for index := 4 to 81 do
Ascii_Area.DATA[index] := 0;
end_for;

//Colon
Ascii_Colon.LEN := 1;
Ascii_Colon.DATA[0] := 58;
for index := 1 to 81 do
Ascii_Colon.DATA[index] := 0;
end_for;

//Carriage return + Line feed
Ascii_CR_LF.LEN := 2;
Ascii_CR_LF.DATA[0] := 13;
Ascii_CR_LF.DATA[1] := 10;
for index := 2 to 81 do
Ascii_CR_LF.DATA[index] := 0;
end_for;

//Equipment
Ascii_Equip.LEN := 9;
Ascii_Equip.DATA[0] := 69;
Ascii_Equip.DATA[1] := 113;
Ascii_Equip.DATA[2] := 117;
Ascii_Equip.DATA[3] := 105;
Ascii_Equip.DATA[4] := 112;
Ascii_Equip.DATA[5] := 109;
Ascii_Equip.DATA[6] := 101;
Ascii_Equip.DATA[7] := 110;
Ascii_Equip.DATA[8] := 116;
for index := 9 to 81 do
Ascii_Equip.DATA[index] := 0;
end_for;

An Ascii table comes in handy:
asciifull.gif
 
Last edited:

Similar Topics

hi , I need to sorry for my bad English first. I'm newbie at plc programming ,I had been asked about E/IP protocol information for some system...
Replies
3
Views
340
So I have a PID loop on an 1756-L61 running V17 software just for background. Also the PID PV is a pressure transmitter and the CV is speed sent...
Replies
1
Views
866
Good morning guys, I have a machine that fills bags of prepared food at a variable speed, and a machine that checks the weight of the bag. What...
Replies
23
Views
6,740
Hello Please Help, I want to use a FSC instruction that will scan 20 DINT arrays. If the arrays are greater than 1000 display the value. How do I...
Replies
4
Views
1,708
Hey all, I just joined today. Not sure if this question is in the right place or if anyone has asked it before. I am monitoring a machine from...
Replies
2
Views
1,408
Back
Top Bottom