Using Multiple mcp23017 as outputs

Hi. I have a question about controlling multiple mcp23017 as outputs. This code works but would like to now if there is a more efficient way to controlling more than one mcp23017 at once. My end goal is to control up to 4 mcp23017 just by calling a channel number from 0 to 32+

#include <Wire.h>
#include "Adafruit_MCP23017.h"

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>


// Basic pin reading and pullup test for the MCP23017 I/O expander
// public domain!

// Connect pin #12 of the expander to Analog 5 (i2c clock)
// Connect pin #13 of the expander to Analog 4 (i2c data)
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
// Connect pin #9 of the expander to 5V (power)
// Connect pin #10 of the expander to ground (common ground)
// Connect pin #18 through a ~10kohm resistor to 5V (reset pin, active low)


Adafruit_MCP23017 mcp;

Adafruit_MCP23017 mcp2;


// Update these with values suitable for your network.
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xED, 0xFE };
IPAddress server(192,168, 0,2);


EthernetClient ethClient;
PubSubClient client(ethClient);

static byte RelayArray[32]      = {0, 1, 2 ,3,4,5,6,7,8,9,10,11,12,13,14,15,0, 1, 2 ,3,4,5,6,7,8,9,10,11,12,13,14,15};
static byte RelayStateArray[32] = {0, 0, 0,0,0,0,0,0,0, 0, 0,0,0,0,0,0,0, 0, 0,0,0,0,0,0,0, 0, 0,0,0,0,0,0};

void setup() {


  //Serial.begin(57600);
//Serial.println("Working");
  client.setServer(server, 1883);
  client.setCallback(callback);

  Ethernet.begin(mac);
  
  //Serial.println("Working2");
  
  // Allow the hardware to sort itself out
  delay(1500);

  
  mcp.begin();      // use default address 0
   mcp2.begin(1);      // use default address 0 
  
  for( byte i = 0; i < 16; i++)
  {
     mcp.pinMode(RelayArray[i], OUTPUT);
    //Serial.print(RelayArray[i]);
    //Serial.print(" ");
   mcp.digitalWrite(RelayArray[i], LOW);
    
  }

  for( byte i = 0; i < 16; i++)
  {
     mcp2.pinMode(RelayArray[i], OUTPUT);
    //Serial.print(RelayArray[i]);
    //Serial.print(" ");
   mcp2.digitalWrite(RelayArray[i], LOW);
    
  }



 
}


// flip the pin #0 up and down

void loop() {


  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  
}

String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void callback(char* topic, byte* payload, unsigned int length) {
  //Serial.print("Message arrived [");
  //Serial.print(topic);
  //Serial.print("] ");

String Topic = topic;

byte Relay = getValue(Topic,'/',5).toInt();

String PubState = "/device/HOUSE1/control/relay/"+(String)Relay+"/State";


if(Relay <= 16) {
if(payload[0] == '0'){
mcp.digitalWrite(RelayArray[Relay], LOW);
RelayStateArray[Relay] = 0;
client.publish(PubState.c_str(),"0");
}
else if (payload[0] == '1'){
mcp.digitalWrite(RelayArray[Relay], HIGH);
RelayStateArray[Relay] = 1;
client.publish(PubState.c_str(),"1");
}
}
else
{
if(payload[0] == '0'){
mcp2.digitalWrite(RelayArray[Relay], LOW);
RelayStateArray[Relay] = 0;
client.publish(PubState.c_str(),"0");
}
else if (payload[0] == '1'){
mcp2.digitalWrite(RelayArray[Relay], HIGH);
RelayStateArray[Relay] = 1;
client.publish(PubState.c_str(),"1");
}
}


  

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    //Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("HOUSERelay")) {
      //Serial.println("connected");
      // Once connected, publish an announcement...
      for( byte i = 0; i < 32; i++)
      {
       String PubState = "/device/HOUSE1/control/relay/"+String(RelayArray[i])+"/State";
       client.publish(PubState.c_str(), String(RelayStateArray[i]).c_str());
       }
      client.subscribe("/device/HOUSE1/control/relay/+/Command");
    } else {
      //Serial.print("failed, rc=");
      //Serial.print(client.state());
      //Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

You COULD setup all the pins for both devices in ONE for loop in setup().

You could put the objects in an array. Then, determining the device and pin number from the "channel" number is simple.

hi PaulS do you have an example of what you mean

do you have an example of what you mean

Adafruit_MCP23017 mcps[4];
for(byte b=0; b<4; b++)
{
   mcps[b].begin(b);
}
byte channelNumber = 26;
byte mcpIndex = channelNumber % 8;
byte pinOffset = channelNumber - mcpIndex * 8;

mcps[mcpIndex].digitalWrite(pinOffset, pinState);

Obviously, the snippets need to go in the proper places and be completed.

hi PaulS it seem there is a bug in that code am i missing something to make that work right?

for( byte Relay = 0; Relay < 32; Relay++)
{
byte channelNumber = Relay;
byte mcpIndex = channelNumber % 8;
byte pinOffset = channelNumber - mcpIndex * 8;

Serial.print("MCP “);
Serial.print(mcpIndex);
Serial.print(” Channel “);
Serial.print(pinOffset);
Serial.print(” Called ");
Serial.println(channelNumber);

mcps[mcpIndex].pinMode(pinOffset, OUTPUT);
//Serial.print(RelayArray*);*

  • //Serial.print(" ");*
  • mcps[mcpIndex].digitalWrite(pinOffset, LOW);*
    }
    output
    MCP 0 Channel 0 Called 0
    MCP 8 Channel 1 Called 1
    MCP 16 Channel 2 Called 2
    MCP 24 Channel 3 Called 3
    MCP 32 Channel 4 Called 4
    MCP 40 Channel 5 Called 5
    MCP 48 Channel 6 Called 6
    MCP 56 Channel 7 Called 7
    MCP 64 Channel 8 Called 8
    MCP 72 Channel 9 Called 9
    MCP 80 Channel 10 Called 10
    MCP 88 Channel 11 Called 11
    MCP 96 Channel 12 Called 12
    MCP 104 Channel 13 Called 13
    MCP 112 Channel 14 Called 14
    MCP 120 Channel 15 Called 15
    MCP 128 Channel 16 Called 16
    MCP 136 Channel 17 Called 17
    MCP 144 Channel 18 Called 18
    MCP 152 Channel 19 Called 19
    MCP 160 Channel 20 Called 20
    MCP 168 Channel 21 Called 21
    MCP 176 Channel 22 Called 22
    MCP 184 Channel 23 Called 23
    MCP 192 Channel 24 Called 24
    MCP 200 Channel 25 Called 25
    MCP 208 Channel 26 Called 26
    MCP 216 Channel 27 Called 27
    MCP 224 Channel 28 Called 28
    MCP 232 Channel 29 Called 29
    MCP 240 Channel 30 Called 30
    MCP 248 Channel 31 Called 31

hi Paul i found what the solution was missing i would like to thank you for you help

Code Fixed
byte mcpIndex = (int) (channelNumber / 16);
byte pinOffset = channelNumber - mcpIndex * 16;