ControlLogix Tidbits, Finding Bits in an Integer

whirlair

Member
Join Date
Dec 2007
Location
mn
Posts
64
For the last day or so I have been reading on here about how to discover what bit is true in an integer. Most of the info is from Peter Nachtwey.

My application requires me to find the least significant bit in a 32 bit DINT on the ControlLogix platform. I don't usually need to do this type of operation so I looked on here and found that RSLogix 500 had the ENC instruction. Unfortunately CLX does not have this. I found much information on here about how to find the bit using log if you only had one bit on at a time. What I'm doing may have many bits on at a time so this didn't work. I also wanted to avoid using a loop.

To accomplish this I used the FSC instruction. I then made a map (using many rungs unfortunately) to map my DINT's bits to a DINT array using MOV instructions. I then made a second DINT with the value of 1 that the FSC will use to compare.

The FSC stops when it finds a match (the first 1 in the array) and the .POS is the bit place value. This is the least significant bit. If you want to keep searching the array you just unlatch .IN and it will find the position of the next true bit. To only search for the LSB just CLR the .POS and reset the control bits for the FSC.

By stepping through the search you should also be able to find the most significant bit by paying attention to the .DN bit of the FSC.

I have a few questions.
What other methods are there to find the LSB in ControlLogix?
Is there a better way to map a DINT's bits to an array?
 
Last edited:
Brute force

What I'm doing may have many bits on at a time so this didn't work. I also wanted to avoid using a loop.

I have a few questions.
What other methods are there to find the LSB in ControlLogix?
Is there a better way to map a DINT's bits to an array?

Binary brute force.
Code:
(*
	LEAST SIGNIFICANT BIT
	return the index if the least significant bit set or -1 if no bits are set.
*)

FUNCTION LSB : DINT
VAR_INPUT
	DW_IN: DWORD;						// CAN'T WRITE TO INPUTS ACCORDING TO THE SPEC
END_VAR
VAR
	DW: DWORD;
	C: DINT;
END_VAR

	IF DW_IN<>0 THEN
		DW:=DW_IN AND NOT(DW_IN+1);
