blemasle / arduino-mcp23017 Goto Github PK
View Code? Open in Web Editor NEWComplete support of MCP23017
License: MIT License
Complete support of MCP23017
License: MIT License
the library use WRIE default ?
but some board have two i2c-bus or more,
how to use another i2c-bus?
Hi,
so I'm experiencing a weird problem, that I can't identify correctly.
In the Arduino (I'm using an Arduino Uno, 2.2K pull-ups on I²C-bus) setup function I do the following configuration:
#define i2c_address_ioe_address 0x27
#define i2c_address_ioe_data_misc 0x20
MCP23017 mcp_address = MCP23017(i2c_address_ioe_address), mcp_data_misc = MCP23017(i2c_address_ioe_data_misc);
mcp_address.init();
mcp_data_misc.init();
mcp_address.portMode(MCP23017Port::A, 0); //Port A as output
mcp_address.portMode(MCP23017Port::B, 0); //Port B as output
mcp_data_misc.portMode(MCP23017Port::A, 0); //Port A as output
mcp_data_misc.portMode(MCP23017Port::B, 0b11110000); //Port A partly as output
In the loop, I have a test program, which turns each pin on individually (all others 0, the tested pin to one; I'm ignoring the ones that are configured as input ofc) to test if the output is working. I monitor the pin states with a 28 pin logic analyzer and therefore see which pin is working. To set the pin states I use the below functions.
uint16_t address = some_value;
mcp_address.write(address);
gpio->mcp_data_misc.writePort(MCP23017Port::A, data);
mcp_data_misc.digitalWrite(singlePin, 0);
mcp_data_misc.digitalWrite(singlePin, 1);
My issue is that if I write any pin to the mcp_address-module, pin 10 of the mcp_data_misc-module is not changing its state anymore.
Obviously, I thought this might be a PCB issue (schematic and layout of the PCB for reference). However, I tried 2 copies of the PCB and the issue persists.
One of those PCBs I already tested months ago with the MCP23017-library of WiringPi (obv. on a Raspberry Pi; I had level conversion there for 3.3V RPi GPIO to 5V MCP23017 levels) and back then all pins were working in a similar test.
So my question: Is there anything one has to keep in mind when working with multiple MCP23017? Has anybody experienced a similar issue? Is my configuration or the functions I use wrong?
TY for any help in advance.
I imagine it might, but just thought I'd ask before I jump in
I found out today that Microchip discovered an issue in their MCP23017 chip where under certain circumstances the I2C SDA signal may become corrupted when the chip’s GPA7 and/or GPB7 pins are used as inputs. For this reason, they updated the datasheet to reflect that those pins should only be used as outputs.
I'm hopeful that a silicon revision is in the works, but I wanted to alert the library maintainer in case they were unaware of the issue.
I'm just letting you know that the Arduino library manager sends you to:
https://github.com/blemasle/arduino-mcp23107 when you click "More Info". It should send you too: https://github.com/blemasle/arduino-mcp23017
The init() method enables the pull-up resistors by default.
this means that there is 5V on each pin. Even if I then configure the pins as output, there will be a very short time that a weak 5V is present at the output.
This is really undesirable.
In my case, my Arduino board is powered with 16V AC.
This is then converted to DC, and from that DC voltage, I make 9 volts with a step-down converter and 5 volts with a linear regulator to power my circuit. I'm controlling solenoids from that stabilized DC voltage. These are activated with a transistor connected to the MCP23017 with an appropriate base resistor.
At power-on, the pull-ups are activated, activating all 16 solenoids. They draw to much current, causing the DC voltage to drop and this causes a brown-out reset. (and the cycle starts again. Arduino starts, executes init() method, activates all solenoids, brown out reset, ....)
EDIT:
I've realized: YES, this library CAN handle up to 8 of the MCP23017 panels, each with different address.
The Readme.md could be enhanced a tiny bit more to make that clear:
Unlike most Arduino library, no default instance is created when the library is included.
It's up to you to create one with the appropriate chip I2C address.
Maximum 8 boards can be attached to one I2C bus. Address goes from (hexa) 0x20 - 0x27
#include <Arduino.h>
#include <MCP23017.h>
MCP23017 mcp1 = MCP23017(0x20);
// ...
MCP23017 mcp8 = MCP23017(0x27);
Just curious if this library is capable with ESP8266/ESP32?
On the 23017 Arduino Library, I changed the delay statement for the switch bounce to checking the io pin according to the timimg on the data sheet instead of waiting the 200 milliseconds. For me the I2C is slow enough without waiting 200ms every time a switch is pressed
Hi!
program code
#include <Wire.h>
#include <MCP23017.h>
#define i2c_mcp23017_ADDR_000 0x20
MCP23017 mcp23017_0x20 = MCP23017(i2c_mcp23017_ADDR_000);
void setup() {
Serial.begin(9600);
Wire.begin();
mcp23017_0x20.init();
for (uint8_t i = 0; i < 16; i++) mcp23017_0x20.pinMode(i, INPUT);
Wire.beginTransmission(i2c_mcp23017_ADDR_000);
Wire.write(0x02);
Wire.write(0xFF);
Wire.endTransmission();
Wire.beginTransmission(i2c_mcp23017_ADDR_000);
Wire.write(0x03);
Wire.write(0xFF);
Wire.endTransmission();
}
void loop() {
if (mcp23017_0x20.digitalRead(2)) {
Serial.println("pin2 = HIGH");
}
else {
Serial.println("pin2 = LOW");
}
Serial.println(mcp23017_0x20.readPort(MCP23017_PORT::A), BIN);
Serial.println(mcp23017_0x20.readPort(MCP23017_PORT::B), BIN);
delay(1000);
}
COM port monitor
pin2 = LOW
10000000
10000000
pin2 = LOW
10000100
10000000
pin2 = LOW
10000100
10000100
pin2 = HIGH
10000101
10000100
pin2 = LOW
10000100
10000100
Pavel
In MCP23017.cpp line 41 setting of OUTPUT is:
iodir = readRegister(iodirreg);
if(mode == OUTPUT) iodir |= _BV(pin);
else iodir &= ~_BV(pin);
but from datasheet:
3.5.1 I/O DIRECTION REGISTER
Controls the direction of the data I/O.
When a bit is set, the corresponding pin becomes an input.
When a bit is clear, the corresponding pin becomes an output.
So please correct
Thanks
I am using two mux (for the moment) to read a keyboard matrix, one mux uses all pins of both ports as outputs, the other one only 7 of port A as inputs (there is a diode from col to row on each key). The MCU is a teensy 4.1.
I am using a Serial.println(mcpRows.readPort(MCP23017Port::A), BIN);
to check the activated rows but I am getting some weird output, at first it seems to shows the 8 pins, then when I start pressing a key it shows 6 digits, then maybe only one, 4, etc. any ideas what can be the issue ?
Code:
#include <Arduino.h>
#include <Wire.h>
#include <MCP23017.h>
MCP23017 mcpCols = MCP23017(KBD_COL_MUX_ADDR, Wire1);
MCP23017 mcpRows = MCP23017(KBD_ROW_MUX_ADDR, Wire1);
const int muxPorts[] = {
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00100000,
0b01000000,
0b10000000,
};
void setup() {
Serial.begin(115200);
// Setup I2c (default ports)
Wire.begin();
// Setup I2c (second port)
Wire1.begin();
mcpCols.init();
mcpCols.portMode(MCP23017Port::A, 0); // Port A output
mcpCols.portMode(MCP23017Port::B, 0); // Port B output
mcpCols.writeRegister(MCP23017Register::GPIO_A, 0x00);
mcpCols.writeRegister(MCP23017Register::GPIO_B, 0x00);
mcpRows.init();
mcpRows.portMode(MCP23017Port::A, 0b11111111, 0b00000000, 0x00); // Port A input,no pull up, ipolb
mcpRows.writeRegister(MCP23017Register::GPIO_A, 0x00);
}
void loop() {
/* Matrix buttons handling */
for (int col = 0; col < 15; col++) {
if (col < 8) {
// Clear bank B
mcpCols.writePort(MCP23017Port::B, 0x00000000);
// Bank A
mcpCols.writePort(MCP23017Port::A, muxPorts[col]);
if (VERBOSE) {
Serial.printf("COLA %d\t", col);
}
} else {
// Clear bank A
mcpCols.writePort(MCP23017Port::A, 0x00000000);
// Bank B
// Remove 8 to start from 0 on the second bank
mcpCols.writePort(MCP23017Port::B, muxPorts[col-8]);
if (VERBOSE) {
Serial.printf("COLB %d\t", col);
}
}
// Get rows status
// byte rowStatus = mcpRows.readPort(MCP23017Port::A);
if (VERBOSE) {
Serial.println(mcpRows.readPort(MCP23017Port::A), BIN);
}
// For debugging purposes
delay(10);
}
}
example output:
COLA 0 10011000
COLA 1 10011000
COLA 2 10011000
COLA 3 10011000
COLA 4 10011100
COLA 5 10011100
COLA 6 11100
COLA 7 11000
COLB 8 11000
COLB 9 11000
COLB 10 11000
...
COLB 13 11001
COLB 14 11001
COLA 0 11001
COLA 1 11001
COLA 2 11001
COLA 3 11001
...
COLB 14 1000
COLA 0 1000
COLA 1 1000
COLA 2 1000
COLA 3 1001000
COLA 4 1001000
COLA 5 1001000
COLA 6 0
COLA 7 0
COLB 8 0
COLB 9 0
COLB 10 0
COLB 11 0
...
COLA 5 0
COLA 6 0
COLA 7 0
COLB 8 0
COLB 9 0
COLB 10 0
COLB 11 0
COLB 12 0
COLB 13 0
COLB 14 0
COLA 0 0
COLA 1 0
COLA 2 1000000
COLA 3 1000000
COLA 4 1000000
COLA 5 0
COLA 6 0
COLA 7 0
COLB 8 0
COLB 9 0
Hi, thanks very much for the library. Does it support rotary encoders? I can't figure out how to get a proper reading.
I have a number of MCP23017 and rather than initialising each individually I attempted to use the following:
MCP23017 mcpi[4];
int address = 0x20;
for( int j = 0; j < 4; j++)
{
mcpi[j].MCP23017(address)
address++;
}
but get the error "no matching function for call to 'MCP23017::MCP23017()'
Are you able to confirm thus can be done and if so what am I doing wrong.
In the init for the MCP23017 the comments say that setting IOCON.ODR (bit 2) to 0 sets the interrupts to be open-drain.
This in fact sets the output to use the active drivers and the IOCON.INTPOL for active high and active low.
Created a PR to update the comments on the init function here #25
Thank you for the library.
Can you give an example on how to use your lib with software i2c? In my project I got the i2c blocked for other parts and want to use your lib to controll a mcp23017. I'm using an ESP32 Dev Board.
arduino-mcp23017/src/MCP23017.cpp
Line 3 in 346e14d
Hi,
I'm stuck with an interrupt issue and hoping to get some guidance.
I'm using 2 MCP23017 with an Arduino Mega on different interrupts and a couple of push buttons. MCPs are initialised in the same way, and the code to read them is the same, however the behaviour is slightly different.
Here's the outuput after pressing and releasing 2 push buttons, one connected to each MCP:
20:00:10.626 -> MCP1 Interrupted
20:00:10.626 -> Port A -> 11111101
20:00:10.626 -> Port B -> 11111111
20:00:13.056 -> MCP4 Interrupted
20:00:13.056 -> Port A -> 11111101
20:00:13.056 -> Port B -> 11111111
20:00:13.148 -> MCP4 Interrupted
20:00:13.148 -> Port A -> 11111111
20:00:13.148 -> Port B -> 11111111
So looks like MCP1 is only catching when I push down the button, but not the release. Any idea what could be causing this difference in behaviour?
Here's my initialisation code:
mcp1.init();
mcp1.portMode(MCP23017Port::A, 0xFF);
mcp1.portMode(MCP23017Port::B, 0xFF); //Port B as input
mcp1.interruptMode(MCP23017InterruptMode::Or);
mcp1.interrupt(MCP23017Port::A, FALLING);
mcp1.interrupt(MCP23017Port::B, FALLING);
mcp1.writeRegister(MCP23017Register::IPOL_A, 0x00);
mcp1.writeRegister(MCP23017Register::IPOL_B, 0x00);
mcp1.writeRegister(MCP23017Register::GPIO_A, 0x00);
mcp1.writeRegister(MCP23017Register::GPIO_B, 0x00);
mcp1.clearInterrupts();
pinMode(MCP1_INT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(MCP1_INT_PIN), MCP1_int, FALLING);
And here's how I read the values:
if(MCP1_interrupted)
{
Serial.println("MCP1 Interrupted");
MCP1_interrupted = false;
mcp1.interruptedBy(a, b);
mcp1.clearInterrupts(captureA, captureB);
currentA = mcp1.readPort(MCP23017Port::A);
currentB = mcp1.readPort(MCP23017Port::B);
Serial.print("Port A -> ");
Serial.println(currentA,BIN);
Serial.print("Port B -> ");
Serial.println(currentB,BIN);
mcp1.clearInterrupts();
}
Cheers,
Bruno
It seems that I miss something in the PortCoypOnInterrupt Example.
My setup uses an Arduino MEGA in conjunction with the MCP23017
I attached buttons to port B (input port) that connect the MCP pins on port B to ground when pressed.
Port A pins serve as outputs for LEDs.
When I run the example and I press any of the buttons the corresponding pin on portA turns on.
The interrupt routine has been called and the interrupt has been handled.
However, after the first interrupt no further interrupts occur anymore, neither on the same pin nor on any other input pin.
As I understand the default input mode is with pull up, so after releasing the button (disconnecting ground) the input pin should return to high.
Any idea why subsequent interrupts are ignored or don't get through?
There is also a SPI version of that chip. Why not implementing that chip also?
Compiling on Arduino IDE 1.8.12 for Arduino 33, seems to be necessary to add
#define _BV(bit) (1 << (bit)) in the MCP23017.h .
Compiling .pio/build/nodemcuv2/libf5a/MCP23017_ID6001/MCP23017.cpp.o
.pio/libdeps/nodemcuv2/MCP23017_ID6001/src/MCP23017.cpp:3:56: error: default argument given for parameter 2 of 'MCP23017::MCP23017(uint8_t, TwoWire&)' [-fpermissive]
MCP23017::MCP23017(uint8_t address, TwoWire& bus = Wire) {
^
In file included from .pio/libdeps/nodemcuv2/MCP23017_ID6001/src/MCP23017.cpp:1:0:
.pio/libdeps/nodemcuv2/MCP23017_ID6001/src/MCP23017.h:67:2: note: previous specification in 'MCP23017::MCP23017(uint8_t, TwoWire&)' here
MCP23017(uint8_t address, TwoWire& bus = Wire);
Default parameter has been specified both here https://github.com/blemasle/arduino-mcp23017/blob/master/src/MCP23017.cpp#L3 and here https://github.com/blemasle/arduino-mcp23017/blob/master/src/MCP23017.h#L67
It should only be set in header-file!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.