More pins on an Arduino Uno
A PCF8574 and an MCP23017 on one I2C bus: a port with no registers walking a bit along its pins, and a port with a register for everything reading a button. The whole build, an Arduino Uno and 3 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
IntermediateRuns in your browser. Free, and no account needed.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Two port expanders on one I2C bus: a PCF8574 at 0x20 and an MCP23017 at 0x27.
//
// The PCF8574 has no registers at all. Every byte written is its eight pins,
// and a pin written 1 is only weakly high, so the LEDs on it run from 5 V
// through a resistor *into* the pin and light when their bit is 0. The sketch
// walks a single dark bit along four of them.
//
// The MCP23017 is a proper pair of ports: a direction register, pull-ups and
// push-pull outputs. GPB0 is an input with its pull-up on and a button to
// ground; GPA0 drives an LED to ground, lit while the button is held. Its
// RESET is tied high and A0 to A2 high too, which is address 0x27: none of the
// four pins is pulled inside the chip, and left floating the chip is simply
// not on the bus.
#include <Wire.h>
#include <Adafruit_MCP23X17.h>
const uint8_t PCF8574 = 0x20;
Adafruit_MCP23X17 mcp;
uint8_t step = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(PCF8574);
Serial.println(Wire.endTransmission() == 0 ? "PCF8574 at 0x20" : "no PCF8574 at 0x20");
if (!mcp.begin_I2C(0x27)) {
Serial.println("no MCP23017 at 0x27");
} else {
Serial.println("MCP23017 at 0x27");
}
mcp.pinMode(0, OUTPUT); // GPA0: the LED
mcp.pinMode(8, INPUT_PULLUP); // GPB0: the button
}
void loop() {
// One dark bit walking along P0..P3; the other four stay high, which is
// also how they would be read as inputs.
Wire.beginTransmission(PCF8574);
Wire.write((uint8_t)~(1 << step));
Wire.endTransmission();
step = (step + 1) % 4;
bool pressed = mcp.digitalRead(8) == LOW;
mcp.digitalWrite(0, pressed ? HIGH : LOW);
Serial.println(pressed ? "button held" : "button up");
delay(250);
}
Parts list
5 parts, plus the jumper wires. Every one is in the editor's parts bin.
How it is wired
5 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Arduino Uno R3 pin 5V; I/O expander, MCP23017 pin VDD; I/O expander, MCP23017 pin A0; I/O expander, MCP23017 pin A1; I/O expander, MCP23017 pin A2; I/O expander, MCP23017 pin RESET; I/O expander, PCF8574 pin VCC
- Ground: Arduino Uno R3 pin GND; I/O expander, MCP23017 pin VSS; I/O expander, PCF8574 pin GND; Pushbutton pin 2b
- Arduino Uno R3 pin A4; I/O expander, MCP23017 pin SDA; I/O expander, PCF8574 pin SDA
- Arduino Uno R3 pin A5; I/O expander, MCP23017 pin SCL; I/O expander, PCF8574 pin SCL
- I/O expander, MCP23017 pin GPB0; Pushbutton pin 1b
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.