Sign in to follow this  
Followers 0
pelly09

Math question !

14 posts in this topic

Hi all i need help with a mathmatical problem i have that i may have to use in a contrologix plc. my problem is simply this i have a value stored in an INT, the value will represent one bit in the INT, there will only ever be one bit set in the "word" eg....1, 2, 4, 8, 16, 32 etc i need to look at this INT and take the position of the bit number and store it elsewhere as a decimal number eg....1=1, 2=2, 4=3, 8=4, 16=5, 32=6 etc i will then use the binary pattern of this decimal number to drive messages on my HMI any help would be greatly appreciated steve

Share this post


Link to post
Share on other sites
Had to get up early today, so my brain is not fully engaged yet, so how about the old brute force method, not elegant, but will work, and will be easy for anyone to follow. Use compare instructions for each value, and then write the corresponding value to your screen variable. (This would be very easy to do in Structured Text, but you can do the same thing in ladder) IF integer = 1 THEN hmi_tag :=1; ELSEIF integer = 2 THEN hmi_tag := 2; ELSEIF integer = 4 THEN hmi_tag := 3; ELSEIF integer = 8 THEN hmi_tag := 4; ELSEIF integer=16 THEN hmi_tag=5; ELSEIF integer = 32 THEN hmi_tag := 6; ELSEIF integer = 64 THEN hmi_tag := 7; ELSEIF integer = 128 THEN hmi_tag := 8; ELSEIF integer = 256 THEN hmi_tag := 9; ELSEIF integer = 512 THEN hmi_tag := 10; ELSEIF integer = 1024 THEN hmi_tag := 11; ELSEIF integer = 2048 THEN hmi_tag := 12; ELSEIF integer = 4096 THEN hmi_tag := 13; ELSEIF integer = 8192 THEN hmi_tag := 14; ELSEIF integer = 16384 THEN hmi_tag := 15; ELSE hmi_tag := 0; ENDIF;

Share this post


Link to post
Share on other sites
Take the LOG of the integer value and divide by the LOG of 2. The result is the base 2 log of the integer, which is the bit position. You will probably need a special case if the integer value is zero.

Share this post


Link to post
Share on other sites
Cool ... But I think you have to add 1 to it.

Share this post


Link to post
Share on other sites
Look at your Logix 5000 Help and check out the FBC Instruction. You'll need to create several additional tags {Reference, Result, CompareCotnrol, ResultCotnrol} but what you'll end up with is the number you want in the result array at position 0 and if the result has more than 1 value then you've got an easy error trap.

Share this post


Link to post
Share on other sites
thanks for the replies guys, but i found an instruction in the internal logic editor of the HMI that does the job for me. it's just a case of taking the INT value from my plc, running it through my logic in the HMI and using the result which is stored in an internal address to drive my messages BTW you are right finfin, you do have to add 1 !!

Share this post


Link to post
Share on other sites
This is an interesting question in the general sense. And in the general sense isn't the solution just an iterated bit shift right, easily adapted to most plcs, as in the following C# example: using System; class BitLocator { public static void Main(string[] args) { double TWO = 2; double exponent = 0; int value = 0; int locOfBit = 0; //get integer value do { Console.WriteLine("Enter an integer 0 thru 15: "); exponent = Math.Round(double.Parse(Console.ReadLine())); } while (exponent < 0 || exponent > 15); value = (int)(Math.Pow(TWO, exponent)); //get location of bit while (value != 0) { value = value >> 1; //bit shift right locOfBit++; Console.WriteLine(value); } //send the result somewhere Console.WriteLine("The location of the bit is {0}", locOfBit); } }

Share this post


Link to post
Share on other sites
popquiz does not have the best solution. This correct solution is ancient knowledge and on the internet. Search the internet to get the best solution.

Share this post


Link to post
Share on other sites
Peter, are you referring to a MSB, divide and conquer, algorithm? If you are, then I found a pretty good link which provides the method in C#. If not, please advise. Thank you. http://www.answers.com/topic/most-significant-bit Edited by popquiz

Share this post


Link to post
Share on other sites
That is good for C#. Another trick is to convert the integer to a float and access exponent directly in the most significant word. However, pelly09's solution is a simplified version of what you posted. Pelly09 said that only 1 bit would be set so this works. if ( n > 0 ) bitnum = 0; else bitnum = -1 if ( n & 0xFF00 ) bitnum += 8; if ( n & 0xF0F0 ) bitnum += 4; if ( n & 0xCCCC ) bitnum += 2; if ( n & 0xAAAA ) bitnum += 1; pelly09 did say that only one bit is set and this code can be easily be converted directly to 6 rungs of ladder ladder. remember this site http://graphics.stanford.edu/~seander/bithacks.html You can find the exponent technique there.

Share this post


Link to post
Share on other sites
The bit shifting technique is a linear search method. Peter's published method computes the binary digits, making it logarithmic, although he unrolled all the loops. I'll put out one more. If you have the situation where you have an arbitrary integer (with more than a single 1 bit), to use Peter's method, you must first clear off the extraneous bits. Here's a method that folds the number onto itself to set all the bits, then uses it as a mask to clear them all: unsigned int msb32(register unsigned int x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); return(x & ~(x >> 1)); } Alternatively I believe you could take combinations of the above methods. For instance, the C# method as proposed is a linear search for the answer. It requires 8 steps on average and 16 in the worst case. A binary search method could do the same thing in 4 comparisons on average and in the worst case. Effectively that's what Peter's method is doing, except that it's computing the answer using binary arithmetic with the assumption that there's a single one bit vs. comparisons which could be made immune to this issue.

Share this post


Link to post
Share on other sites
It is much easier to find the LSB. I usually make the LSB the highest priority bit if I use them to queue up events. lsb = bits & not (bits-1); // this is the bit itself, not the index I then remove the lsb from the list of events bits &= ~ lsb; if the lsb is not zero then I convert to and index for array indexing.

Share this post


Link to post
Share on other sites
Why is this getting so complicated? ScottC already posted the cleanest, quickest answer which can be easily applied to any modern programming language. KISS!

Share this post


Link to post
Share on other sites
The bit solutions are the simplest cleanest way to solve this. The bit solutions return an integer. ScottC's solution returns a float and the fraction still must be removed. You assume that there is always one bit set. What if there are none? You assume there is floating point. You assume that the PLC has a log instruction. You assume that the Log instruction is fast. If the micro controller must emulatie floating point the log solution will not be fast. Do you have any idea of what it takes to compute a log? The speed difference between the two techniques will be great unless there is a lot of over head for each ladder instruction. I would stick with the bit hacks. For speed and being portable.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0