I have a setup using 13 MCP23017 boards communicating on the I2C. Since it is possible only for 3-bit addressing, I am using TCA9546 for multiplexing the I2C bus: 5 on 1st channel, 4 on 2nd channel and 4 on the 3rd channel.
Initially everything seemed to work fine, but now I am facing issues with failures on the MCP23017 boards only on one channel of the multiplexer - Channel 0. The same microcontroller also drives some LEDs through 3 MOSFETs. As soon as I send a drive signal, the MCPs starts misbehaving. This I fear is because of the I2C picking up interference from the MOSFET signals only Channel 0 of the multiplexer. I managed to improve the performance by reducing the cable lengths but now I still see a failure every now and then.
To make it more robust, I am connecting the 5 MCP23017 boards to the Feather M4 bus directly and the rest of the 8 MCP23017 boards to the multiplexer.
Is there a solution changing the software or the hardware?
#include <MCP23017.h>
#include <I2C_Switch_driver.h>
// defines Pins
#define BACKLIGHT_PIN_1 5
#define BACKLIGHT_PIN_2 6
#define BACKLIGHT_PIN_3 9
// define TCA I2C Mux address
#define TCAADDR 0x70
I2C_Switch I2C_Switch(I2C_Switch_ADRESS_0);
// IO
MCP23017 Mcp1_1(MSP23017_ADRESS_0);
MCP23017 Mcp1_2(MSP23017_ADRESS_1);
MCP23017 Mcp1_3(MSP23017_ADRESS_2);
MCP23017 Mcp1_4(MSP23017_ADRESS_3);
MCP23017 Mcp1_5(MSP23017_ADRESS_4);
MCP23017 Mcp2_1(MSP23017_ADRESS_2);
MCP23017 Mcp2_2(MSP23017_ADRESS_3);
MCP23017 Mcp2_3(MSP23017_ADRESS_6);
MCP23017 Mcp2_4(MSP23017_ADRESS_7);
MCP23017 Mcp3_1(MSP23017_ADRESS_0);
MCP23017 Mcp3_2(MSP23017_ADRESS_1);
MCP23017 Mcp3_5(MSP23017_ADRESS_4);
MCP23017 Mcp3_6(MSP23017_ADRESS_5);
// IO initialization
uint8_t mcp1_1PortA = 0x00;
uint8_t mcp1_1PortB = 0x00;
uint8_t mcp1_2PortA = 0x00;
uint8_t mcp1_2PortB = 0x00;
uint8_t mcp1_3PortA = 0x00;
uint8_t mcp1_3PortB = 0x00;
uint8_t mcp1_4PortA = 0x00;
uint8_t mcp1_4PortB = 0x00;
uint8_t mcp1_5PortA = 0x00;
uint8_t mcp1_5PortB = 0x00;
uint8_t mcp2_1PortA = 0x00;
uint8_t mcp2_1PortB = 0x00;
uint8_t mcp2_2PortA = 0x00;
uint8_t mcp2_2PortB = 0x00;
uint8_t mcp2_3PortA = 0x00;
uint8_t mcp2_3PortB = 0x00;
uint8_t mcp2_4PortA = 0x00;
uint8_t mcp2_4PortB = 0x00;
uint8_t mcp3_1PortA = 0x00;
uint8_t mcp3_1PortB = 0x00;
uint8_t mcp3_2PortA = 0x00;
uint8_t mcp3_2PortB = 0x00;
uint8_t mcp3_5PortA = 0x00;
uint8_t mcp3_5PortB = 0x00;
uint8_t mcp3_6PortA = 0x00;
uint8_t mcp3_6PortB = 0x00;
// Functions
void i2ctest();
void tcaselect(uint8_t i);
void setup()
{
Serial.begin(9600);
Serial.print("Initialisation started\n");
Serial.println();
// Scan I2C devices
i2ctest();
// Init IO
I2C_Switch.setChannel(0);
Mcp1_1.initInputPortAB(); // all 16 IOs used as input
Mcp1_2.initInputPortAB(); // all 16 IOs used as input
Mcp1_3.initInputPortAB(); // all 16 IOs used as input
Mcp1_4.initInputPortAB(); // all 16 IOs used as input
Mcp1_5.initInputPortAB(); // all 16 IOs used as input
I2C_Switch.disableChannel();
//I2C_Switch.setChannel(1);
Mcp2_1.initInputPortAB(); // all 16 IOs used as input
Mcp2_2.initInputPortAB(); // all 16 IOs used as input
Mcp2_3.initInputPortAB(); // all 16 IOs used as input
Mcp2_4.initInputPortAB(); // all 16 IOs used as input
//I2C_Switch.disableChannel();
//I2C_Switch.setChannel(2);
Mcp3_1.initInputPortAB(); // all 16 IOs used as input
Mcp3_2.initInputPortAB(); // all 16 IOs used as input
Mcp3_5.initInputPortAB(); // all 16 IOs used as input
Mcp3_6.initInputPortAB(); // all 16 IOs used as input
//I2C_Switch.disableChannel();
delay(10);
Serial.print("Initialisation done\n");
Serial.println();
digitalWrite(LED_BUILTIN, LOW);
delay(10);
}
void loop()
{
// read Inputs
I2C_Switch.setChannel(0);
mcp1_1PortA = Mcp1_1.readPortA(mcp1_1PortA); // read MCP1_1 only PortA
mcp1_1PortB = Mcp1_1.readPortB(mcp1_1PortB); // read MCP1_1 only PortB
mcp1_2PortA = Mcp1_2.readPortA(mcp1_2PortA); // read MCP1_2 only PortA
mcp1_2PortB = Mcp1_2.readPortB(mcp1_2PortB); // read MCP1_2 only PortB
mcp1_3PortA = Mcp1_3.readPortA(mcp1_3PortA); // read MCP1_3 only PortA
mcp1_3PortB = Mcp1_3.readPortB(mcp1_3PortB); // read MCP1_3 only PortB
mcp1_4PortA = Mcp1_4.readPortA(mcp1_4PortA); // read MCP1_4 only PortA
mcp1_4PortB = Mcp1_4.readPortB(mcp1_4PortB); // read MCP1_4 only PortB
mcp1_5PortA = Mcp1_5.readPortA(mcp1_5PortA); // read MCP1_5 only PortA
mcp1_5PortB = Mcp1_5.readPortB(mcp1_5PortB); // read MCP1_5 only PortB
I2C_Switch.disableChannel();
//I2C_Switch.setChannel(1);
mcp2_1PortA = Mcp2_1.readPortA(mcp2_1PortA); // read MCP2_1 only PortA
mcp2_1PortB = Mcp2_1.readPortB(mcp2_1PortB); // read MCP2_1 only PortB
mcp2_2PortA = Mcp2_2.readPortA(mcp2_2PortA); // read Mcp2_1 only PortA
mcp2_2PortB = Mcp2_2.readPortB(mcp2_2PortB); // read Mcp2_1 only PortB
mcp2_3PortA = Mcp2_3.readPortA(mcp2_3PortA); // read Mcp2_2 only PortA
mcp2_3PortB = Mcp2_3.readPortB(mcp2_3PortB); // read Mcp2_2 only PortB
mcp2_4PortA = Mcp2_4.readPortA(mcp2_4PortA); // read Mcp2_3 only PortA
mcp2_4PortB = Mcp2_4.readPortB(mcp2_4PortB); // read Mcp2_3 only PortB
//I2C_Switch.disableChannel();
//I2C_Switch.setChannel(2);
mcp3_1PortA = Mcp3_1.readPortA(mcp3_1PortA); // read MCP3_0 only PortA
mcp3_1PortB = Mcp3_1.readPortB(mcp3_1PortB); // read MCP3_0 only PortB
mcp3_2PortA = Mcp3_2.readPortA(mcp3_2PortA); // read MCP3_1 only PortA
mcp3_2PortB = Mcp3_2.readPortB(mcp3_2PortB); // read MCP3_1 only PortB
mcp3_5PortA = Mcp3_5.readPortA(mcp3_5PortA); // read MCP3_4 only PortA
mcp3_5PortB = Mcp3_5.readPortB(mcp3_5PortB); // read MCP3_4 only PortB
mcp3_6PortA = Mcp3_6.readPortA(mcp3_6PortA); // read MCP3_5 only PortA
mcp3_6PortB = Mcp3_6.readPortB(mcp3_6PortB); // read MCP3_5 only PortB
//I2C_Switch.disableChannel();
Serial.print(mcp1_1PortA, BIN);
Serial.println();
Serial.print(mcp1_2PortB, BIN);
Serial.println();
Serial.print(mcp1_3PortA, BIN);
Serial.println();
Serial.print(mcp1_4PortB, BIN);
Serial.println();
Serial.print(mcp1_5PortA, BIN);
Serial.println();
Serial.print(mcp2_1PortB, BIN);
Serial.println();
Serial.print(mcp2_2PortA, BIN);
Serial.println();
Serial.print(mcp2_3PortB, BIN);
Serial.println();
Serial.print(mcp2_4PortA, BIN);
Serial.println();
Serial.print(mcp3_1PortB, BIN);
Serial.println();
Serial.print(mcp3_2PortA, BIN);
Serial.println();
Serial.print(mcp3_5PortB, BIN);
Serial.println();
analogWrite(BACKLIGHT_PIN_1, 255);
analogWrite(BACKLIGHT_PIN_2, 255);
analogWrite(BACKLIGHT_PIN_3, 255);
delay(1000);
}
void i2ctest()
{
Wire.begin();
Serial.println("\nScanning I2C devices...");
for (uint8_t t = 0; t < 4; t++)
{
tcaselect(t);
Serial.print("TCA Port #");
Serial.println(t);
for (uint8_t addr = 0; addr <= 127; addr++)
{
if (addr == TCAADDR)
continue;
Wire.beginTransmission(addr);
if (!Wire.endTransmission())
{
Serial.print("Found I2C device on 0x");
Serial.println(addr, HEX);
delay(10);
}
}
}
Serial.println("\nI2C device scanning completed");
delay(10);
}
void tcaselect(uint8_t i)
{
if (i > 7)
return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}