File Sort (SRT) Fault Array Help Needed

spence144db

Member
Join Date
May 2011
Location
Lansing MI
Posts
34
I have a machine with a tag called SP_FLT[57] with a data type of DINT. Each bit in each DINT is a machine fault of some sort. I need a way to count all 1824 bits from files SP_FLT[0] up to SP_FLT[57] then sort them by number of times each fault occurred in an 8 hour day.
I think I can do the sorting and the hours, shift, day, and month code on my own without issue so Im not asking for help on that, but I do need help with a better way to count all the machine faults and not put in 1824 counters (one for each bit in the array)
 
A first approximation

Do a DTR on SP_FLT[X] to detect a change of state.
On state change compare current value of SP_FLT[X] to SP_FLT_old[X]
If current > previous, a bit turned on - increment a counter.
If current < previous, a bit turned off - do nothing.
MOV SP_FLT[X] to SP_FLT_old[X]

This assumes that not more than one bit per word will change on the same scan.

There will probably be an issue with the high (sign) bit.
 
Well, you first need to detect when a new fault has occurred and where it's located.

How I would do this:

1) Create a second table to hold the previous contents of the element that you compared in your SP_FLT array (more on that in a minute). For our purposes we'll call it SP_FLT_STORAGE, and it has to be of the same size and type as SP_FLT.

2) Use a FSC function to compare each word in your SP_FLT to the corresponding word in SP_FLT_STORAGE. If there is a difference the .FD and the .IN bits will be set in the FSC instruction.

3) Once you detect a difference (using SP_FLT[.pos] <> SP_FLT_STORAGE[.pos] as your expression in your FSC instruction), use the .in bit to jump to a subroutine that XOR's SP_FLT[.pos] with SP_FLT_STORAGE[.pos] and stores the result in TEMP (a DINT, of course).

4) Create a 1824 element array of either DINTs or SINTs (just how many of these faults are you expecting a day anyway?). Call it: FLT_COUNT.

5) Now step through TEMP bit-by-bit to look for 1's. Once you detect a "1", use the expression: "(.pos + 1) x 32 + position of bit detection" to get your fault location and the index of which element in FLT_COUNT to increment.

5a) One way to detect the presence of a "1" is to use a BSR instruction and check to see if the .ul bit is set. If it is, then you dumped a "1" out of your TEMP DINT. A MOD and a DIV instruction will do the same thing.

5b) You will have to continue on through the remainder of the bits in TEMP to detect any other bits that might be set in TEMP. However, a short cut would be to compare TEMP to "0" to quickly determine if any other iterations will be necessary (TEMP equaling "0" would of course mean that there were no more "1" in TEMP). So if TEMP at this point equals 0, then exit the subroutine (after doing step 6 first).

6) Once you have checked all of the bits in temp, and incremented the indexed variable in FLT_COUNT to update your fault count for that particular fault, copy SP_FLT[.pos] into SP_FLT_STORAGE[.pos], reset the .in bit of your FSC and continue checking the remainder of your array using the FSC instruction.
 
Do a DTR on SP_FLT[X] to detect a change of state.
On state change compare current value of SP_FLT[X] to SP_FLT_old[X]
If current > previous, a bit turned on - increment a counter.
If current < previous, a bit turned off - do nothing.
MOV SP_FLT[X] to SP_FLT_old[X]

This assumes that not more than one bit per word will change on the same scan.

There will probably be an issue with the high (sign) bit.


Ok Now that I am not in a hurry I just looked back and checked this thread and realized I did a horrible job explaining what I'm trying to do. However I thank both of you very much for the quick response. Let me go into FULL detail as to what I'm trying to do...I notice that both of your guys suggestions is only looking to the word level. and I need to look to the bit level

First I have my tag named SP_FLT[57] (this tag holds all the machine faults). Each of the 57 DINT holds the faults for a part of the machine EX:

SP_FLT[0].0 through SP_FLT[0].31 - All of the loading faults that machine has (32 possible faults for the loader)

