MCP23017 I²C GPIO Expander

Turn two MCU pins into sixteen general-purpose pins — perfect when you've run out of GPIO and don't want a bigger board.

Difficulty: Breadboard. Estimated build time: about 40 minutes. Estimated parts cost: about US$5.50. 9-line bill of materials. Compare supplier offers when available. A sixteen-LED chaser that lights every output of an MCP23017 in sequence, driven by an Arduino over a two-wire I²C bus.

Wire the chip

MCP23017 in DIP-28 sits across the breadboard's centre gap. Pins 9 and 10 are VCC and GND — connect 5 V and ground. Pins 12 and 13 are SCL and SDA; wire them to A5 and A4 on the UNO with 4.7 kΩ pull-ups to 5 V (some breakouts include the pull-ups). Pins 15, 16, 17 are the address pins A0/A1/A2 — tie all three to GND to set the address 0x20. Pin 18 is RESET; tie it to 5 V through a 10 kΩ resistor so the chip starts in a known state.

Wire 16 LEDs

Port A is pins 21–28 and Port B is pins 1–8. Wire one LED through a 330 Ω resistor to each of the sixteen port pins, with the cathodes commoned to GND. The MCP23017 sinks/sources up to 25 mA per pin, so even a typical 10 mA LED is well within budget.

Install the Adafruit_MCP23X17 library

In the Library Manager, search for "Adafruit MCP23017" and install. The library wraps the I²C calls into a friendly mcp.pinMode(0, OUTPUT) / mcp.digitalWrite(0, HIGH) API — pin numbers 0–7 are Port A, 8–15 are Port B. Test by setting one pin HIGH; the corresponding LED should light.

Run the chaser

In loop(), for each value of i from 0 to 15, set all pins LOW then set pin i HIGH and delay 80 ms. The result is the classic Knight-Rider chase across two rows of LEDs. Behind the scenes, every digitalWrite is being routed through a single I²C transaction — about 30 µs at 400 kHz — yet the API feels exactly like using local pins. Once that works, you can read sixteen inputs the same way for big keypads, or mix four LEDs and twelve buttons however you like.