Aug 012013
 

In this article, I’ll show you how to hook up and control a port expander chip with wiringpi2 for python. It’s really easy, and once set up (with about 3 lines of code) you can control your new ports just the same way as if they were on the Pi itself. This is, so far, my favourite new feature of WiringPi2 for Python – although there are some I have yet to play with.

This is part 3 of my wiringpi2 for python series. If you haven’t read parts 1 & 2 yet, I recommend you read those first.

What is a port expander?

You probably guessed from the name, but a port expander is a chip that gives you more GPIO ports. WiringPi2 has drivers for several port expander chips…

  • MCP23017 – 16 ports i2c based
  • MCP23S17 – 16 ports spi based
  • MCP23008 – 8 ports i2c based
  • MCP23S08 – 8 ports spi based
  • 74×595 – 8 bit shift register

We’re going to focus on just one – MCP23017

They’re all similar in usage, so I’ll simplify things by only dealing with one. There’s not much price difference between the 8 port and 16 port expanders either, so unless you need a smaller chip, you might as well have 16 ports.

Although spi (10 MHz) is faster than i2c (1.7MHz), at the kind of speeds we’re interested in for general GPIO work, it doesn’t make much difference. The advantage of i2c is that you only need to hook up 2 wires to communicate with the Pi, whereas SPI uses 4.

Pinouts

MCP23017 pinouts

The expanded GPIO ports are
Pins 21-28 GPA0-GPA7.
Pins 1-8 GPB0-GPB7.

Once you’ve set up the chip (I’ll show you how in a minute) you can use these 16 GPIO ports as either inputs or outputs.

Chip – Pi connection
VDD – 3V3 (P1 header pin 1 or 17)
VSS – GND (P1 header pin 6)
SCL – SCL on Pi (P1 header pin 5)
SDA – SDA on Pi (P1 header pin 3)
NC – Do Not Connect
RESET – 3V3 (P1 header pin 1 or 17)
INTA – Do Not Connect (I think these can be used in WP2, but haven’t played wth them)
INTB – Do Not Connect (I think these can be used in WP2, but haven’t played wth them)

Circuit diagram

Adding an MCP23017 gives us 16 additional GPIO ports to play with. You could “go to town” with this. But since my purpose here is to show you how to use wiringpi2 with the MCP23017 chip, I’m sticking to our simple “One input, one output” circuit, suitably modified for this chip. We’re using the chip’s internal pull-up. It has no pull-downs.

Circuit diagram for 1 input 1 output circuit with MCP23017

One input, one output code for MCP23017

Before you use this code, you’ll want to check that your Pi has i2c enabled, or it won’t work. You can find out how to do that here.

Once you’ve done that, you can test which i2c port your chip is set up as…
sudo i2cdetect -y 1 (if you have a rev 2 Pi)
sudo i2cdetect -y 0 (if you have a rev 1 Pi)

If you’ve done your wiring the same as in the diagram above (A0, A1, A2 all to GND) your result should be “20”. If it’s anything else, something is wrong.

Here’s the code to drive the MCP23017 with WiringPi2 for python…

import wiringpi2 as wiringpi
from time import sleep

pin_base = 65       # lowest available starting number is 65
i2c_addr = 0x20     # A0, A1, A2 pins all wired to GND

wiringpi.wiringPiSetup()                    # initialise wiringpi
wiringpi.mcp23017Setup(pin_base,i2c_addr)   # set up the pins and i2c address

wiringpi.pinMode(65, 1)         # sets GPA0 to output
wiringpi.digitalWrite(65, 0)    # sets GPA0 to 0 (0V, off)

wiringpi.pinMode(80, 0)         # sets GPB7 to input
wiringpi.pullUpDnControl(80, 2) # set internal pull-up 

# Note: MCP23017 has no internal pull-down, so I used pull-up and inverted
# the button reading logic with a "not"

try:
    while True:
        if not wiringpi.digitalRead(80): # inverted the logic as using pull-up
            wiringpi.digitalWrite(65, 1) # sets port GPA1 to 1 (3V3, on)
        else:
            wiringpi.digitalWrite(65, 0) # sets port GPA1 to 0 (0V, off)
        sleep(0.05)
finally:
    wiringpi.digitalWrite(65, 0) # sets port GPA1 to 0 (0V, off)
    wiringpi.pinMode(65, 0)      # sets GPIO GPA1 back to input Mode
    # GPB7 is already an input, so no need to change anything