SP_FLT[1].0 through SP_FLT[1].31 - Paint robot faults. (32 possible faults for this one robot)
.
.
.
SP_FLT[57].0 through SP_FLT[57].31 - Unload robot faults (32 faults for this robot)

I have in my program 1824 OTL instructions that represent each individual bit of SP_FLT[0] all the way up to SP_FLT[57].

What I am looking to NOT do is make 1824 counters and count each bit each time any one bit may go high. I am looking for an elegant way to scan this SP_FLT file that has a length of 57 looking for each time any one bit turns on. The once I have detected that bit as being a value of 1 count it (was thinking of doing a simple ADD instruction not a CTU to save memory...I have an L71S that is almost full)

Second I would like to take all the counts that I have for each bit SP_FLT[57] file and sort them from Highest to lowest do I may display my top 5 faults for a given period of time. I think if I could figure out how to get the SP_FLT counted and put into a file I can figure this out on my own...

Thank you in advance for the help guys. I hope this makes sense to you. guys.
 
Why not use ST to accomplish this?

Indirect stuff is super powerful. I'm still a novice but this should get the wheels turning. Syntax not checked for accuracy and may not even be possible. I'm on the road and not near my laptop....

Still a great exercise in ST none the less. Good luck!

Code:
a:=0 //default val
b:=0 //default val, stored detection of offending element
c:=0 //default val
d:=0 //default val, stored detection of offending bit

for a 0 to 57 do //what word?
if array[a]<> oldarray[a] //detect change, value in b represents offending element
then b:=a;
else
oldarray[a]:= array[a] //if no change detected, overwrite old
end_if;
end_for;

for c 0 to 31 do //what bit?
if array[b].[c] <> oldarray[b].[c] //if rsl will accept the .?
then d:=c;
else
oldarray[a].[b] := array[a].[b]
end_if;
end_for;

if array[a].[b] = true and a=b then
fltarray[a*b] := +1; //unsure of this syntax, sized 1824 SINT
oldarray[a].[b]:= array[a].[b] //overwrite old with new once flt array has been incremented
else
exit
end_if;
end_for;
 
This sounds like a job for...SCADA MAN!
13384415411393522163superman-logo-012-hi.png

And you all thought the "S" stood for "super" (n)

But in all seriousness, this definitely sounds like the sort of thing that I wouldn't even attempt in the PLC. I've done this previously using FTView SE - it's quite straightforward with a little bit of SQL knowledge to set up an automated query to log all of the alarms from the last 24 hours to an excel spreadsheet, and then from there you can use pivot tables to check for the most frequent alarms. The time I did it, I was able to identify 5 alarms that, if eliminated, would reduce the alarm frequency by 20%.

If you must do it in the PLC, then good luck to you - I think the suggestions above are good ones 🍺
 
Ok Now that I am not in a hurry I just looked back and checked this thread and realized I did a horrible job explaining what I'm trying to do. However I thank both of you very much for the quick response. Let me go into FULL detail as to what I'm trying to do...I notice that both of your guys suggestions is only looking to the word level. and I need to look to the bit level

Au contraire.

Take a second look at step 5. The plan is that once you detect a new fault (or more precisely, a difference between words in the two tables), you jump to a subroutine to unroll that fault word into individual bits.

And remember (as I pointed out originally) that your fault "counter" array can be made up of SINTs or DINTs, but no need for actual counter variables. These would just get incremented each time that there is a new fault by simply adding 1 to the current total.

Now, I have to point out that I left a step out (or inserted a bug, if you prefer). Step 5 should read as thus:

5) Now step through TEMP bit-by-bit to look for 1's. Once you detect a "1", check to make sure that this is a new fault by checking to see if the bit in your SP_FLT[index] is also set to 1 use the expression: "(.pos + 1) x 32 + position of bit detection" to get your fault location and the index of which element in FLT_COUNT to increment. Otherwise you will be logging 2x the occurrences.
 
This sounds like a job for...SCADA MAN!

And you all thought the "S" stood for "super" (n)

