Counting consecutive bits in ladder logic (RSLogix 5000, CompactLogix)

That won't work... if you had 6 bits on consecutively, you would get a count of 3. That's not what the OP wants...

Doh. The first bit should have been XIO not XIC. This should only count a string of four or more on bits once.

count=0
For I = 0 to 355 (where C[0] is always 0 and your array starts in C[1])
XIO C XIC C[I+1] XIC C[I+2] XIC C[I+3] XIC C[I+4] ADD count 1 count
next I
 
Doh. The first bit should have been XIO not XIC. This should only count a string of four or more on bits once.

count=0
For I = 0 to 355 (where C[0] is always 0 and your array starts in C[1])
XIO C XIC C[I+1] XIC C[I+2] XIC C[I+3] XIC C[I+4] ADD count 1 count
next I


I'll punch that in and compare execution time to mine

My "counting" method works much faster, 2.2mS. Your method takes 4.15mS to achieve the same result.

I think it might be because you have 5 indirect addresses, 4 of them requiring enumeration (calculation). These must take longer than using a couple of counters.

Another possible problem is that you can't use bit 0 in the array. My latest version has the code to copy a DINT[12] array into the BOOL array for processing. I am sort of assuming the DINT[12] array will be built from 32-bit word moves from input module .Data elements. That would mean that we need to use bit 0
 
Last edited:
I'll punch that in and compare execution time to mine

My "counting" method works much faster, 2.2mS. Your method takes 4.15mS to achieve the same result.

I think it might be because you have 5 indirect addresses, 4 of them requiring enumeration (calculation). These must take longer than using a couple of counters.

I don't normally like to use arrays of bits as they are slow and use up 32 times the memory. In general, I'd rather use DINTS. I think the principle of the algorithm is easy to understand how it works. I figure there is a way to use a mask to test the 5 bits which would be faster, but in this case would be a little more complicated to code. The OP should have plenty of ideas he can try.
 
I don't normally like to use arrays of bits as they are slow and use up 32 times the memory. In general, I'd rather use DINTS. I think the principle of the algorithm is easy to understand how it works. I figure there is a way to use a mask to test the 5 bits which would be faster, but in this case would be a little more complicated to code. The OP should have plenty of ideas he can try.

The statement in red is incorrect.

It is true that a single BOOL tag will be allocated a whole 32-bit memory word.

But a BOOL array is packed into 32-bit words, just like a DINT array.

You can see this happening if you tried to create a BOOL array of 24 bits. What will happen is that the array created will be 32-bits long, i.e. the system has "snapped" it into a single 32-bit memory word. The system allocates up to the next 32-bit memory boundary.

examples.....

BOOL[1000] will snap to BOOL[1024]
BOOL[32] will stay as BOOL[32]
BOOL[33] will snap to BOOL[64]

The main reason why BOOL arrays are not liked is that you can't do a great deal with them. Even Bit Shift Registers use xINT arrays.

However, in this scenario, the BOOL Array is the best storage method, as the FOR loop index can be used directly as the index into the BOOL Array. A DINT array could be used, but the Element.Bit numbers would have to be calculated on each iteration, slowing everything down.

Here is the program I have written to test two of the suggested methods....
 

There is an error in your code Sergei...

You are not clearing "OBJECT_SIZE" if the threshold is not reached.

So if you had already accumulated 3, and a single beam is broken later in the array, it would be counted as an object of 4 consecutive beams broken.

You need to copy the accumulated value to another tag that is tested, and clear the count anyway, since we have now found an unbroken beam.

I will put that code into my test program, and see how it fares.
 
Yes, you are right, the clearing must be not subject to the comparison, but in a separate branch after the contact.
Corrected that.
 
Last edited:
Sergei's code tested, and is just a tiny bit faster than my solution, by 0.1 mS.

But it uses twice the number of instructions, and a much hated JMP backwards.