Early on (lines 4-5) we define…
pin_base = 65
i2c_addr = 0x20

After setting up wiringpi (line 7) in its native pin mode…
wiringpi.wiringPiSetup()

…we initialise the MCP23017 chip (line 8) using the two variables we set earlier…
wiringpi.mcp23017Setup(pin_base,i2c_addr)

…if you wire all three address pins to GND, the i2c address is 0x20. (I explain how you can change this and use multiple MCP23017 chips, a bit further down.)

If we start with a pin_base of 65 (the lowest available number in wiringpi2) GPA0 is allocated to 65, GPA1 = 66…GPA7=72, GPB0=73, GPB1=74…GPB7=80

You can choose whatever pin_base number you like (above 64)

After that, we’re just setting up GPA0 as an output (line 10)…

wiringpi.pinMode(65, 1) # sets GPA0 to output
wiringpi.digitalWrite(65, 0) # sets GPA0 to 0 (0V, off)

…and GPB7 as an input (line 13) with pull-up enabled (line 14)…

wiringpi.pinMode(80, 0) # sets GPB7 to input
wiringpi.pullUpDnControl(80, 2) # set internal pull-up

The rest of the program is as it was before, except the logic is inverted with a not (line 21), because the button is now “the other way round”. (Pressing the button connects it to GND, not 3V3, as we did before.)

You can use up to 8 of these MCP23017 chips

If 8 onboard GPIO ports + 16 extra ports is not enough, you can connect up to eight MCP23017 chips to your Pi using different i2c addresses.

There are three address pins on the MCP23017: A0, A1 and A2. They are used to determine the chip’s ID (000 to 111). Each needs to be wired to either 3V3 (1) or 0V (0).

To begin with, I suggest wiring all three pins to GND, for ID 000, which gives us 0x20 as i2c address.

Wiring your address pins on the MCP23017

If you want to use more than one of these chips, you can easily do that. Just wire each one’s address pins with a different address, and give it a pin_base value that doesn’t overlap with numbers already in use.

e.g. ID 000, i2c address 0x20, pin_base 65

WiringPi knows this chip has 16 ports, so will allocate WiringPi pins 65-80 to this chip when this command is issued. Our first MCP23017 chip was wired as 000 = 0x20 and we chose 65 as pin_base, so…

wiringpi.mcp23017Setup(pin_base,i2c_addr) …gave the Pi…
wiringpi.mcp23017Setup(65,0x20)

To add another MCP23017, connect Pin A0 of the second chip to 3V3 instead of GND.

Now, its ID is 001, i2c address is 0x21. pin_base 81 will allocate wiringpi pins 81-96 to the second chip.

Now we issue another setup command with the second pin base and i2c address in.

wiringpi.mcp23017Setup(81,0x21)
Our second chip is now ready to use on wiringpi pins 81 (GPA0) – 96 (GPB7).

Now you can control these pins just like any other WiringPi2 pin – exactly as if they were on the Pi itself.

In this way you can add up to 8 of these chips to give you a potential extra 128 ports. That should be enough for most people. If it’s not, you can have 8 of the SPI variant (MCP23S17) on each of the two SPI lines (CE0 and CE1) for another 256 ports. If you can’t do what you need to do with 384 ports, you might need a different device.

I haven’t gone quite that silly yet, but I have had 3 MCP23017s and an MCP23S17 running at the same time.

Watch out for your 3V3 lines

Expanders are fun, but one word of warning. The 3V3 lines on the Pi (including the GPIO ports) can only give out ~51mA safely. That’s the total maximum for all ports/pins.

If you want to connect up lots of leds and lots of expanders, you’ll need to power them from another source (e.g. the 5V lines or a battery) and use transistors or Darlington arrays to do the switching for you.

You can use 16 standard 5mm leds with 330R resistors as the resistors limit the current to about 3 mA. But you’d be well advised not to use lower value resistors if you want that many LEDs.

That’s all for today. There’s a lot of fun to be had with port expanders. Enjoy :)

What we’ve covered so far in the WiringPi-Python series…

Part 1

Part 2

Part 3

There’s some parts of WiringPi2 that I haven’t yet explored. When I have, I’ll write part 4.