But in all seriousness, this definitely sounds like the sort of thing that I wouldn't even attempt in the PLC.

I was thinking the same thing at first, but then I remembered that this was more or less the exact way that we did it at Saturn (and in PLCs that usually had no more than 8K of RAM!).

But yeah, an option would be to figure out the new faults and store those results in a table and send that to a PLC for processing.


If you must do it in the PLC, then good luck to you - I think the suggestions above are good ones 🍺

Thanks! And probably the most productive 20 minutes of my day!
 
Why not use ST to accomplish this?

Indirect stuff is super powerful. I'm still a novice but this should get the wheels turning. Syntax not checked for accuracy and may not even be possible. I'm on the road and not near my laptop....

Still a great exercise in ST none the less. Good luck!

Code:
a:=0 //default val
b:=0 //default val, stored detection of offending element
c:=0 //default val
d:=0 //default val, stored detection of offending bit

for a 0 to 57 do //what word?
if array[a]<> oldarray[a] //detect change, value in b represents offending element
then b:=a;
else
oldarray[a]:= array[a] //if no change detected, overwrite old
end_if;
end_for;

for c 0 to 31 do //what bit?
if array[b].[c] <> oldarray[b].[c] //if rsl will accept the .?
then d:=c;
else
oldarray[a].[b] := array[a].[b]
end_if;
end_for;

if array[a].[b] = true and a=b then
fltarray[a*b] := +1; //unsure of this syntax, sized 1824 SINT
oldarray[a].[b]:= array[a].[b] //overwrite old with new once flt array has been incremented
else
exit
end_if;
end_for;


for c 0 to 31 do //what bit?
if array.[c] <> oldarray.[c] //if rsl will accept the .?
then d:=c;
else
oldarray[a]. := array[a].
end_if;
end_for;


Only problem that I am having with this is that operators such as -,*,/,+,<>,= all do not work with the Bool data type...I see what your trying to do and I like it a lot...its basically a FSC for the word then once we store the .POS of the "text FSC" we do another home made FCS for the bit level. combine the 2 .POS of the word and the bit and BOOM we have the exact bit in the array that was on at time of fault...Love it. Now I just need help trying to get this one last item taken care of

How do I compare the IF array.[c] <> oldarray.[c] when I cant use any operators on bools???
 
Apply a mask for the specific bit youre interested in and compare the resulting dwords?

Code:
mask[0] := 1;
For c := 1 To 31 Do
    mask[c] := mask[c-1] * 2;
End_For;

For c := 0 To 31 Do
    If (array[b] AND mask[c]) <> (oldarray[b] AND mask[c]) Then
        d := c;
    Else
        oldarray[b] := (array[b] AND mask[c]) OR oldarray[b];
    End_If;
End_For;
 
Here's what I had in mind.

Be forewarned that it hasn't been tested, and that you are on your own as to debugging it. So be sure to try it out outside of production hours (and check for array out of bounds errors by yours truly).

You will need to create a routine for the Bit_Detect FOR instruction, and put the Bit_Detect code there. The Main routine code can go anywhere.

Enjoy!

Fault array main routine.jpg Bit_Detect routine.jpg
 

Similar Topics

I am storing values into an array. I am wanting to find an average of the highs and an average of the lows. Something like this... After 50...
Replies
36
Views
8,806
Working with a customer today and they have qualified a bunch of changes today on this 1756-L73 v20.01. It crashes with a "fatal application...
Replies
26
Views
10,562
I have a file which I'm hoping is for a Mitsubishi A172SHCPUN processor but I can't see how to open it in GX Developer V8.102G The file is a zip...
Replies
4
Views
173
Hello, This product that I have the 1790D-T8BV8B is discontinued, does anyone have the EDS file for it? I wonder if TechConnect will have this...
Replies
8
Views
174
How can I access the web page that allows me to see and upload the pcl or translation file into my Pl1000E? My Pl1000E doesn’t have an ethernet...
Replies
2
Views
120
Back
Top Bottom