Facebook Twitter Instagram Pinterest YouTube
    Trending
    • Elecrow Meteor IPS Touchscreen with RGB LEDs
    • Pi Pico Pinout Display on the Command Line
    • How to Add a Raspberry Pi Pico Reset Button
    • Pi Pico Onboard LED
    • Pi Pico W Pinout and Power Pins
    • CrowPi L Raspberry Pi Laptop and Learning Platform
    • Pi Pico W Launched
    • Add Kodi to RetroPie Menu
    Facebook Twitter Instagram Pinterest YouTube RSS
    Raspberry Pi SpyRaspberry Pi Spy
    • Home
    • Categories
      • General
      • Hardware
      • Programming
      • Python
      • Software
      • Tutorials & Help
    • BerryClip
      • BerryClip Instructions
      • BerryClip Plus Instructions
      • Videos & Reviews
    • Buy
      • Buy Pi
      • Buy Pi Accessories
      • Buy Books
    • Tools
      • Ultimate Raspberry Pi Alexa Skill
      • Pi Power Estimator App
      • Pi-Lite 14×9 LED Matrix Sprite Editor
      • RPiREF Pin-out Reference App
      • Simple Ohm’s Law Calculator
      • Web Sites & Links
    • Tutorials & Help
        Featured
        November 9, 20200

        Raspberry Pi Temperature Monitoring

        Recent
        December 23, 2022

        How to Add a Raspberry Pi Pico Reset Button

        November 20, 2022

        Pi Pico Onboard LED

        May 6, 2022

        Add Kodi to RetroPie Menu

      1. Contact Us
      2. Site Map
      Raspberry Pi SpyRaspberry Pi Spy
      You are at:Home»Hardware»Interfaces»I2C»How To Use A MCP23017 I2C Port Expander With The Raspberry Pi – Part 1
      MCP23017 Example Circuit

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

      27
      By Matt on July 31, 2013 I2C, Tutorials & Help

      For all of my projects I have used the standard GPIO header pins as inputs and outputs. This gives you a total of 17 pins to play with but what if you need more?

      The easiest way of getting more inputs and outputs is to use an “i/o port expander”. This is a device that allows you to control a number of ports using data you send to the device.

      MCP23017 Example CircuitOther people have has lots of success using I2C devices so I decided to give one a try. I2C is a serial communications protocol which allows chips to swap data on the same “bus”. A port expander takes the data and controls the appropriate pins. This allows lots of sensors and devices to be controlled using only a few of the Pi’s GPIO pins.

      The Hardware Set-up

      MCP23017 16-bit Port ExpanderThe device I chose was a MCP23017 I2C port expander with a total of 16 ports. To drive it you use the two I2C pins on the Pi’s GPIO header (Pins 3 and 5). This would give us 31 (15 + 16) inputs or outputs to play with!

      It’s actually possible to drive multiple port expanders giving you a huge boost in the number of inputs or outputs available. Adding another MCP23017 would increase the GPIO count from 31 to 47 (15 + 16 + 16). All for a few £/$.

      The great thing with these devices is that they are cheap (a couple of £/$) and require very few external components.

      In this example I’ve got 3 LEDs and a push switch connected to the device which is being driven by the two I2C pins on the Pi. I’ve used 330 ohm resistors to limit the current through the LEDs. You can use other suitable values but I tend to use 330 (as I’ve lots of them available due to my BerryClip stock!) :

      MCP23017 IO Expander ExampleThe switch resistor is 10Kohm and ties the input to ground. This insures the input is Low until the switch it pressed. Pressing the switch places 3.3V on the input resulting in it going High. The resistor stops this resulting in a short circuit between the two power rails.

      • Pin 9 (VDD) is connected to 3.3V
      • Pin 10 (VSS) is connected to Ground
      • Pin 12 (SCL) is connected to Pin 5 on the Pi GPIO
      • Pin 13 (SDA) is connected to Pin 3 on the Pi GPIO
      • Pin 18 (Reset) should be set high for normal operation so we connect this to 3.3V
      • Pins 15, 16 & 17 (A0-A2) determine the number assigned to this device. We are only using one device so we will give it a binary zero by setting all three of these pins to 0 (ground)

      Here is a photo of my test circuit built on a small piece of breadboard :

      MCP23017 Example Circuit

      The System Set-up

      To use I2C on the Pi you need to enable a few things in Raspbian as by default it is not enabled. This is a fairly easy process and is described in my Enabling The I2C Interface On The Raspberry Pi tutorial.

      Testing The Hardware

      Once you’ve enabled you i2c interface and connected your hardware double check the wiring. Make sure 3.3V is going to the correct pins and you’ve got not short circuits. Power up the Pi and wait for it to boot.

      If you’ve got a Rev 2 Pi or later then type the following command :

      sudo i2cdetect -y 1

      If you’ve got an original Rev 1 Pi then type the following command :

      sudo i2cdetect -y 0

      Why the difference? Between the Rev 1 and Rev 2 versions of the Pi they changed the signals that went to Pin 3 and Pin 5 on the GPIO header. This changed the device number that needs to be used with I2C from 0 to 1.

      I used a Rev 1 Pi and my output looked like this :

      pi@raspberrypi ~ $ sudo i2cdetect -y 0
           0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
      00:          -- -- -- -- -- -- -- -- -- -- -- -- --
      10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      70: -- -- -- -- -- -- -- --

      This shows that I’ve got one device connected and its address is 0x20 (32 in decimal). This is because the three address pins are set low. If you set A0 high the address would become 0x21 (33 in decimal). How you set A0, A1 and A2 is up to you but all your I2C devices must have a unique address.

      Command Line Test

      To do a quick test we can use the command line to enable the LED on GPA0 :

      First we configure Port A pins GPA0-6 as outputs and GPA7 as an input. (10000000 in binary and 0x80 in hex) :

      sudo i2cset -y 1 0x20 0x00 0x80 
      

      Then we set GPA0 to logic high which will enable the LED :

      sudo i2cset -y 1 0x20 0x14 0x01
      

      To turn off the LED we use :

      sudo i2cset -y 1 0x20 0x14 0x00

      Remember to replace the 1 with a 0 if you are using a Rev 1 board.

      It’s time to start using those extra GPIOs …

      Check out How To Use A MCP23017 I2C Port Expander With The Raspberry Pi – Part 2 for instructions on how you can control outputs using Python scripts.

      Check out How To Use A MCP23017 I2C Port Expander With The Raspberry Pi – Part 3 for instructions on how you can control inputs using Python scripts.

      Here are some photos of my test circuit for reference :

      MCP23017 Example Circuit
      MCP23017 Example Circuit
      MCP23017 Example Circuit
      MCP23017 Example Circuit
      MCP23017 Example Circuit
      MCP23017 Example Circuit
      MCP23017 Example Circuit
      MCP23017 Example Circuit
      Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
      Previous ArticleRunning A Python Script At Boot Using Cron
      Next Article How To Use A MCP23017 I2C Port Expander With The Raspberry Pi – Part 2

      Related Posts

      How to Add a Raspberry Pi Pico Reset Button

      Pi Pico Onboard LED

      Add Kodi to RetroPie Menu

      27 Comments

      1. Kev Partner on August 1, 2013 7:57 am

        Great tutorial, thanks. Presumably this approach also affords some protection against short circuits etc to the gpio pins?

        Reply
      2. Max on August 30, 2013 11:09 am

        This is great, for those of us with failing eyesite can you give the value of the resistors you used.

        Regards

        Reply
        • Matt on August 30, 2013 11:30 am

          I’ve updated the text. They are 330 ohm. I used them because I’ve a lot of them available but you could use other values if required.

          Reply
          • Max on August 30, 2013 4:11 pm

            Matt,

            Thanks for the fast response, what about the other resistor between the switch and ground (what does this do?) A lot of this is new to me so forgive my questions,
            I built a chess computer using an RPI & an Arduino, (www.chess.fortheray.co.uk) I needed the Arduino because of the lack of pins on the PI, but using the port exander should enable me to do it all on the RPI.

            Thanks,

            Max

            Reply
            • Matt on August 31, 2013 12:09 am

              The switch resistor is 10Kohm. I’ve updated the text to give a bit more explanation about its purpose. When the switch is not being pressed it connects the input to ground (Low). When the switch is pressed the input sees 3.3V (High). Current flows through the resistor but it is only 3.3/10 mA so nothing noticeable.

              Reply
              • Max on September 1, 2013 8:14 pm

                Matt,

                I have worked my way through all your excellent tutorials and I now think I have all I need for my project. I am building a wooden chess computer that senses moves using 64 reed switches, and signals moves with 64 LEDS. Even with multiplexing I need 24 inputs. see http://www.chess.fortherapy.co.uk .
                In my original project I used an Arduino to provide the inputs, communicating serially to the RPI, but now I should be able to do everything on the Pi. Thanks again, Max

      3. Rhys on September 29, 2013 3:41 am

        Hi,

        This is working great for me now. But I can’t figure out how to use the b0-7 pins? Any help?

        Reply
      4. Timbergetter on October 6, 2013 12:45 pm

        Many thanks Matt for this clear tutorial. It has given me the confidence to progress my internet radio project to now include many preset swithed stations. One worry is the time it will take to poll all the switched inputs, but I can only try.
        Cheers, Timbergetter.

        Reply
      5. dicks-raspberry-pi on October 10, 2013 9:17 pm

        I followed your procedure above. My response to the i2cdetect command is like yours but when I try to turn on the LED connected to gp0 nothing happens (command return code “0”). My wiring diagram is in post 31 at http://dicks-raspberry-pi.blogspot.com/

        Reply
        • Matt on October 10, 2013 9:33 pm

          It doesn’t look like you’ve connected the VDD pin to 3.3V on your diagram.

          Reply
      6. Sonia on March 21, 2014 12:53 am

        Matt, is there a ‘mouse-o’ on the circuit picture? On the bottom 5V rail just below the digits ’01’ of the mcp23017 there appears to be an extra horizontal connection.

        Reply
        • Matt on March 21, 2014 4:03 pm

          That’s deliberate. On the breadboard power rails there are gaps so I had to draw a horizontal connection to attach the wire to a hole. I don’t like diagonal lines 🙂

          Reply
      7. Average Man on April 3, 2014 11:59 pm

        Hi. I’m trying to use the MCP23017 to power a simple segment display (onme pin per segment). Problem is, the segment uses one shared 3.3V connection, and then each segment is controlled by connecting a ground.

        For the life of me I can’t work out how to switch on/off a GND connection with this chip – it seems to only support output power via each pin. Any ideas?

        Reply
      8. jamie on May 8, 2014 10:21 pm

        great tutorial! I’m gonna try using this to create an oven mapping device (9 temperature probes – each corner plus one centre). I need a lot of pins for resolution in the AtoD conversion. I gather activating each MCP23017 in sequence in the software code will take a sample temperature reading from each probe in turn (though there are only eight addresses available so eight MCP chips/probes?). I’m still very much in the early stages.

        Reply
        • Matt on May 8, 2014 10:30 pm

          The MCP23017 is a port expander so it gives you 8 inputs and outputs. These are just logic levels. It isn’t an ADC so can’t read analogue inputs. It depends on the probes but you should look at my MCP3008 posts. That is an ADC with 8 inputs. You can use two devices to read 16 analogue channels with 10-bit precision.

          Reply
          • jamie on May 9, 2014 9:30 pm

            Hi, Thanks for the reply. I’m really keen for as great an accuracy as i can get (probably +/- 0.25 degC at best if i’m lucky). I’ve been checking out the Maxim31855 (maybe one chip per probe) due to its 14 bit resolution and cold junction compensation. The output is a serial output, I thought I might have to use a multiplexer, but if I can avoid it and sample temperature across all nine points then so much the better?

            Reply
      9. Nico on November 19, 2014 6:41 am

        Hi,

        I’m trying to understand the i2cset commands better 🙂

        sudo i2cset -y 1 0x20 0x14 0x01

        works perfectly – the LED goes on 🙂

        the “1” I understand – reference to the bus on the Raspberry Pi.
        0x20 is the address of the chip
        0x14 -where does this come from? man i2cset says this is the data address – but if I look at the mcp23017 datasheet this seems to be the address for INTCONB. Obviously I don’t understand this as the LED lights up 🙂
        0x01 – set pin 0 high

        Would love to understand where I’m reading the datasheet wrong 🙂

        Reply
        • Matt on November 22, 2014 9:10 pm

          It’s the address of the output latches. In the datasheet it is “OLATA” and is quoted as 0x14.

          Reply
      10. Julian on February 24, 2015 9:18 pm

        Firstly allow me to thank you for this great article.

        I’m used to working with Arduino and ussually I have to place 4.7K resistors on SDA and SCL to 5V. Why don’t you do this on a Raspberry Pi? Does it have internal pullup resistors on the SDA and SCL pins?

        Reply
        • Erich on March 3, 2015 3:16 am

          Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors they have a value of approximately 50KΩ on the Raspberry Pi.

          Reply
      11. Rpsreal on March 25, 2015 7:54 pm

        Chek my Python library to control the MCP23017 GPIO. With this library you can use the chip with simple commands.

        https://github.com/rpsreal/MCP23017_I2C-with-Raspberry-Pi-.git

        Reply
      12. Mark on July 14, 2015 1:23 pm

        Hey, thanks for that greate tutorial! 🙂

        Is it possible to add an I/O epander like the MCP23017 to the Pi and connect an ad converter like the MCP3008 to it and attach some sensor to that one?

        No idea if that is possible.
        If it is, do you, by chance, know how wiring is done in that case?
        🙂

        Reply
      13. keith crooks on September 25, 2016 4:40 pm

        Hi i think i am being terribly thick, I have seen in this example how to make the LED light using sudo i2cset -y 1 0x20 0x14 0x01 but how do i amend the code to make the 2nd led light connected to the GPA1 cheers

        Reply
        • Matt on September 25, 2016 6:19 pm

          The three LEDs are connected to GPA1,2 & 3. To light them up you need to think of a 3 digit binary sequence but converted to Hex for the code.

          RYG
          —–
          001 – Green ON
          010 – Yellow ON
          100 – Red ON
          101 – Red and Green ON

          So …

          Green
          sudo i2cset -y 1 0x20 0x14 0x01

          Yellow
          sudo i2cset -y 1 0x20 0x14 0x02

          Red
          sudo i2cset -y 1 0x20 0x14 0x04

          To light up Green and Red you need 1 + 4 :
          sudo i2cset -y 1 0x20 0x14 0x04

          Yellow and Red is 2 + 4 :
          sudo i2cset -y 1 0x20 0x14 0x06

          Reply
          • keith crooks on September 25, 2016 7:36 pm

            thankyou im getting somewhere now

            Reply
      14. dave klebt on November 19, 2017 11:31 pm

        why does this circuit have 3 grounds going into A0, A1 and A2?
        why is there a voltage in on RESET?

        for a simpler, output only would these be necessary at all?

        Reply
        • Matt on November 21, 2017 12:03 pm

          A0,A1 and A2 are connected to ground to make sure they are set low. If they aren’t connected to something their logic level may “float” and give unpredictable results. The Reset pin is set High for normal operation as defined in the datasheet. When connected High or Low you know what state they are in. If you don’t connect them their state is unknown and unpredictable.

          Reply

      Leave A Reply Cancel Reply

      This site uses Akismet to reduce spam. Learn how your comment data is processed.

      Recent Posts
      March 13, 2023

      Elecrow Meteor IPS Touchscreen with RGB LEDs

      December 26, 2022

      Pi Pico Pinout Display on the Command Line

      December 23, 2022

      How to Add a Raspberry Pi Pico Reset Button

      November 20, 2022

      Pi Pico Onboard LED

      November 14, 2022

      Pi Pico W Pinout and Power Pins

      Categories
      • 1-wire
      • 3D Printing
      • Add-ons
      • BBC Micro:bit
      • BerryClip
      • Books
      • Camera Module
      • Cases
      • Events
      • General
      • Hardware
      • I2C
      • Infographics
      • Interfaces
      • Minecraft
      • Model A+
      • Model B+
      • News
      • Pi Models
      • Pi Pico
      • Pi Zero
      • Power
      • Programming
      • Python
      • Raspberry Pi OS
      • Raspbian
      • RetroGaming
      • Robotics
      • Sensors
      • Software
      • SPI
      • Tutorials & Help
      Tags
      Arduino audio battery berryclip Birthday bluetooth cambridge camera CamJam DigiMakers display games GPIO I2C interface Kickstarter Kodi LCD LED Linux media Minecraft Model A motionEyeOS PCB photography photos Pi-Lite Pi Pico power python Raspberry Jam Raspberry Pi Bootcamp raspbian Retrogaming retroPie screen SD card security sensor SPI SSH temperature ultrasonic video
      Raspberry PI Related
      • Adafruit Blog
      • Average Maker
      • Official RaspBerry Pi Site
      • Raspberry Pi Pod
      • RasPi.tv
      • RaspTut
      • Stuff About Code
      Tech Resources
      • MattsBits – Pi Resources
      • Microbit Spy
      • Technology Spy
      Archives
      About

      Unofficial site devoted to the Raspberry Pi credit card sized computer offering tutorials, guides, resources,scripts and downloads. We hope to help everyone get the most out of their Pi by providing clear, simple articles on configuring, programming and operating it.

      Popular Posts
      September 19, 2014

      Top 5 Reasons The Raspberry Pi Sucks

      July 27, 2012

      16×2 LCD Module Control Using Python

      October 20, 2013

      Analogue Sensors On The Raspberry Pi Using An MCP3008

      Recent Posts
      March 13, 2023

      Elecrow Meteor IPS Touchscreen with RGB LEDs

      December 26, 2022

      Pi Pico Pinout Display on the Command Line

      December 23, 2022

      How to Add a Raspberry Pi Pico Reset Button

      Facebook Twitter Instagram Pinterest YouTube RSS

      Entries RSS | Comments RSS

      This site is not associated with the official Raspberrypi.org site or the Raspberry Pi Foundation. Raspberry Pi is a trademark of the Raspberry Pi Foundation.

      Copyright © 2022 - All Rights Reserved - Matt Hawkins

      mastodon.social@RPiSpy

      Type above and press Enter to search. Press Esc to cancel.