How To Use A MCP23017 I2C Port Expander With The Raspberry Pi – Part 3

MCP23017 Example CircuitIn How To Use A MCP23017 I2C Port Expander With The Raspberry Pi – Part 2 I explained how to use an MCP23017 16-bit port expander to provide additional outputs. In this article I’ll show a basic input example where we read the status of a push switch.

In our example circuit the switch input uses the last bit of the GPA set of pins.

Python Script For Inputs

Here is an example script which will read the status of the switch in a loop and print message when it is pressed :

import smbus
import time

bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
#bus = smbus.SMBus(1) # Rev 2 Pi uses 1

DEVICE = 0x20 # Device address (A0-A2)
IODIRA = 0x00 # Pin direction register
GPIOA  = 0x12 # Register for inputs

# Set first 7 GPA pins as outputs and
# last one as input.
bus.write_byte_data(DEVICE,IODIRA,0x80)

# Loop until user presses CTRL-C
while True:

  # Read state of GPIOA register
  MySwitch = bus.read_byte_data(DEVICE,GPIOA)

  if MySwitch & 0b10000000 == 0b10000000:
   print "Switch was pressed!"
   time.sleep(1)

You can download direct to your Pi using :

wget http://www.raspberrypi-spy.co.uk/archive/python/i2c_inputs.py

You can run the script using the following command :

sudo python i2c_inputs.py

The script above performs the following actions :

  • Imports the smbus and time libraries
  • Creates an smbus object named “bus”
  • Configures some register address constants
  • Sets first 7 GPA pins as outputs
  • Sets last GPA pin as an input
  • Reads the state of the 8th bit and prints a message if it goes high

When you press the button you should see “Switch was pressed!” printed to the screen.

In this example we only used one switch. Using both 8 bit registers (GPA and GPB) you’ve got a total of 16 pins to configure as inputs or outputs. That’s a possible 16 LEDs or switches in whatever combination you like. You just need to configure the IODIRA and IODIRB registers with the correct bit pattern.

Don’t forget to check out the online binary, hexadecimal, decimal number convertor to quickly generate binary, decimal and hexadecimal numbers for your own I2C scripts.

This entry was posted in Hardware, Python and tagged , , , . Bookmark the permalink.



