Search code examples
pythonraspberry-pigpioi2c

Getting the info from MCP23017 with Python


I bought a MCP23017 for my Raspberry Pi to increase the GPIO pins.

enter image description here

I have currently installed it and I'm trying to get the extra pins that I have; GPB0-GPB7 on the left and GPA0-GPA7 on the right to do my bidding.

I need to set them to input pins to read a HIGH and LOW status, and add the pull up resistors to them but this is as far as I have gotten:

import smbus
import time

bus = smbus.SMBus(1) # As I'm using an newer RPi.

DEVICE = 0x20 # this is what it shows when I check it.
IODIRA = 0x00
GPIOA  = 0x12

bus.write_byte_data(DEVICE,IODIRA,0xFF)
bus.write_byte_data(DEVICE,0x0C,0xff)

value = bus.read_byte_data(DEVICE,GPIOA)

When I try to read the value, it gives me strange numbers, and I can barely find any explanation on the Hexidecimals ans the Binary numbers and it's compeltly throwing me off. The datasheet seems like Chinese to me..

Any help would REALLY be appreciated!


Solution

  • This script will turn on the internal pull-up resistors for GPIOA and GPIOB. Then it will print the values of all the registers once per second. You can use the output to watch the register values change as you change the inputs.

    import smbus
    import time
    
    DEVICE = 0x20
    
    address_map = {
        0x00: 'IODIRA',   0x01: 'IODIRB',   0x02: 'IPOLA',   0x03: 'IPOLB',
        0x04: 'GPINTENA', 0x05: 'GPINTENB', 0x06: 'DEFVALA', 0x07: 'DEVFALB',
        0x08: 'INTCONA',  0x09: 'INTCONB',  0x0a: 'IOCON',   0x0b: 'IOCON',
        0x0c: 'GPPUA',    0x0d: 'GPPUB',    0x0e: 'INTFA',   0x0f: 'INTFB',
        0x10: 'INTCAPA',  0x11: 'INTCAPB',  0x12: 'GPIOA',   0x13: 'GPIOB',
        0x14: 'OLATA',    0x15: 'OLATB'
    }
    register_map = {value: key for key, value in address_map.iteritems()}
    max_len = max(len(key) for key in register_map)
    
    def print_values(bus):
        print "-" * 20
        for addr in address_map:
            value = bus.read_byte_data(DEVICE, addr)
            print "%-*s = 0x%02X" % (max_len, address_map[addr], value)
    
    bus = smbus.SMBus(1)
    bus.write_byte_data(DEVICE, register_map['GPPUA'], 0xFF)
    bus.write_byte_data(DEVICE, register_map['GPPUB'], 0xFF)
    
    counter = 0
    try:
        while True:
            print_values(bus)
            counter += 1
            print "counter = %s" % counter
            time.sleep(1.0)
    except KeyboardInterrupt:
        print "Keyboard interrupt"
    

    Example Output

    --------------------
    IODIRA   = 0xFF
    IODIRB   = 0xFF
    IPOLA    = 0x00
    IPOLB    = 0x00
    GPINTENA = 0x00
    GPINTENB = 0x00
    DEFVALA  = 0x00
    DEVFALB  = 0x00
    INTCONA  = 0x00
    INTCONB  = 0x00
    IOCON    = 0x00
    IOCON    = 0x00
    GPPUA    = 0xFF
    GPPUB    = 0xFF
    INTFA    = 0x00
    INTFB    = 0x00
    INTCAPA  = 0x00
    INTCAPB  = 0x00
    GPIOA    = 0xFF
    GPIOB    = 0xE9
    OLATA    = 0x00
    OLATB    = 0x00
    counter = 3
    

    I am using the MCP23017 on an Adafruit LCD Keypad Kit, so some of the pins are being pulled low by the board.

    Understanding the Port Values

    Each port has 8 GPIO pins. If all pins for a port are pulled high, the hex value for the port will be 0xFF. If a pin is pulled low, the bit for that pin will be zero. For example, if GPA0 is pulled low, the GPIOA register will have a value of 0xFE:

    1111 1110 = 0xFE