Built-in project · Arduino Uno R3

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.

More pins · Arduino Uno R3live0.000 s 0.00x
Hold the button
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// 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.