Sony Arouje

a programmer's log

Digital I/O Expander for Arduino

with 5 comments

When we work with processor like Amega328 or ATTiny85 we will come to a situation like we are running short of GPIO pins. One option is to go for 40pin processors like Atmega16/32/324, etc. But there are some cons with 16/32, these chips doesn’t have PCINT (Pin change interrupt) and we cant use software serial. If we are not dealing with Software serial then we can use these MC’s without any issues. Some of the experiments I am doing, deals with Software serial, so I decided to use Atmega328. But I need more Digital I/O pins. To get more IO we can pair Atmega328 with GPIO expanders like MCP23017 or MCP23S17.

Keep in mind that MCP23017 talks via I2C and MCP23S17 talks via SPI. I prefer I2C as it uses two pins of my Arduino, SCL and SDA. SPI needs 4 pins, MISO, MOSI, SCK and RESET. Also in my system there are several other chips connected to I2C bus and thus deals with only one type of communication.

Lets see how to connect MCP23017 to Arduino

MCP23017 Pinout

 

As you can see we have 16 GPIO’s in MCP23017, 1-8 and 21 to 28.

Connection

  • 5v to pin 9
  • GND to 10.
  • Arduino SCL to pin 12
  • Arduino SDA to pin 13.
  • MCS23017 RESET pin to pin9 with a 1k Resistor.

Now we need to set the I2C address of this pin. You can connect upto 8 MCP23017 by changing connection to A0 to A2 (pin 15 to 17). For e.g. connect all three pins to GND will get an address of 0, connect A0 to VCC and A1 and A2 to GND will give an address of 1 and so on.

Here I am connecting all the pins to GND and I get an address of 0.

 

Schematic

schema

 

Here I am not detailed the connection to Atmega328. I focused on the connectivity between 328 and MCP23017. To see how to run an Atmega in standalone mode, check this post.

Edit: As Anon suggested in comments sections, I added a pullup resistor to SDA and SCL lines. I2C is open drain and without a pullup resistor the system will not work.

Arduino Sketch

I used Adafruit library to interact with MCP23017, you also can directly interact with expander by just using wire library. There is a good post explaining how to write data to MCP23017 without any library.

#include <Wire.h> #include "Adafruit_MCP23017.h" Adafruit_MCP23017 mcp; void setup() { mcp.begin(0); mcp.pinMode(1, OUTPUT); } void loop() { delay(1000); mcp.digitalWrite(0, HIGH); delay(1000); mcp.digitalWrite(0, LOW); }

 

Here port 0 is referring to pin 21.

 

Here I talks about I2C connectivity but you can also use SPI using MCP23S17.

These expanders are not limited to Atmegas we can use it with Raspberry pi’s or any other processors that supports I2C or SPI communication.

Happy hacking…

Written by Sony Arouje

June 14, 2016 at 10:41 am

Posted in Arduino

Tagged with , ,

5 Responses

Subscribe to comments with RSS.

  1. I2C should have pull-up resistors. The reason why this works in the first place is that there may be internal pull-ups enabled inside the MCU. But those pull-ups are way too weak to drive the I2C line up. Add about 2k2-4k7 ohm resistors between signals (SDA, SCL) and the VCC. If you have an oscilloscope you would see sharper edges of the signal.

    Anon

    June 19, 2016 at 8:56 pm

    • Thanks for notifying. In my case it was working fine. Later I read some post explaining the use but havent tried that yet. I will add the pullups and give it a try. Thanks once again for the feedback.

      Sony Arouje

      June 20, 2016 at 12:31 pm

    • Updated the schematic, thanks for notifying me.

      Sony Arouje

      June 23, 2016 at 12:44 am

  2. (MCS23017 RESET pin to pin9 with a 1k Resistor) – Why must you use the resistor?

    mohd rais

    January 19, 2020 at 10:42 am

    • I dont remember mohd, this was done couple of years ago and not doing any active work in this area now.

      Sony Arouje

      January 22, 2020 at 9:47 am


Leave a comment