If you want to use the same MCP23017 port expander chip directly with i2c instead of WiringPi, Matt Hawkins has done a 3-part series on how to do that here.

  80 Responses to “Using the MCP23017 port expander with WiringPi2 to give you 16 new GPIO ports – part 3”

  1. The Quick2Wire library also includes driver code for the MCP23017 chip https://github.com/quick2wire/quick2wire-python-api/tree/master/quick2wire/parts
    But the API isn’t quite as seamless as the one offered by WiringPi https://github.com/quick2wire/quick2wire-python-api/blob/master/doc/getting-started-with-i2c.md and the documentation seems quite lacking.

    P.S. Have you switched back to using the old Fritzing models?

    P.P.S. I’d be tempted the replace ‘0x65’ in your code examples with ‘pin_base + 0’ and ‘0c80’ with ‘pin_base + 15’ (so that you could change the pin_base without having to update the rest of your code), but that’s just me ;-)

    • And it looks like AdaFruit have their own MCP23017 driver too http://learn.adafruit.com/mcp230xx-gpio-expander-on-the-raspberry-pi/overview and I’m sure there’s probably many other examples of people re-inventing the wheel ;-)

    • I wrote this blog a few days before the new Fritzing models were even published Andrew. :) And then, when I went to update the Fritzing picture, I realised that the port labels on the new models were much too small, so would need to be made much bigger in order to be useful.

      I’ve done that now, so will be using my new improved, further improved Fritzing models for future diagrams.

      I like the pin_base suggestion and will probably implement that in future stuff I do. :)

      • Taking the pin_base suggestion one step further, you could do:
        led_output = pin_base + 0
        button_input = pin_base + 15

        IMHO if not wiringpi.digitalRead(button_input):
        wiringpi.digitalWrite(led_output, 1)
        is much easier to read ;-) (at the ‘expense’ of adding more layers of abstraction).

      • On the subject of Fritzing diagrams, I wondered why some of your wires were angled, rather than perfectly horizontal or vertical… So I did some investigation, and discovered why, and also came up with a work-around :-)
        http://code.google.com/p/fritzing/issues/detail?id=2176#c6

        • Isn’t it because the power rail holes are slightly offset from the rest of the breadboard holes? (just like on a real breadboard).

          • Not in the latest version of Fritzing (and on my breadboard) they’re not ;-) But it still has the rotation-bug, meaning that post-rotation the Pi’s P1-header pins still end up out of alignment with the breadboard pins. Unless you jiggle them both back onto grid. :)

          • I’ve got six breadboards from various sources and I think they’re all like that. The P1 Pi pins line up with the main board holes not the power rail holes. Fritzing has various breadboard models though.

            I’ve never given it a second thought. It takes long enough to do this stuff without worrying about that level of detail. ;)

            As long as it’s clear what wire goes where, I don’t really mind. You should see what my REAL wiring looks like. I don’t think you’d like it ;) (Well you have seen my Gertboard Wii controller wiring)

          • Apologies if I’m being overly pedantic again… please don’t take it as personal criticism :)

            • No worries. I’ll ‘get ya’ on 21st September. ;) There’s nothing wrong with having a good eye for detail – in fact I think it’s a pre-requisite for programming and debugging.

              Actually it’s nice to know that someone’s watching my back. I don’t always get things right.

          • Although I can’t promise to watch your back all the time Alex ;-)

  2. Just wanted to say, this series of articles has been excellent, great work. WiringPi has been something I’ve intended to look at for a while now, but haven’t as other things keep coming.

    My preference for numbering GPIO has shifted to using Pin numbers, as when describing it to beginners it seems to be the most logical to them (they are not normally concerned about the SOC’s GPIO pin numbers (as they aren’t looking at the BCM datasheet) or having GPIO0-7 being scattered around the pins (as numbered by the foundation). It just takes a little to explain only some pins are available as I/O, but that has to be explained anyway.

    Keen to see what other things WiringPi2 has to offer over standard RPi.GPIO.
    Regarding the MCP23017 I’ve done some bit-banging tests using the i2cset and i2cget to get things working, nice to see there is some direct support too.

    I take it that the Hardware PWM is now built into the current distros, I had all sorts of problems when merging the Occidentalis kernel to try it out (rather than imaging a new card).
    Software PWM was mentioned, is it any good for servo control or just a little too slow?

    Anyway, keep it up, as usual quality stuff!

    Cheers.

    • Thanks Tim. Hardware PWM has been working as part of WiringPi for a long time. I think I got the motor program for the Gertboard working back in December 2012. I don’t really know how that affects the kernel to be honest (there be dragons LOL). I haven’t tried it with a servo.

      It offers other expanders too, (I have tried the SPI versions), soft PWM (not tried yet), some sound tones (not tried yet) and some other bits like Gertboard, PiFace, PiGlow support etc.

      I know other people have used servoblaster (C library I believe) with some success for servos with soft pwm, but I’m sceptical if Python is really suitable for servo PWM as it needs to be very precisely timed.

  3. Hi

    Great tutorial!

    I’m trying to add a second MCP23017 to my setup. The first is fine at address 0x20, and when I give the command [sudo i2cdetect -y 0] I see address 0x20 show up. However, after connecting the second MCP23017, I do not see a second address with this command.

    Is this normal – do you get the same thing? Does this command only show the first address only?

    • What have you done with the three address wires? If you’ve grounded all three of them, you’ve given it the same address as the first one.
      You need to connect one of them to 3V3 to give the chip a different address from the first one. It doesn’t really matter which one. In this way you have eight possible addresses, where GND = 0 and 3V3 = 1
      A3A2A1
      0 0 0 = 0x20
      0 0 1
      0 1 0
      0 1 1
      1 0 0
      1 0 1
      1 1 0
      1 1 1 = 0x27

      • I think my problem is that i’m not using wiring Pi. I copied a bit of code from another webise before I saw your page, and it uses smbus to set things up – which I can’t fathom how to add a second MCP23017.

        Some snippets from the code:

        —————-

        bus = smbus.SMBus(0)

        address = 0x20

        bus.write_byte_data(address,0x00,0x00) # Set all of bank A to outputs
        bus.write_byte_data(address,0x01,0x00) # Set all of bank B to outputs

        def set_led(data,bank): #means bank1 or bank0…simple
        #print “set_led bank=” + str(bank) + ” data=” + str(data)
        if bank == 1:
        bus.write_byte_data(address,0x12,data)
        else:
        bus.write_byte_data(address,0x13,data)
        return

        —————-

        Either way, the ‘sudo i2cdetect -y 0’ command still only shows the 0x20 address. Weird.

        • That looks like Matt Hawkins’ work. We were both working on this at the same time. He went with straight i2c and I went with WiringPi.

          WiringPi makes it easier, (I think) but requires installing.

          This is going to sound like “nasty teach giving extra homework”, but I think you should try WiringPi once you’ve finished the first way.
          It’ll be a great learning experience.

          Have fun

  4. I fixed it…and you know what it was? My lack of breadboard knowledge. I had one of the half size ones where the power rail breaks in the middle…my chip was getting no power!

    Thanks anyway!

    • We’ve all done it. By the way – you’ll almost certainly do it again at some point, but next time you’ll spot it much faster. :)

  5. Do you guys know if a) there is a smaller (shorter) alternative to the MCP23017 (I need it 1 pin shorter for my project!!) and b) if other chips will work with the SMBus/Wiring Pi code?

    Thanks again

    • One pin shorter?! Huh? ;-)
      There’s the MCP23008 which is an 18-pin chip, as opposed to the 28-pin MCP23017…

      If you’re prepared to write the driver code yourself (by studying the relevant datasheet), there’s no reason why any I2C chip shouldn’t work with the SMBus library! :-)

      • Yeah kinds trying to get 3 of these on a Humble Pi board to get the most out of it, I love tight circuits!

        Hmm I’m reasonably comfortable with the datasheets…how hard is it to write driver code? And what would I do with it? (the MCP23017 works without me touching code…so where would it go?)

        Thanks again

        • If you love tight circuits and you’re handy with a soldering iron, you can solder up the chips in “mid air” as long as you have insulation meaning they can’t electrically contact other parts ;-)
          And check out http://www.geocities.jp/Arduino_diecimila/obaka/project-2/index_en.html

          ‘driver code’ is basically everything that WiringPi does for you. When you’re using ‘raw SMBus’ that’s what most people count as ‘driver code’. Obviously how easy/difficult it is depends on what level of programming experience you have, how much of the chip’s functionality you need to access, and how comfortable you are with low-level bit-twiddling code.

          • I’ll probably have to give that a miss then! I’m relatively new to all of this. Great link, although not sure that wiring goes by the book ;)

    • If you don’t need all 16 ports on the last chip, you could just bend up the top two pins (1 & 28) and lose two ports. You’d still get 14 though.

  6. Hey just trying to use this chip with an 8×8 LED matrix.

    I’m getting some funny results, I can’t seem to set any of the MCP pins as a ground, and specifically, a ground that I can almost “turn on” when required, to give a selected ground power to selected LEDs.

    Any ideas? (Long shot!!)

    • You might be running into the current limitations of the chip. It can’t provide very much current. I’ve forgotten the details, but it’s in the data sheet.

  7. Where can I find a write-up of the WiringPi2 functions/methods for Python3, including descriptions of parameters being passed through “module.method(parameter list)”? I could muddle through the source code, but that seems like an awful lot of work!

    • As far as I know, what you find on here is the only available documentation for WiringPi2 for Python.

      But the good news is that the C documentation is pretty good on Gordon’s site and you can work out most things from that.
      wiringpi.com

  8. Hello,
    Thank’s a lot for that tutorial.
    I have bought the necessary but i have a pb.
    When i want to execute the python script, i can read :

    pi@raspberrypi ~/scripts $ sudo ./gpioextender2.py
    import.im6: unable to open X server `’ @ error/import.c/ImportImageCommand/368.
    ./gpioextender2.py: 4: ./gpioextender2.py: Syntax error: Bad function name

    I have no x server launch on my raspbian OS.
    What’s wrong ?
    Thank’s in advance for your help.
    Nico33

    • Are you doing this in the command line or in LXTerminal?

      • I do that in command line with ssh.
        What is LXterminal ?

        • A way of getting a terminal in LXDE. Irrelevant if you’re using ssh.

          I don’t know what to suggest. There is a message about function names there? I discovered the hard way that if you choose an “obvious” function name, sometimes it messes things up. e.g. once I had a program called email.py which conflicted with a function called email, buried deeply in one of the modules I was using. It could be something like that?

          • Hah, I just had a similar problem in Perl recently! For years and years I’d been using my own read_file function, but then I needed to use a 3rd-party module that defined its own read_file function, so I had to change my function name and do a big search’n’replace over all my code files ;-)

    • That error looks a bit weird :-/
      Could you paste the full source code of your gpioextender2.py script to http://pastebin.com/ and then copy the relevant URL here?

      (LXTerminal is the default graphical terminal app on LXDE – which you obviously can’t be using if you’re not running an X server! ;-) )

      • here is the pastbin link :
        http://pastebin.com/1GiPKKka

        Thanks for your help.

        • Ah… you’re not supposed to call all three ‘setup’ functions, you’re supposed to choose just one numbering scheme from “BCM GPIO numbers” or “wiringpi numbers” or “P1 header pin numbers” and stick to using just that code section.

          • Oups … It’s a mistake.
            Here is the good file :

            pi@raspberrypi ~/scripts $ cat gpioextender.py
            import wiringpi2 as wiringpi
            from time import sleep

            wiringpi.wiringPiSetup() # initialise wiringpi

            wiringpi.pinMode(12, 2)

            pi@raspberrypi ~/scripts $ sudo ./gpioextender.py
            import.im6: unable to open X server `’ @ error/import.c/ImportImageCommand/368.
            from: can’t read /var/mail/time
            ./gpioextender.py: 4: ./gpioextender.py: Syntax error: Bad function name

          • Aha! Now the problem is obvious – you need to use
            sudo python gpioextender.py
            (or python3 if necessary) and then it should all work.
            Alternatively you could add
            #!/usr/bin/env python
            as the first line of your script, and then your
            sudo ./gpioextender.py
            invocation would work. Without the #! line, the bash shell try to execute “import” as a shell command rather than running your script via the python interpreter.

          • I am having a similar issue as Nico33 and Andrew are discussing above. Where I am not effectively telling my python interpretor what or how to run wiringpi. In playing with the execute command line: #!/usr/bin/ pythonN I think I got the program to execute, but the very next thing that happend is that I got a syntax error here:
            import wiringpi2 as wiringpi
            from time import sleep
            Syntax line 3 and both IDLE and Terminal pointed to the Fr in From? this lead me to believe that there was something mission in the line above “import wiringpi2 as wiringpi” . So I looked for wiringpi2 and was unable to find it. Even though I have downloaded and installed it momments previous.

            I am going to give it another couple of looks later today. But it seems that the call to wiringpi2 or wiringPi2 is not happy.

          • In Python code, you need to spell ‘from’ all lower case :-)

            The reason you can’t ‘see’ wiringpi2 is that it got installed into a python-specific system directory (can’t remember which one it uses off the top of my head).

          • Ah…I will have to look for wiringpi2, when I get back to the Pi tonight. I will post a transcript of my error codes as they pop up. Hopefully I will get this happening without too much more pestering.

            Dave

  9. Thank’s a lot for the time spent to explain to me !
    And it’s ok now.

  10. Hi There,

    Nice tutorial
    I am using mcp23017 chips and I was wondering if is there a code to set up all the cip’s pins as Outputs from a single line instead of using 16 lines and setting up each pin to output.

    wiringpi.pinMode(65, 1)
    wiringpi.pinMode(66, 1)
    wiringpi.pinMode(67, 1)
    .
    .
    .
    .

    Thanks
    Marius

    • No single line command as far as I know, but you could do them all in about 2 lines with a loop.

      for x in range(65,81):
          wiringpi.pinMode(x,1)
  11. I need to connect a lot of of these chip to a raspberry, so I need an external 5v power supply. I’m a beginner in electronic, could you provide a diagram to connect 2 or more of these chip with external 5v power supply without burn my raspberry?

    If I power my I/O chip with 5v … the GPA and SDA SCL pins works at 5v? right? so I need a MOSFET to connect it to raspberry…right?

    thank you

    • Best way to do it would be power the chips with 3v3 and use a Darlington array ULN2803 chip on each side to handle the current to power your devices.

      If you power your IO chip with 5V, I think you’ll toast the Pi.

      • I have read somewhere (I don’t know if is it true…) that if you connect several of these devices don’t work well with 3.3v. For this reason I want use 5v (I need 10 of these).
        I have found this diagramm…. What do you think about it?

        http://www.abelectronics.co.uk/docs/stock/raspberrypi/iopi/IOPi-schematic.pdf

        Thank you.

        • I guess if you try to power too much stuff from the Pi’s (limited) 3.3V power supply that might cause problems yeah. Should work fine if you also use an external 3.3V power supply though (or you could connect a 5V->3.3V regulator to your 5V power supply). Just make sure to remember to connect all the GNDs together.

          I’m not qualified to comment on schematics ;)

        • If you are drawing current to power output devices, e.g. LEDs, I would say that’s the case, but there should be enough to power a whole bunch of these chips, since you’re only powering the chip itself from the 3v3. Any current hungry outputs would be powered from the separate line (3v3, 5v or whatever you want) on the Darlington.

          If you want to use inputs as well, you’ll need a level converter or, as Andrew said below, a resistor divider.

        • According to the datasheet, this chip requires 1 mA to run. You could therefore power lots of them safely with the Pi’s 3V3 lines (which can handle a total of ~60mA Max), as long as you only use them for signalling, rather than powering outputs. Couple that with the Darlington idea, and a voltage divider for your inputs and you’re sorted.

          http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf

      • ….I need to receive a flow meter sensor input (5v) as well so…in case I use the ULN2803 chip, I can connect this input sensor to the pin output?

        ex: flow meter 5v -> (out) ULN2803 (in) -> MCP23017 3.3v

  12. Hello,
    I can’t seem to get a LED to light. But, I can detect my i2c chip when I use this command:
    sudo i2cdetect -y 1
    All I want to do is light a LED, so I changed your script to this:

    import wiringpi2 as wiringpi
    from time import sleep

    pin_base = 65 # lowest available starting number is 65
    i2c_addr = 0x20 # A0, A1, A2 pins all wired to GND

    wiringpi.wiringPiSetup() # initialise wiringpi
    wiringpi.mcp23017Setup(pin_base,i2c_addr) # set up the pins and i2c address

    wiringpi.pinMode(65, 1) # sets GPA0 to output
    wiringpi.digitalWrite(65, 0) # sets GPA0 to 0 (0V, off)

    # Note: MCP23017 has no internal pull-down, so I used pull-up and inverted
    # the button reading logic with a "not"

    wiringpi.digitalWrite(65, 1) # sets port GPA1 to 1 (3V3, on)

    The code runs without any errors but the LED does not light. I have checked and double checked my wiring and cannot figure it out. I also tried using this command:
    sudo i2cset -y 1 0x20 0x14 0x01
    When I run this, i get this error:
    Error: Write failed

    • Is the resistor too high a value?
      Does the LED work?
      Is the LED the right way round? (long leg towards the port, short leg towards GND)
      Is the LED connected to the right pin (8th down from the dimple, on the right hand side?)
      Have you tried a different pin on the port expander chip? e.g. the top right one (72 in wiringpi)

      It’s got to be something simple. Maybe you have a dogdy chip?

  13. That is how I found the problem. Took apart the circuit and tested all the wires. :)

  14. Hello,
    Have you any idea of the distance max in meter between the rasp and the MCP ?
    I want to have the raspberry in my home and the MCP next my swiming pool.
    Thanks

    Nico33

  15. Hey,
    Great tute!

    I’ve connected the MCP23017 chips to a 16 channel relay board and by doing this I’ve discovered that when the pins are set as outputs and turned off eg:

    wiringpi.pinMode(65, 1)
    wiringpi.digitalWrite(65, 0)

    They have a voltage output of 0.14V which isn’t much i know but it is still enough to trip the relays. On further investigation when turned on “wiringpi.digitalWrite(65, 1)” the output voltage is 3.44V (3.3+0.14). Any ideas why this is?

    Also is there a problem setting them to inputs to effectively turn them off? This gives the output voltage of 0V.

    Cheers,

    Kip

    • Don’t most relay boards trip at 0 and switch off at 1 (i.e. 3v3 or 5v)? Could that be what you’re seeing?

      • I know that type of board and i dont think is is and if it were i should of seen them turn off at 1. I would of thought that they would only trip at 3v3 or at 5v but they seem to trip from the 0.14v which the MCP23017 chip is outputting (pretty consistent on the multimeter) when the pin is set as an output.

        I’ve managed to solve the problem by turning them from outputs to inputs every time i want to turn the relays off and on. A bit hacky i know but it does the trick.

        Chuck a miltimeter on one of the pins and see if you get the same.

        • Place a 220ihm resistor between the pin and ground. This will make sure that the output is zero when the state of the pin is zero.

  16. Hello

    I tried to make my LED blinks but it doesnt. I try running the code with the LX terminal and have no error but the LED doest light up. I tried to figure out this prblem for few days and i have no idea what is wrong. I really need your help. Thank you :)

    • To help you, we need a good, clear, photo of your wiring. It’s almost certainly a wiring issue.
      We also need a proper description of what you’ve done. For example you didn’t say what sort of Pi you’re using.

      It’s impossible to help you without the proper information. Ordinarily I’d suggest asking in the forums, but they seem to be down at the moment due to massive traffic on the RPi site because of the Pi 2 launch.

      • Now i got the LED light up with pin base 65. But now i have different problem where when i change to another pin such as pin base 66, the LED does not light up. I just change the pin base in the coding as well as the position of the LED at the mcp23017 chip to pin 66.

  17. Hello There,

    I use https://www.abelectronics.co.uk/products/3/Raspberry-Pi-Model-A-and-B/18/IO-Pi as port expansion

    this does not work with your code

    after the launch, there are already problems with finding the wiringpi2 file

    could you help me?

  18. Do you have any further information about what the particular function calls are from wiringPi2 for Python and the SPI interface. I’m trying to interface to an ST Microelectronics L6470 stepper chip that has an SPI communications. For example, to tell the L6470 chip to RUN, I need to send a binary string 8 bits in length.

  19. I would like to read all the pins without using a for loop isn’t there any function there that can do it ? Since that the the I2C can send 8 bit at once or something like that

  20. I have an old Raspi.IO-Duino that I would like to use as vanilla MCP2307 from Pi. It doesN#t however show up on I2Cdetect, and I cannot see how to get at the 3 address pins A1/A2/A3 ( of the MCP23017 pins 15-17 when installed in the RaspiIO-Duino.

    • Are you talking about using it in the prototyping area? That’s the only way it would work on a Duino. You can’t use it in place of the ATMEGA chip because the tracking on the PCB would be all wrong.

Leave a Reply