0

I am receiving a decimal variable that correlates to 8 relay values of on or off. If off its value is 0 if on it variable is as follows

Relay1 = 1
Relay2 = 2
Relay3 = 4
Relay4 = 8
Relay5 = 16
Relay6 = 32
Relay7 = 64
Relay8 = 128

So if Relay1 and Relay8 were on I would receive 129.

Relay1 = 1
Relay2 = 0
Relay3 = 0
Relay4 = 0
Relay5 = 0
Relay6 = 0
Relay7 = 0
Relay8 = 128

I need to create some logic to figure out when I receive a value between 0-255 what the relay values would be. Ultimately I'm just spitting out some XML code that will have something as follows

<map key="00">
    <update state="Relay1" type="boolean">Off</update>
    <update state="Relay2" type="boolean">Off</update>
    <update state="Relay3" type="boolean">Off</update>
    <update state="Relay4" type="boolean">Off</update>
    <update state="Relay5" type="boolean">Off</update>
    <update state="Relay6" type="boolean">Off</update>
    <update state="Relay7" type="boolean">Off</update>
    <update state="Relay8" type="boolean">Off</update>
</map>
<map key="01">
    <update state="Relay1" type="boolean">On</update>
    <update state="Relay2" type="boolean">Off</update>
    <update state="Relay3" type="boolean">Off</update>
    <update state="Relay4" type="boolean">Off</update>
    <update state="Relay5" type="boolean">Off</update>
    <update state="Relay6" type="boolean">Off</update>
    <update state="Relay7" type="boolean">Off</update>
    <update state="Relay8" type="boolean">Off</update>
</map>
<map key="02">
    <update state="Relay1" type="boolean">Off</update>
    <update state="Relay2" type="boolean">On</update>
    <update state="Relay3" type="boolean">Off</update>
    <update state="Relay4" type="boolean">Off</update>
    <update state="Relay5" type="boolean">Off</update>)
    <update state="Relay6" type="boolean">Off</update>
    <update state="Relay7" type="boolean">Off</update>
    <update state="Relay8" type="boolean">Off</update>
</map>
<map key="129">
    <update state="Relay1" type="boolean">On</update>
    <update state="Relay2" type="boolean">Off</update>
    <update state="Relay3" type="boolean">Off</update>
    <update state="Relay4" type="boolean">Off</update>
    <update state="Relay5" type="boolean">Off</update>
    <update state="Relay6" type="boolean">Off</update>
    <update state="Relay7" type="boolean">Off</update>
    <update state="Relay8" type="boolean">On</update>
</map>

so the programming language is not as important but help with the logic would be great. I don't want to have to write out all 255 scenarios as this xml is simplified. If someone can point me in the right direction that would be great. What I'm struggling with is the correlation between 129 and say relay5.

Most familier with python so going to clasify it there.

3 Answers 3

3

I'd use bit-wise shifting (or powers of 2) and bit-wise comparisons to get the relay values from a given input. A little cleaner in my opinion vs. converting it to a string with bin

value = 53
for relay in range(8):
    print 'Relay{} = {}'.format(relay + 1, 2**relay & value)

Prints:

Relay1 = 1
Relay2 = 0
Relay3 = 4
Relay4 = 0
Relay5 = 16
Relay6 = 32
Relay7 = 0
Relay8 = 0

When you use &, Python's bit-wise and-operator, it's individually and'ing each bit of the number together. Powers of two, 1, 2, 4, 8, and so forth, only have one bit set in their binary representations, so when you & them with the value in question, if the bits align, they return a non-zero number (True), and if not, 0 (False).

 53 = 00110101
--------------
  1 = 00000001   --&-> 00000001  # the 1's place lined up, so you get it back
  2 = 00000010   --&-> 00000000  # nothing at the 2's in the key
  4 = 00000100   --&-> 00000100  # 4's place lines up
     ... and so on.

For all the things:

for key in range(256):
    print '<map key="{}">'.format(key)
    for relay in range(8):
        print '    <update state="Relay{}" type="boolean">{}</update>'.format(
                relay + 1, 'On' if key & 2**relay else 'Off')
    print '</map>'

Regarding shifting, if you're a C programmer, you could also use 1 >> relay for powers of 2.

Sign up to request clarification or add additional context in comments.

Comments

1

Convert the input to binary using bin(n), and the resulting bits will correspond to the state of the relays: 0 means off, and 1 means on.

>>> bin(129)
'0b10000001'
>>> 

The right-most (least significant) bit corresponds to relay 1 (showing it is On) and the left-most (most significant) bit corresponds to relay 8 (currently On).

Comments

1

The key is converting the integer into binary, the simplest way is using the built in bin().

From there, iterate over each bit in the binary number, and then convert that to the number of the index. As binary numbers are most significant bit first, so you need to iterate in reverse order (x[::-1])

>>> for i,x in enumerate(bin(8)[:1:-1]):
...  print "Relay ",i+1," is ",['off','on'][int(x)]
...
Relay  1  is  off
Relay  2  is  off
Relay  3  is  off
Relay  4  is  on

You can package this as a function like this:

# Returns an array, with 'True' if the relay is 'on', false otherwise.
def relays(in):
    return [i=='1' for i in enumerate(bin(in)[:1:-1]]

It then becomes a matter of either calling this 255 times to generate your XML (which is a confusing idea) or using this to determine the state of the relays and altering logic based on that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.