Shop OBEX P1 Docs P2 Docs Learn Events
Convert an integer to Binary — Parallax Forums

Convert an integer to Binary

T ChapT Chap Posts: 4,223
edited 2007-02-02 02:41 in Propeller 1
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

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-02-01 15:47
    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 ChapT Chap Posts: 4,223
    edited 2007-02-02 01:36
    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 GreenMike Green Posts: 23,101
    edited 2007-02-02 01:42
    My mis-typing. The assignment "pin := 0" should be "pinState := 0".
  • Mike GreenMike Green Posts: 23,101
    edited 2007-02-02 01:49
    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 ChapT Chap Posts: 4,223
    edited 2007-02-02 02:41
    That solved the issue, now I use both methods, works great! I appreciate the breakdown, trying to absorb it.
Sign In or Register to comment.