// 		DW_IN:=DW_IN AND (DW_IN-1);    // REMOVE THE LSB IF DW_IN IS A VAR_IN_OUT		
		C:=0;
		IF (DW AND 16#FFFF0000)<>0 THEN C:=C+16; END_IF
		IF (DW AND 16#FF00FF00)<>0 THEN C:=C+8;  END_IF
		IF (DW AND 16#F0F0F0F0)<>0 THEN C:=C+4;  END_IF
		IF (DW AND 16#CCCCCCCC)<>0 THEN C:=C+2;  END_IF
		IF (DW AND 16#AAAAAAAA)<>0 THEN C:=C+1;  END_IF
	ELSE
		C:=-1;
	END_IF
	LSB:=C;
END_IF
You shoud be able to do this in about 7 or 8 rungs.
 
I AND NOT(I-1) returns the integer value that has only the least significant bit set. All other bits except the LSB will be cleared.

10100 = I (20), Counting from 0, bit 2 is the LSB.

10011 = I-1 (19)

01100 = NOT(I-1)

00100 = I AND NOT(I-1), counting from 0, bit 2 is the only bit set (making it both the LSB and also the MSB of the result).

What other methods are there to find the LSB in ControlLogix?
Another brute force method would be a subroutine with 32 rungs, one for each bit. As soon as the first true bit is found, the subroutine returns, there by skipping any other more significant bits.

XIC DINTTAG[0] MOV 0 INDEX RET
XIC DINTTAG[1] MOV 1 INDEX RET
XIC DINTTAG[2] MOV 2 INDEX RET
XIC DINTTAG[3] MOV 3 INDEX RET
.
.
.
XIC DINTTAG[31] MOV 31 INDEX RET

Not super efficient rung wise, but it will execute very fast and its easy for Bubba to understand.
 
I AND NOT(I-1) returns the integer value that has only the least significant bit set. All other bits except the LSB will be cleared.

10100 = I (20), Counting from 0, bit 2 is the LSB.

10011 = I-1 (19)

01100 = NOT(I-1)

00100 = I AND NOT(I-1), counting from 0, bit 2 is the only bit set (making it both the LSB and also the MSB of the result).


Another brute force method would be a subroutine with 32 rungs, one for each bit. As soon as the first true bit is found, the subroutine returns, there by skipping any other more significant bits.

XIC DINTTAG[0] MOV 0 INDEX RET
XIC DINTTAG[1] MOV 1 INDEX RET
XIC DINTTAG[2] MOV 2 INDEX RET
XIC DINTTAG[3] MOV 3 INDEX RET
.
.
.
XIC DINTTAG[31] MOV 31 INDEX RET

Not super efficient rung wise, but it will execute very fast and its easy for Bubba to understand.

I don't really understand your first method, could you explain it better or give an example of how to program that?

I can't use your second method because I'm making a AOI to return the LSB.
 
The second method would work great as an AOI. Just forget about the RET and change the rung order from high-to-low ... 3, 2, 1, 0. Or, if you like the idea of skipping logic once the bit is found, add a JMP in place of the RET.
 
You can also use FBC (File Bit Compare). Seems efficient. Have seen some examples around here for using it in alarming and it is very fast.

You can put it in all mode and it will output all bits that are high (or do not match your comparison array) and the value in position 0 of your output array will be the LSB position.

Darren
 
Last edited:
Also note that even though the instruction is called File Bit Compare it operates on arrays of DINTs at the bit level. It actually will not work with BOOLs (kinda non-intuitive to me).

Darren
 
This PLC code will set a DINT to the first occurance of a true state within a word.
Uses a FOR (loop) but it works well for me.

The second rung shown is the entire scope of the subroutine R25_InductAssign.

FFU_LaneBits is the word with the bit/s you want to find.

DINT_035I_Induct_Assign is the resultant DINT.

This example only looks through the first 14 bits.
Set the Terminal Value to 32 if you want to looks at 32 bits.

1st Bit to DINT.jpg
 
Last edited:
The second method would work great as an AOI. Just forget about the RET and change the rung order from high-to-low ... 3, 2, 1, 0. Or, if you like the idea of skipping logic once the bit is found, add a JMP in place of the RET.

I'll try it. I was unsure if you could use JMP in an AOI.
 
For/Next loops are convenient, but they have a large overhead cost. For an AOI a brute force approach will be a lot more efficient. There are several different kinds bit hacks that can be used as well.

I don't really understand your first method, could you explain it better or give an example of how to program that?
I'm not sure how I can explain it any more clearly. Try it yourself with a piece of paper and a pencil. Write down a number in binary. Subtract 1 from the binary. Bitwise NOT the result. Then bitwise AND that with the original number. Only the LSB will remain. Using a CPT instruction you would program CPT RESULT "I AND (NOT(I-1))"


What I'm not totally clear on is if you want a number that has only the LSB set or do you want to know the position of the LSB?
 
For/Next loops are convenient, but they have a large overhead cost. For an AOI a brute force approach will be a lot more efficient. There are several different kinds bit hacks that can be used as well.


I'm not sure how I can explain it any more clearly. Try it yourself with a piece of paper and a pencil. Write down a number in binary. Subtract 1 from the binary. Bitwise NOT the result. Then bitwise AND that with the original number. Only the LSB will remain. Using a CPT instruction you would program CPT RESULT "I AND (NOT(I-1))"


What I'm not totally clear on is if you want a number that has only the LSB set or do you want to know the position of the LSB?

I want the position, but that shouldn't be too difficult to acquire after using your method to get only the LSB.
 

Similar Topics

Why does the controllogix redundancy modules use a single mode fiber vs multimode fiber?
Replies
1
Views
80
Hello, I have two 16 point input cards and 1 16 point output card showing module faulted on my IO tree in Logix Designer. The fault code is...
Replies
7
Views
214
Hello, My associate and I are trying to sync up two ControlLogix racks (7-slot chassis) with identical modules. We are able to see the secondary...
Replies
4
Views
193
Trying to setup a message read via Ethernet. I have the path setup as 1, 1, 2, 192.168.66.10 I get an error code 1, ext err 315. I am beating...
Replies
9
Views
231
I have a redundant ControlLogix being set up. This program reads a value from a remote site which happens to be SLC PLC. Rockwell mentions SLC...
Replies
2
Views
96
Back
Top Bottom