The GPIO expander MCP23017 with Arduino and Raspberry Pi is the standard solution for projects that need more digital I/O pins than available on your development board. MCP23017 adds 16 fully configurable GPIO pins via I2C — up to 8 chips can be chained on a single I2C bus, giving you 128 additional pins for matrix keyboards, relay banks, LED arrays, and more.
Table of Contents
- MCP23017 Overview
- Wiring to Arduino and Pi
- Arduino Library and Code
- Raspberry Pi Python Code
- Interrupt-Driven Input
- Indian Project Applications
- Frequently Asked Questions
MCP23017 Overview
Microchip’s MCP23017 is a 16-bit I/O port expander using I2C (400 kHz fast-mode capable). It has two 8-bit ports (PORTA and PORTB), each with independent direction, pull-up resistor, polarity inversion, and interrupt settings. The three address pins (A0, A1, A2) allow addressing up to 8 devices on the same I2C bus (addresses 0x20–0x27). Available in DIP-28 package for easy breadboard prototyping — priced ₹40–80 from Indian component suppliers.
Wiring to Arduino and Pi
MCP23017 to Arduino Uno (5V system):
| MCP23017 Pin | Arduino Uno |
|---|---|
| VDD | 5V |
| GND | GND |
| SCL | A5 (with 4.7kΩ pull-up) |
| SDA | A4 (with 4.7kΩ pull-up) |
| RESET | 5V (tie high for always-on) |
| A0, A1, A2 | GND (address 0x20) |
| INTA, INTB | Optional: connect to D2 for interrupts |
For Raspberry Pi (3.3V I2C): Use VDD = 3.3V. MCP23017 operates down to 1.8V — fully compatible at 3.3V. I2C pull-ups to 3.3V.
Arduino Library and Code
Install the Adafruit MCP23017 library via Arduino Library Manager.
#include <Adafruit_MCP23X17.h>
Adafruit_MCP23X17 mcp;
void setup() {
Serial.begin(115200);
if (!mcp.begin_I2C(0x20)) { // Address 0x20 (A0/A1/A2 = GND)
Serial.println("MCP23017 not found!");
while(1);
}
// Configure GPIO pins
for (int i = 0; i < 8; i++) {
mcp.pinMode(i, OUTPUT); // PORTA (0-7): outputs (relay/LED control)
}
for (int i = 8; i < 16; i++) {
mcp.pinMode(i, INPUT_PULLUP); // PORTB (8-15): inputs (buttons/sensors)
}
}
void loop() {
// Read all PORTB buttons
for (int i = 8; i < 16; i++) {
bool pressed = !mcp.digitalRead(i); // Active low with pull-up
if (pressed) {
mcp.digitalWrite(i - 8, HIGH); // Turn on corresponding LED on PORTA
}
}
delay(50);
}
Raspberry Pi Python Code
import smbus2
import time
MCP23017_ADDR = 0x20
IODIRA = 0x00 # I/O direction for PORTA
IODIRB = 0x01 # I/O direction for PORTB
GPIOA = 0x12 # GPIO PORTA
GPIOB = 0x13 # GPIO PORTB
GPPUA = 0x0C # Pull-ups for PORTA
bus = smbus2.SMBus(1) # I2C bus 1 on Raspberry Pi
# Configure PORTA as outputs, PORTB as inputs with pull-ups
bus.write_byte_data(MCP23017_ADDR, IODIRA, 0x00) # All outputs
bus.write_byte_data(MCP23017_ADDR, IODIRB, 0xFF) # All inputs
bus.write_byte_data(MCP23017_ADDR, GPPUA, 0xFF) # Enable pull-ups on PORTB
# Write to PORTA (turn on all 8 outputs)
bus.write_byte_data(MCP23017_ADDR, GPIOA, 0xFF)
# Read PORTB
portb_state = bus.read_byte_data(MCP23017_ADDR, GPIOB)
print(f"PORTB state: {portb_state:08b}")
Interrupt-Driven Input
MCP23017 can generate interrupts when any configured input changes — avoiding continuous polling. Connect INTA to Arduino INT0 (D2) for interrupt-driven keyboard or button reading, critical for responsive Indian security system keypads or industrial panel buttons.
// Enable interrupt on PORTB pin change
mcp.setupInterrupts(true, false, LOW); // Mirrored, open-drain, active LOW
mcp.setupInterruptPin(8, CHANGE); // Interrupt on any change of pin 8
// Arduino ISR
attachInterrupt(digitalPinToInterrupt(2), mcpISR, FALLING);
volatile bool mcpInterrupt = false;
void mcpISR() { mcpInterrupt = true; }
Indian Project Applications
- 16-zone intrusion alarm panel with zone monitoring LEDs
- Industrial relay bank controllers (8+ relays for factory automation)
- Matrix keyboard scanning for ATM PIN pads and access control
- Smart home light switch expansion (Indian buildings with 8–16 light circuits)
- Agricultural sensor multiplexing (soil moisture across multiple zones)
Frequently Asked Questions
How many MCP23017 chips can I daisy-chain?
Up to 8 chips on a single I2C bus (addresses 0x20–0x27), giving 128 additional GPIO pins. For more, use multiple I2C buses or a different expander.
Can MCP23017 drive relays directly?
Not directly. MCP23017 GPIO sink/source maximum is 25 mA. Use a ULN2003 transistor array or individual transistors to drive relay coils from MCP23017 outputs.
Is MCP23017 available in India?
Yes. Available from Rajiv Gandhi Electronics (Mumbai), SP Road (Bengaluru), Lamington Road, and online from Robu.in and Amazon India for ₹40–80 per IC.
Add comment