pyLCD icon indicating copy to clipboard operation
pyLCD copied to clipboard

MCP23017 IO Expander

Open kolonuk opened this issue 11 years ago • 2 comments

Hi,

I've just done a quick clone/convert for a backend for the MCP23017 GPI expander chip, use it as you will. It's not been tested or checked in any way yet as I'm not near my pi - just came across your code and liked it, so will be using it for my project, plus my little addition!

Notes: Needs some code to read and set individual pins as input/output instead of all at once, and there is unfortunately no PWM available AFAIK for the chip.


class MCP23017Backend:
    # For the 16 pin MCP23017 (can also be used for the 8 pin version, but need to check for lack of pins
    # useful quick reference for the pin definitions that you can use in the pinmap
    a = [(0x12, 0), (0x12, 1), (0x12, 2), (0x12, 3), (0x12, 4), (0x12, 5), (0x12, 6), (0x12, 7)]
    b = [(0x13, 0), (0x13, 1), (0x13, 2), (0x13, 3), (0x13, 4), (0x13, 5), (0x13, 6), (0x13, 7)]

    def __init__(self, display, pinmap, bus_id, address):       # bus_id is the i2c interface, address is 0x20/21/22 etc. (hex address of i2c address )
        self.display = display
        try:
            import smbus
            from time import sleep
            self.bus = smbus.SMBus(bus_id)
        except:
            raise IOError("Could not export the MCP23017. Make sure that you have the smbus library installed, run as root and are on a Raspberry Pi.")
        self.address = address.

        self.reverse_pinmap = dict([(value, key) for key, value in pinmap.iteritems()])
        self.bus.write_byte_data(self.address, 0x00, 0)    # 1 is for input
        self.bus.write_byte_data(self.address, 0x01, 0)    # 1 is for input

    def high(self, output):
        value = self.bus.read_byte_data(self.address, register)
        value |= (1 << pin)
        self.bus.write_byte_data(self.address, register, value)

    def low(self, output):
        value = self.bus.read_byte_data(self.address, register)
        value &= ~(1 << pin)
        self.bus.write_byte_data(self.address, register, value)

    def pulse(self, output):
        self.high(output)
        time.sleep(0.001)
        self.low(output)

    def all_low(self):
        for output in self.reverse_pinmap.keys():
            self.low(output)

    def write_nibble(self, nibble, data = True):
        self.write_bit(self.PIN_RS, data)
        self.write_bit(self.PIN_D4, nibble[3])
        self.write_bit(self.PIN_D5, nibble[2])
        self.write_bit(self.PIN_D6, nibble[1])
        self.write_bit(self.PIN_D7, nibble[0])

    def write_bit(self, pin, bit):
        if (bit):
            self.high(pin)
        else:
            self.low(pin)

    def write_byte(self, byte, data = True):
        self.write_bit(self.PIN_RS, data)
        for i in range(8):
            self.write_bit(getattr(self, "PIN_D%i" % i), byte[i])


    def set_brightness(self, level):
        assert level >= 0
        assert level <= 1023
        self.display.brightness = level
        self.write_bit(self.PIN_LED, level > 0)

kolonuk avatar Nov 18 '13 15:11 kolonuk

Well, just take your time and test it! Seems great!

CatoLynx avatar Nov 18 '13 17:11 CatoLynx

Hi @kolonuk, how about a pull request? Is it running stable? (For help see https://help.github.com/articles/about-pull-requests/)

nickma82 avatar Jul 15 '17 09:07 nickma82