Tuesday 15 October 2019

(EN) MCP23017 I/O port expander - How to use it with Arduino



The MCP23017 chip is I/O port expander that uses the I2C communication protocol. You can connect it to your Arduino using only two pins (those needed for I2C communication) and get 16 more digital I/O ports in return.
Furthermore you can chain up to eight expander in series and get 128 digital ports, always at the small cost of two pins.

This is a simple circuit to explain you how to connect and use the MCP23017: connect a momentary button
to an expander port and a LED to another; Arduino, through the port multiplier, reads the state of the button (pressed or unpressed) and turns on the LED accordingly.




To make the circuit you need an Arduino (in this case a UNO R3), a breadboard, a led, a momentary button (normally open), a 220 Ohm resistor and a 10K Ohm resistor. Connect them together as follows:

  • connect the VDD port of the expander to + 5V;
  • connect the VSS port of the expander to Ground;
  • connect the SCL port of the expander to the SCL port of Arduino (pin A5 in the UNO board);
  • connect the SDA port of the expander to the SDA port of Arduino (pin A4 in the UNO board);
  • connect the A0, A1 and A2 ports of the expander to Ground;
  • connect the RESET port of the expander to + 5V using the 10K Ohm resistor;
  • connect one side of the momentary button to the GPA0 port of the expander, then connect the other side to Ground;
  • connect the anode (+) of the led to the GPA7 port of the expander using the 220 Ohm resistor;
  • connect the cathode (-) of the LED to Ground;
  • lastly supply power to the circuit through Arduino 5V and GND pins.



The pins 15, 16 and 17 of the MCP (namely A0, A1 and A2 ports) are very important because they set the I2C address of the expander according to the way they are connected, so you can assign a unique address to each MPC in a chain.
In the following table you can find the combinations of the three ports and the corresponding addresses:

Port connection

MCP23017
address
(max 8 units)

A0

A1

A2

GND
GND
GND
0
GND
GND
5V
1
GND
5V
GND
2
GND
5V
5V
3
5V
GND
GND
4
5V
GND
5V
5
5V
5V
GND
6
5V
5V
5V
7
tab.1 - Assigning the MPC an address

While in this other table a pin number is associated to each port of the expander:

MCP23017
pin

Port Name

Pin number to use
in Arduino sketch

21
GPA0
0
22
GPA1
1
23
GPA2
2
24
GPA3
3
25
GPA4
4
26
GPA5
5
27
GPA6
6
28
GPA7
7
1
GPB0
8
2
GPB1
9
3
GPB2
10
4
GPB3
11
5
GPB4
12
6
GPB5
13
7
GPB6
14
8
GPB7
15
tab.2 - Pin numbers

Now the Arduino sketch. To easily use the MCP23017 you need to install the "Adafruit MCP23017 Arduino Library" in the Arduino IDE . You can install the library via the Arduino IDE using the Library Manager (available from IDE version 1.6.2). A detailed guide on Arduino libraries install is available here.

Once the library is installed we can proceed with the sketch:


  1. #include <Wire.h>
  2. #include "Adafruit_MCP23017.h"
  3. Adafruit_MCP23017 mcp1;
  4. void setup() {  
  5.   mcp1.begin(0);
  6.   mcp1.pinMode(0, INPUT);
  7.   mcp1.pullUp(0, HIGH);
  8.   mcp1.pinMode(7, OUTPUT);
  9. }
  10. void loop() {
  11.   mcp1.digitalWrite(7, mcp1.digitalRead(0));
  12. }

Let's analyze the code block by block.

  1. #include <Wire.h>
  2. #include "Adafruit_MCP23017.h"
  3. Adafruit_MCP23017 mcp1;

We start including in the sketch the "Wire" library, which is already contained in the IDE and is necessary for I2C communication, and the library we have just installed. On line 3 we create the expander instance and we call it "mcp1"; you can give it any name you want.

  1.   mcp1.begin(0);
  2.   mcp1.pinMode(0, INPUT);
  3.   mcp1.pullUp(0, HIGH);
  4.   mcp1.pinMode(7, OUTPUT);

On line 6 the command mcp1.begin() is used to initialize the expander and to communicate its unique I2C address to Arduino; since in the circuit we made the gates A0, A1 and A2 are all connected to ground, the address between the brackets is 0 (see tab.1).

Then we set the mode of pin 0 (aka GPA0, see tab.2) and 7 (aka GPA7), to which the button (input) and the led (output) are connected respectively. On line 8 we activate the internal pull-up resistor for pin 0;  this resistor is present in all sixteen of the MCP23017 ports. As you can see, the Adafruit library allows us to set the expander pins as we would do with Arduino pins.

  1.   mcp1.digitalWrite(7, mcp1.digitalRead(0));

Finally in the loop() there are the two functions that read the state of the button and command the LED simultaneously; also in this case the commands are similar to those normally used for Arduino.

Note: the positioning of the Arduino SCL and SDA pins vary from board to board; refer your Arduino board pinout to find them.

Have fun with your expander.

No comments:

Post a Comment