Arduino + MCP23017: Turning an LED On with a Button

Here it is shown how to expand Arduino's I/O using MCP2307 I/O expander IC with example of a button-controlled LED.

The MCP2307 is a 16-bit input/output (I/O) expansion chip manufactured by Microchip Technology that can be used to add extra input/output pins to a microcontroller or processor or boards like Arduino, Raspberry Pi Pico 2, PIC, AVR microcontroller, ESP32-CAM etc. The MCP2307 is connected to the microcontroller or Arduino like boards using I2C communication interface. That means only two pins of the microcontroller/Arduino like boards are required. It has 16 bidirectional I/O pins and supports interrupt for event driven input handing. Each pin can source/sink upto 25mA. Its operating voltage is 1.8V to 5V and has low power standby current, as low as 1uA.

MCP2307 I/O expander IC

MCP23017 I/O expander IC Arduino Example Circuit

To illustrate how to use MCP23017, we will use Arduino and connect Arduino with MCP23017 with I2C pins. A push button is connected to MCP23017 GPB0 pin on one side and grounded on the other side. The LED in series with 220Ohm resistor is connected to the GPA7 pin of the MCP23017 expander IC. The circuit diagram is shown below.

MCP23017 IO expander IC Arduino Example

When the push button is pressed, the LED is turned. Here we have not used the interrupt feature of the MCP23017. Instead to detect the push button state, Arduino is programmed to continuously read the state of the GPB0 pin using the I2C read command. Once the button pressed and pin grounded or otherwise, the GPB0 pin state is read. This method of repeatedly reading the state of the pin is called Polling method. Watch the following to see how the circuit works.


Arduino MCP23017 Programming

The following is the program code.
// MCP23017 Button-to-LED, POLLING version (no interrupt) — for diagnosis
#include <Wire.h>

#define MCP23017 0x20
#define IODIRA  0x00
#define IPOLB   0x03
#define GPPUB   0x0D
#define GPIOB   0x13
#define GPIOA   0x12

uint8_t portA = 0;

void I2Cwrite(uint8_t addr, uint8_t reg, uint8_t val) {
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.write(val);
  Wire.endTransmission(true);
}

uint8_t I2Cread(uint8_t addr, uint8_t reg) {
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.endTransmission(false);
  Wire.requestFrom(addr, (uint8_t)1);
  return Wire.read();
}

void setup() {
  Wire.begin();
  I2Cwrite(MCP23017, IODIRA, 0x00); // Port A = all outputs (LED)
  I2Cwrite(MCP23017, GPPUB,  0xFF); // Port B pull-ups on (button)
  I2Cwrite(MCP23017, IPOLB,  0xFF); // Invert polarity: pressed = 1

  Serial.begin(9600);
  while (!Serial) { ; }
  Serial.println("Polling Button-to-LED Ready!");
}

void loop() {
  uint8_t portB = I2Cread(MCP23017, GPIOB); // plain poll, no interrupt

  if (portB & B00000001) {      // B0 pressed
    portA |= B10000000;
    Serial.println("Button B0 pressed -> LED ON");
  } else {                      // B0 released
    portA &= B01111111;
    Serial.println("Button B0 released -> LED OFF");
  }

  I2Cwrite(MCP23017, GPIOA, portA);
  delay(100);
}

This code uses an Arduino to talk to an MCP23017 chip (an I/O expander that adds extra pins) over I2C: in setup(), it configures Port A as outputs for the LED and Port B as inputs with pull-up resistors for the button, then in loop(), it simply asks the chip "what's the button doing right now?" every tenth of a second, checks if that reading shows the button pressed, and if so flips on a bit for the LED (or off if released) and sends that result back to the chip — so the light just continuously follows whatever the button's current state is, with no waiting or interrupts involved.

Another similar I/O expansion method and examples are described in the blog post How to Expand ATtiny13 Outputs with 74HC595 Shift Register and Control a 16x2 LCD with Only 2 Wires — Arduino + MCP23017 I2C Expander.

Note: You can download the proteus project which contains schematic and program code from the link below.

Download MCP23017 Arduino Button LED Proteus Project


Post a Comment

Previous Post Next Post