MCP23017 IO Expansion Board SKU: CQRMCP23017A
Contents
Description
The MCP23017 IO Expansion Board expands 2 signal pins as 16 I/O pins based on the I2C bus, up to 8 MCP23017 IO Expansion Board can be used at the same time, providing up to 128 I/O pins, it is compatible with both 3.3V and 5V levels.
Features
- I2C controlled, expands 2 signal pins as 16 I/O pins
- I2C address configurable by shorting the A0/A1/A2 jumpers
- Up to 8 MCP23017 IO Expansion Board can be used at the same time, providing up to 128 I/O pins.
- Onboard voltage translator, compatible with 3.3V/5V level
- Comes with development resources and manual (examples for Raspberry Pi / micro:bit / Arduino / STM32)
Interface Description and Size
Connection Diagram
Connect to Arduino:
- Note: Do not connect the DuPont female single-head wire directly to the UNO R3 control board. You need to stack the sensor expansion board on the UNO R3 control board or connect the male-to-male Dupont wire on the Dupont female single-head wiring(bread wire).
- We connected the 4Pin interface of the sensor to the UNO R3 control board in the experiment.
Connect to Raspberry Pi:
- We connected the 4pin interface of the sensor to the Raspberry Pi 4B control board in the experiment.
Specifications
Sensor Specifications
- Operating Voltage: 5V/3.3V
- Interface: I2C (JST PA SMT 6-Pin interface to 2.54mm pitch pin header interface)
- Interrupt Pins: INTA, INTB
- Expansion I/Os: 16
- Dimension: 45.24mm * 31.79mm
- Mounting Hole Size: 3.0mm
Ocean Wire Specifications
- Cable specifications: 22AWG
- Material: Silicone
- Withstand Voltage: Less Than 50V
- Withstand Current: Less Than 1000MA
- Length: 21cm
- Line Sequence: Black-negative power supply, Red-positive power supply, Green-SDA, Blue-SDA, Yellow-INTA, Orange-INTB.
Demo for Arduino
//Note: Before uploading the code, the corresponding library file must be placed in the library file folder where the Arduino IDE is installed. #include <Wire.h> #include "MCP23017.h" // Connect pin SCL of the expander to SCL // Connect pin SDA of the expander to SDA // don't solder A0,A1,A2 (default) // Connect PA0 to a led MCP23017 mcp; byte arduinoIntPin1 = 2; byte arduinoIntPin2 = 3; byte arduinoInterrupt1 = 0; byte arduinoInterrupt2 = 1; volatile boolean awakenByInterrupt1 = false; volatile boolean awakenByInterrupt2 = false; byte mcpPinA = 7; byte mcpPinB = 15; void setup() { /*the param can be 0 to 7,the default param is 7.means the dafault device address 0x27. Addr(BIN) Addr(hex) param 010 0111 0x27 7 010 0110 0x26 6 010 0101 0x25 5 010 0100 0x24 4 010 0011 0x23 3 010 0010 0x22 2 010 0001 0x21 1 010 0000 0x20 0 */ Serial.begin(9600); Serial.println("Interrupt Test Start"); pinMode(arduinoIntPin1,INPUT); pinMode(arduinoIntPin2,INPUT); mcp.begin(7); mcp.setupInterrupts(true,false,LOW); mcp.pinMode(mcpPinA, INPUT); mcp.pullUp(mcpPinA, HIGH); // turn on a 100K pullup internally mcp.setupInterruptPin(mcpPinA,FALLING); mcp.pinMode(mcpPinB, INPUT); mcp.pullUp(mcpPinB, HIGH); // turn on a 100K pullup internall mcp.setupInterruptPin(mcpPinB,FALLING); for (int i = 0; i < 7; i++) { mcp.pinMode(i, INPUT); } for (int i = 0; i < 7; i++) { mcp.pullUp(i, HIGH); } for (int i = 8; i < 15; i++) { mcp.pinMode(i, OUTPUT); } } // The int handler will just signal that the int has happen // we will do the work from the main loop. void intCallBack1() { awakenByInterrupt1 = true; } void intCallBack2() { awakenByInterrupt2 = true; } void handleInterrupt1() { // Get more information from the MCP from the INT uint8_t pin = mcp.getLastInterruptPin(); uint8_t val = mcp.getLastInterruptPinValue(); Serial.println("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-"); Serial.println("the key has been pressed!!!"); Serial.print("the last interrupt Pin is:"); Serial.println(pin); Serial.print("the last interrupt value is:"); Serial.println(val); Serial.println("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-"); // we have to wait for the interrupt condition to finish // otherwise we might go to sleep with an ongoing condition and never wake up again. // as, an action is required to clear the INT flag, and allow it to trigger again. // see datasheet for datails. //while( ! (mcp.digitalRead(mcpPinB) && mcp.digitalRead(mcpPinA) )); while( ! (mcp.digitalRead(mcpPinA) )); // and clean queued INT signal cleanInterrupts1(); } void handleInterrupt2() { // Get more information from the MCP from the INT uint8_t pin = mcp.getLastInterruptPin(); uint8_t val = mcp.getLastInterruptPinValue(); Serial.println("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-"); Serial.println("the key has been pressed!!!"); Serial.print("the last interrupt Pin is:"); Serial.println(pin); Serial.print("the last interrupt value is:"); Serial.println(val); Serial.println("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-"); // we have to wait for the interrupt condition to finish // otherwise we might go to sleep with an ongoing condition and never wake up again. // as, an action is required to clear the INT flag, and allow it to trigger again. // see datasheet for datails. //while( ! (mcp.digitalRead(mcpPinB) && mcp.digitalRead(mcpPinA) )); while( ! (mcp.digitalRead(mcpPinB) )); // and clean queued INT signal cleanInterrupts2(); } // handy for interrupts triggered by buttons // normally signal a few due to bouncing issues void cleanInterrupts1() { EIFR = 0x01; awakenByInterrupt1 = false; } void cleanInterrupts2() { EIFR = 0x02; awakenByInterrupt2 = false; } // int this loop will flip the PA0 up and down void loop() { //PA0-PA6 input low level, PB0-PB6 output low level. for (int i = 0; i < 7; i++) { mcp.digitalWrite(i + 8, mcp.digitalRead(i)); } //PA7, PB7 low level trigger interrupt, print the value of the corresponding IO port as 0. attachInterrupt(arduinoInterrupt1,intCallBack1,FALLING); attachInterrupt(arduinoInterrupt2,intCallBack2,FALLING); //while(!awakenByInterrupt); // disable interrupts while handling them. detachInterrupt(arduinoInterrupt1); detachInterrupt(arduinoInterrupt2); if(awakenByInterrupt1) { handleInterrupt1(); } if(awakenByInterrupt2) { handleInterrupt2(); } }
Test Methods and Results
First, upload the test code on the UNO R3 control board with Arduino IDE software. Then, connect the cable according to the wiring method and power on by USB cable. PA0-PA6 input low level, PB0-PB6 output low level; PA0-PA6 input high level, PB0-PB6 output high level.
Next, turn on the serial monitor, and set the baud rate to 9600. When the interrupt signal is detected by D2, D3, the serial monitor will display the corresponding images.
Demo for Raspberry Pi
import smbus import time MCP23017_IODIRA = 0x00 MCP23017_IPOLA = 0x02 MCP23017_GPINTENA = 0x04 MCP23017_DEFVALA = 0x06 MCP23017_INTCONA = 0x08 MCP23017_IOCONA = 0x0A MCP23017_GPPUA = 0x0C MCP23017_INTFA = 0x0E MCP23017_INTCAPA = 0x10 MCP23017_GPIOA = 0x12 MCP23017_OLATA = 0x14 MCP23017_IODIRB = 0x01 MCP23017_IPOLB = 0x03 MCP23017_GPINTENB = 0x05 MCP23017_DEFVALB = 0x07 MCP23017_INTCONB = 0x09 MCP23017_IOCONB = 0x0B MCP23017_GPPUB = 0x0D MCP23017_INTFB = 0x0F MCP23017_INTCAPB = 0x11 MCP23017_GPIOB = 0x13 MCP23017_OLATB = 0x15 bus = smbus.SMBus(1) # Addr(BIN) Addr(hex) #XXX X A2 A1 A0 #010 0 1 1 1 0x27 #010 0 1 1 0 0x26 #010 0 1 0 1 0x25 #010 0 1 0 0 0x24 #010 0 0 1 1 0x23 #010 0 0 1 0 0x22 #010 0 0 0 1 0x21 #010 0 0 0 0 0x20 MCP23017_ADDRESS = 0x27 #Configue the register to default value for addr in range(22): if (addr == 0) or (addr == 1): bus.write_byte_data(MCP23017_ADDRESS, addr, 0xFF) else: bus.write_byte_data(MCP23017_ADDRESS, addr, 0x00) #configue all PinA output bus.write_byte_data(MCP23017_ADDRESS,MCP23017_IODIRA,0x00) #configue all PinB input bus.write_byte_data(MCP23017_ADDRESS,MCP23017_IODIRB,0xFF) #configue all PinB pullUP bus.write_byte_data(MCP23017_ADDRESS,MCP23017_GPPUB,0xFF) #only for debug for addr in range(22): print(bus.read_byte_data(MCP23017_ADDRESS,addr)) print("----------------Start to toggle all PinA, all PinB will read it----------------") while True: #configue all PinA output low level bus.write_byte_data(MCP23017_ADDRESS,MCP23017_GPIOA,0x00) #then PinB read the level from PinA, print 0 means all PinA are in low level print(bus.read_byte_data(MCP23017_ADDRESS,MCP23017_GPIOB)) time.sleep(0.5) #configue all PinA output high level bus.write_byte_data(MCP23017_ADDRESS,MCP23017_GPIOA,0xFF) #then PinB read the level from PinA, print 255 means all PinA are in high level print(bus.read_byte_data(MCP23017_ADDRESS,MCP23017_GPIOB)) time.sleep(0.5)
Test Methods and Results
1. Save the test code as a folder in the Raspberry Pi system.
2. The I2C communication function is used in the code. Since the Raspberry Pi does not enable the I2C function by default, you need to enable that before running the code.
A. Enter “sudo raspi-config” in the terminal to start the Raspberry Pi configuration interface.
B. Turn on the I2C function of Raspberry Pi according to the steps below.
Execute the following commands in the terminal to run the program. The 16 IO ports (PA0-PA7 PB0-PB7) on the expansion board cycle between low and high levels with an interval of 0.5 seconds. The output data on the terminal is shown in the picture below.
cd TS1698 ls sudo python TS1698.py