There's nothing technically wrong with it, it works fine, but many people disapprove of the JMP/LBL construct.

Here's the test program with sergei's solution added.
 
There's nothing technically wrong with it, it works fine, but many people disapprove of the JMP/LBL construct.
The only reasonable concern imo is that because of an error it may loop too many times or even infinitely.
Wherever the number of passes is defined literally, as in my example, this is nothing but preconception.
 
Last edited:
The only reasonable concern imo is that because of an error it may loop too many times or even infinitely.
Wherever the number of passes is defined literally, as in my example, this is nothing but preconception.

Yes, agreed, and I wasn't saying it's wrong, it's a perfectly formed piece of code using available instructions.

But unfortunately that preconception writes many company's "standards" that SI's have to adhere to.

You can often convince the "man-in-charge", but to get him to re-write even a small section of "standards" is impossible, so it stays. Hopefully the next guy to fill his shoes "sees the light", but even he won't touch "standards". They usually cost tons to develop, and he'll accept that they are what they are, they've already got loads of systems using them, their engineers are "comfortable" with them, so is the new guy going to rock the boat ? Unlikely, even if he truly believes it could be better, he will tend to leave well alone. Legacies can thrive into old-age for no other reason.

I will give you an example....

"Client" would not let us use a "function" (in this case, a subroutine), for handling over 200 automatic valves....

Each valve had something like 20 rungs of code for control and alarming, so our "Valve_Handling" routine had 20 x 200 rungs of code, that's 4000+, I kid you not. It's going back a few years, which is probably why we had to use PLC5/250's with their incredibly expensive memory modules (pre Logix5000).... Anyway, I digress....

His approach was "the engineers can't see what is going on", and despite arguments that they don't even need to connect up the programming terminal if only one valve is playing up, etc. etc.

Don't get me wrong, I have the greatest respect for this "client", but he would not budge from that standpoint.

Today, of course, we are more advanced and have things like AOI's which remove the tedium of repetitive blocks of code. We can write lots of "checking" algorithms into our handlers, and deliver more information to the HMI or SCADA than any amount of "engineer scrutiny" of the code could elicit.

We have sophisticated motor-cars that almost drive themselves, can park themselves, can tell you if you are wandering off your lane, can automatically detect the road surface for water, ice, snow, gravel, etc., can maintain the cabin temperature to within +/- 0.5 degrees, can navigate you to anywhere in the world, connect you to the web, let you share wifi with 6 scantily-clad girls, and if you believe the adverts, can stop the rain from falling.....

So why do people love Jeeps and Beetles ???
 
Screenshots requested....

here's the code for my optimised FOR routine, with results for all I've tested...

the "Results" are variable, even though I'm using UID/UIE around the "calls", but you can see it's marginal...

2017-02-02_014435.jpg
 
here's "proof"s code, clearly slower due to calculated indirection....

2017-02-02_014856.jpg
 
All of the above were called independently by this code, to even out the playing field...

the GSV's are only there to get a measure of the execution time of the methods, but exist for all methods, so the results are consistent between methods.

2017-02-02_015314.jpg
 
Last edited:

Similar Topics

Hi all I have a program that when a can is rejected from the machine this is put into a shift register, which is moved via a clock pulse on the...
Replies
12
Views
3,075
Hello I am looking for tips on how to count the duration of a given function and then how to display it on the hmi panel in the hh:mm:ss format...
Replies
4
Views
1,713
Guys, I know it will be silly but can't get my head around it. I have 3 conveyors, every one on a separate servo drive, and 2...
Replies
25
Views
3,536
The 1734-IB8 has no hardware counting function correct? I am trying to find something to substitute in for a 5069-IB16F (since lead times are...
Replies
3
Views
1,431
Been scratching my head at what I thought should be a relatively simple task. I need to count how many rows a .csv file has, so I can later read...
Replies
6
Views
2,567
Back
Top Bottom