26 Responses to How To Use A MCP23017 I2C Port Expander With The Raspberry Pi – Part 3

  1. heath says:

    hello, I’ve seen several posts that says one of the restrictions of i2c is the cable length has to be less than 6″. Is that the cable length just between the Pi and the MCP23017? Or does that mean any peripherals attached to the MCP23017 can only be up to 6″ away?

    Thanks.

    • Matt says:

      I’m not sure but I did some quick Googling and plenty of people seem to have some sucess with cable lengths measured in metres. If there is a restriction it will be the two I2C lines between the MCP23017 and the Pi. The inputs and outputs on the chip are just normal logic pins.

    • Geert Vancompernolle says:

      Old thread, but still…
      The length of the cables you’re talking about, are at the output side of the MCP23017 and have nothing to do with I2c. So, there’s not really a length restriction at that side.
      I2c, however, is limited because of the line capacitance that should not be larger than 400pF.
      There are solutions for that. One of them is using the P82B96 (http://www.ti.com/product/p82b96). When you’re using this device, you can have lengths up to at least 20m (because at the transmission side, you can go up to 4000pF bus capacitance…)

    • John Sirach says:

      An old question but it maybe helps:

      We have extended the bus line and it depends on for example the cable type used. On the next page we have an example of how to extend the bus line. Allthough the shown setup is correct you should use octocouplers to protect the expanded bus part against shorts and interferance.

      The chip mentioned below (P82B96 ) is also the one we used and if done correctly you can go up to 50 meters and counting. We also have the spec sheet on this page so you have a table explaining how far you can get at 100khz (which the pi uses by default).

      The page is: http://pidome.wordpress.com/manual-howtos/pidome-hardware/i%C2%B2c-bus-extender-for-the-raspberry-pi/

  2. Florin says:

    Hello. Any tutorials for how to read a temperature sensor like the DS18B20 using raspberry pi and the MCP23017? Thanks!

  3. Chris says:

    Im looking to really increase the number of GPIO output.. I’m looking for 32 outputs, can I use 2 of these port expanders in parallel?

    • Matt says:

      You can connect two using the same I2C pins on the Pi. You just need to set a different address for the second device using the A0,A1,A2 pins. ie rather than set them all low set A0 high.

  4. Miss K says:

    Hi there. Great tutorial! Im fairly new at using i2c on the raspberry and have very little experience.. I wanted to know if you can maybe post a diagram of how 2 mcp chips can be connected to the RPi

    • Matt says:

      It’s on my list of things to do! The only real difference is the A0, A1 and A2 pins. One of these must be set high to give the second device a unique address.

  5. Samadi says:

    Hi there, I’m pretty new to I2C so I was wondering if it is possible to use interrupts with inputs on the MCP? If so could you explain how? If not I will have to stick with the 7 accessible pins on the GPIO header of my Rev 2 RPi.

    • Robin says:

      Hi Samadi (and anyone else that can help),
      I’m trying to use the interrupts on the slice of Pi/o mcp23017 with Python and smbus. How did you get on with enabling the interrupt?
      I know I need to tie the INT pad back to one of the GPIO pins on the rpi, but I need to know how to tell the mcp23017 to change the INT state during an input change using bus.write_byte_data()
      Any examples would be very helpful…
      Thanks all,
      R

      • iPadawan says:

        I was searching about this, and came here. Anyone has some idea to do that, and got it working?
        Matt, something for part 4?

        Thank you in advance.

        • Andy Wright says:

          I have been through part 1 to part 3 and all work really well, thank you. However now I would also like to see if I can use the intrupts with your smbus library and any additional wiring. Did you ever create a part 4 or do you have some sample code or examples. I think I might also need some notes on connecting the INT pin as it look as though you need to connect it to one of the GPIO pins. I would be creatful for any information. Thank you.

          • Matt says:

            The smbus library isn’t mine it’s just one of the libraries out there that everyone uses. I’m not sure who the author is. Unfortunately I haven’t had a chance to ever try out interrupts on the MCP23017.

  6. Louis J Bogdan says:

    In my consulting work I find that I have need for a programmable module and with some research find the raspberry pi to be of great interest. I have no use for video, audio or external connection such as TV or monitor. The module would be used to control a plurality of stepper motors and DC motors. Input information would be in multiple tables, or more desirable, with input values of A, B and C and a 6-step formula which would preclude the units to be confined to only the preloaded tables and their attendant high usage of memory. The latter would make the units more universal.
    What linux language would be most appropriate? Would like any and all comments.

  7. steve says:

    Thank for your work. It help me to start with i2c study.
    Good work.
    Thank from Italy
    steve

  8. I’d like to use the I2C ports to control 24v solenoid switches (irrigation valves) via an 8-channel opto relay board (such as listed at http://www.ebay.com/bhp/8-channel-relay-board). Would those be treated like LEDs from an MPC23008 chip?

  9. DavidBW says:

    Thanks for the tutorial, but could someone clarify something? I have set GPA7 as an input and GPA1-6 as outputs using: i2cset -y 1 0x20 0x00 0x80. When I hold GPA7 at either 0v or 3.3v I was expecting to read the GPIOA register using: i2cget -y 1 0x20 0x12 w and was expecting to see either 0x80 or 0x00, as high or low. yet the returned values seem to randomly fluctuate. My only experience of the MCP23017 is this topic!

    • Matt says:

      Although it may look random is the result you get correctly indicating the state of the input (bit 7)? If you haven’t set the outputs they may be floating. Bit 7 is probably correct. The other bits don’t matter as they are outputs. 0x80,0x60,0xA0 are all valid results for Bit 7 being High.

  10. slatan says:

    Very nice tutorial. Thanks a lot.
    at first it wasn’t clear where the numbers for DEVICE , IODIRA and GPIOA came from, then i googled it.

  11. Mike says:

    Hello
    thanks for this gread howto…
    but can anyone tell me how to use interrupts on the mcp23017 and readout and interpret them? the reason is, i want to wire more than one DHT11 on my pi but there are only a few pins free so i thought i use the mcp23017 or the mcp23S17 (heared that ISP is faster I2C)…
    i found a python script to readout the dht11 directly wired with gpios and there is “GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP)” in there…
    so how can i translate it for the mcp??
    thnx 4 help.
    mike

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>