PDA

View Full Version : Convert an integer to Binary



T Chap
02-01-2007, 07:59 PM
There is an i2c project that requires two bytes followed by the start/address/dir byte. The device is the PCF8575 i/o expander, and in this case, all 16 pins are outputs, and generally only one pin will be high, but that could change.

A serial string is sent to several different Propellers, typically with a value of 0 to 16. A 1 sent to the i2c device should look like this:

'the start byte
%10000000
%00000000

This produces a 1 on pin one of the device. Here is an example of what happens:



PUB AMPIN_on
lcd.cls
lcd.str(string("Ampin_on"))
i2c.i2cStart(25) 'start the transaction
i2c.i2cWrite(25,%0100_000_0 + 0) ' this is a write
i2c.i2cWrite(25, %10000000) ' send the 1st byte = relay 1 on
i2c.i2cWrite(25, %00000000) ' send the 2nd byte
i2c.i2cStop(25)

PUB AMPIN_off
lcd.cls
lcd.str(string("Ampin_off"))
i2c.i2cStart(25) 'start the transaction
i2c.i2cWrite(25,%0100_000_0 + 0) ' this is a write
i2c.i2cWrite(25, %00000000) ' send the 1st byte = relay 1 off
i2c.i2cWrite(25, %00000000) ' send the 2nd byte
i2c.i2cStop(25)



The above is only 1 output of 16 to manage out of 3 banks totalling 48 pins, and I think there must be a better way to code this than to create 48 methods for each pin state, 16 for each individualy pin control per bank, and 3 Off methods for each address. I imagine that sending one method a parameter or value, such as Ampin(16) to produce the i2c value below would be best, but don't know a way to produce this value from integer 16. The trick will be turning on more than one pin should that state occur.

%11111111
%11111111

Using the integer that reflects the pin(high state) would really make things nice. It would be just an nice to be able to send the value in word form if I can find a way to break the word in half within the method prior to it sending it to the i2c part.

Can anyone suggest a conversion method to use the integer as value(0-16)? I am open to suggestions on other methods to simplify the process.

Thanks

Post Edited (originator) : 2/1/2007 1:09:44 PM GMT

Mike Green
02-01-2007, 11:47 PM
Try this:

VAR word pinState
PUB AMPIN_on(pin)
pinState |= |< (16 - pin) ' pins numbered from 1 to 16
lcd.cls
lcd.str(string("Ampin_on "))
lcd.dec(pin)
i2c.i2cStart(25) 'start the transaction
i2c.i2cWrite(25,%0100_000_0 + 0) ' this is a write
i2c.i2cWrite(25, pinState >> 8) ' send the 1st byte
i2c.i2cWrite(25, pinState & $FF) ' send the 2nd byte
i2c.i2cStop(25)

PUB AMPIN_off(pin)
if pin == 0
pin := 0 ' turn off all pins if pin number given as zero
else
pinState &= $FFFF & ! |< (16 - pin) ' pins numbered from 1 to 16
lcd.cls
lcd.str(string("Ampin_off "))
lcd.dec(pin)
i2c.i2cStart(25) 'start the transaction
i2c.i2cWrite(25,%0100_000_0 + 0) ' this is a write
i2c.i2cWrite(25, pinState >> 8) ' send the 1st byte
i2c.i2cWrite(25, pinState & $FF) ' send the 2nd byte
i2c.i2cStop(25)


Note that this accumulates overall relay settings so every time you
set a pin on, you'll have to set it off and you can have more than
one relay on at a time. If you turn off pin zero, all pins are turned
off.

T Chap
02-02-2007, 09:36 AM
Mike this is very very cool! I am not sure how you converted the received integers to each pin like that (for which binary output doesen't correspond with the actual integer), but it works as designed the first try. For now I have case statements that look for and ID string that gets converted to a number like ascii "AMP1" becomes decimal 20221, so there is a case loop:




PRI casetemp1
case 20221 : amp1 := temp2 'first ID is established then the value is assigned 0-16
if amp1 > 0
ampin_on(amp1) 'will accumulate until 0 is seen
else
ampin_onold 'reset all to 0





I tried to get yours to take all to 0 on pin == 0 but it wouldn't reset, so I just used my old version that outputs all 0's and that is easy enough.

Many thanks.

Mike Green
02-02-2007, 09:42 AM
My mis-typing. The assignment "pin := 0" should be "pinState := 0".

Mike Green
02-02-2007, 09:49 AM
In trying to understand something like these routines, it's best to simulate the whole thing on paper. For example, "ampin_on(amp1)". Take a piece of paper, write down the value of "amp1". Then (from the first line of "ampin_on" write down the value of "16 - pin", then write down the value of the |< operator applied to that, then (assuming pinState is zero) write down the value of "pinState |= <that>". Later in the code, write down the value of "pinState >> 8" and "pinState & $FF". At this point, you should be able to figure out what's going on. If not, try it with another example using the (now current) value of pinState. Try the same thing with "ampin_off" if you're still not sure what's going on.

T Chap
02-02-2007, 10:41 AM
That solved the issue, now I use both methods, works great! I appreciate the breakdown, trying to absorb it.