Which one is best MUX or MCP for additional port to digital Read & Write on ESP32

Hi…
I have a doubt for my project which one I use for port extent at ESP32 for 16 Switch and 16 Relay operation through Blynk when the network is available and the Physical switch for offline mode when the network is not available, which one I use MUX CD74HC4067 or MCP23017 please suggest me…
Advance Thank you for your reply…

Pete.

2 Likes

I tried this code also with some modification for ESP32 but showing an error at ICACHE_RAM_ATTR intCallBack() loop “getLastInterruptPin” such type of syntax is not available in that library(Adafruit_MCP23017.h) and even used latest updated library of adafruit same error showing

I’d suggest that you post your modified code and the exact compiler message, along with details of which ESP32 core version you are using, whether you are using Blynk Legacy or IoT and which Blynk library version you have installed.Pete.

1 Like

Thank you Pete i will be back with details…

Hi…Pete
Somehow I managed, it is working fine through Blynk only, but the Physical button not working in both conditions online and offline of blynk, pullup is checked ok, but the interrupt pin not getting low or high, please refer to this sketch attached…Please help…

#define BLYNK_PRINT Serial

#define BLYNK_TEMPLATE_ID "TMPLhCaV8q9c"
#define BLYNK_DEVICE_NAME "Automation"
#define BLYNK_AUTH_TOKEN "6WZ9MU0GradTViMAxgoVb3ddXHpOes26"

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "KK";
char pass[] = "kk@12345";

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

//#include <Adafruit_MCP23X08.h>
#include <Adafruit_MCP23X17.h>

#include <Wire.h>
BlynkTimer timer;

// uncomment appropriate line
//Adafruit_MCP23X08 mcp;
Adafruit_MCP23X17 mcp1;
Adafruit_MCP23X17 mcp2;

#define wifiLed   2  //LED1
int wifiFlag = 0;

//MCP1 Input: 0 to 7 are Input
#define SW1 0
#define SW2 1
#define SW3 2
#define SW4 3
#define SW5 4
#define SW6 5
#define SW7 6
#define SW8 7

//MCP2 Input: 0 to 7 are Input
#define SW9 0
#define SW10 1
#define SW11 2
#define SW12 3
#define SW13 4
#define SW14 5
#define SW15 6
#define SW16 7

//MCP1 Output: 8 to 15 are Output
#define SK1 8
#define SK2 9
#define SK3 10
#define SK4 11
#define SK5 12
#define SK6 13
#define SK7 14
#define SK8 15

//MCP2 Output: 8 to 15 are Output
#define SK9 8
#define SK10 9
#define SK11 10
#define SK12 11
#define SK13 12
#define SK14 13
#define SK15 14
#define SK16 15

// Define the interrupt pin on the MCU
int esp_interrupt_pin = 14; // GPIO14 (D14)

volatile unsigned long last_interrupt; // Used to store the time in millis of the last interrupt, for debouncing
int debounce_delay = 100;              // The minimum delay in milliseconds between button presses, for debouncing

volatile int mcp_device_ID; // when an interrupt is detected and decoded the device which generated the interrupt is stored here
volatile uint8_t pin_num;   // when an interrupt is detected and decoded the pin which generated the interrupt  is stored here

// Interrupt handler for pins mcb1 pins 0-7 and mcb2 pins 0-7
void ICACHE_RAM_ATTR intCallBack()
{
  noInterrupts();

  if (mcp1.getLastInterruptPin() < 15)
  {
    pin_num = mcp1.getLastInterruptPin();
    mcp_device_ID = 0x20;
  }

  else if (mcp2.getLastInterruptPin() < 15)
  {
    pin_num = mcp2.getLastInterruptPin();
    mcp_device_ID = 0x21;
  }

  if (millis() - last_interrupt >= debounce_delay) // Debounce routine
  {
    // for debugging only...
    Serial.println("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-");
    Serial.println("A button has been pressed!!!");
    Serial.print("Device = ");
    Serial.println(mcp_device_ID);
    Serial.print("Pin = ");
    Serial.println(pin_num);
    Serial.println("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-");
    Serial.println();

    process_button_press();  // Call the function that will activate the correct relay etc.
  }
  last_interrupt = millis();
  interrupts();
  clear_mcp_interrupts(); // Call the function that clears all of the interrupt registers
}

void clear_mcp_interrupts()
{
  for (int loop = 0; loop <= 7; loop++) // Loop through the 8 pins on mcp_A that have interrupts attached
  {
    mcp1.digitalRead(loop);    // Read the pin to clear the interrupt register for that pin
  }

  for (int loop = 0; loop <= 7; loop++) // Loop through the 8 pins on mcp_B that have interrupts attached
  {
    mcp2.digitalRead(loop);    // Read the pin to clear the interrupt register for that pin
  }

}

void process_button_press()
{
  switch (mcp_device_ID)
  {
    case 0x20: //mcp1
      {
        int current_pin_state = mcp1.digitalRead(pin_num + 8);     // Get the current state of the pin
        mcp1.digitalWrite(pin_num + 8, current_pin_state);        // Write the opposite state to the pin to toggle it
        Blynk.virtualWrite(pin_num, current_pin_state);
      }
      break;

    case 0x21: //mcp2
      {
        int current_pin_state = mcp2.digitalRead(pin_num + 8);     // Get the current state of the pin
        mcp2.digitalWrite(pin_num + 8, current_pin_state);
        Blynk.virtualWrite(pin_num + 8, current_pin_state);
      }
      break;
  }
}
BLYNK_WRITE_DEFAULT()
{
  int widget_pin = request.pin;      // Which virtual pin triggered this BLYNK_WRITE_DEFAULT callback?
  int widget_value = param.asInt();  // Get the value from the virtual pin (O = off, 1 = on)

  if (widget_pin >= 0 && widget_pin <= 7) // if it was a virtual pin in the range 0-7 then it's a command meant for mcp_A
  {
    mcp1.digitalWrite(widget_pin + 8, widget_value);            // Write the opposite state to the pin on mcp_A to toggle the relay
  }

  if (widget_pin >= 8 && widget_pin <= 15) // if it was a virtual pin in the range 8-15 then it's a command meant for mcp_B
  {
    mcp2.digitalWrite(widget_pin + 8, widget_value);            // Write the opposite state to the pin on mcp_B to toggle the relay
  }

}

BLYNK_CONNECTED()
{
  for (int loop = 0; loop <= 15; loop++)
  {
    Blynk.syncVirtual(loop);
  }
}

void setup()
{
  Serial.begin(115200);

  pinMode(esp_interrupt_pin, INPUT);

  mcp1.begin_I2C(0x20);
  mcp2.begin_I2C(0x21);

  mcp1.setupInterrupts(true, false, LOW);
  mcp2.setupInterrupts(true, false, LOW);

  pinMode(wifiLed, OUTPUT);

  mcp1.pinMode(SW1, INPUT_PULLUP);
  mcp1.pinMode(SW2, INPUT_PULLUP);
  mcp1.pinMode(SW3, INPUT_PULLUP);
  mcp1.pinMode(SW4, INPUT_PULLUP);
  mcp1.pinMode(SW5, INPUT_PULLUP);
  mcp1.pinMode(SW6, INPUT_PULLUP);
  mcp1.pinMode(SW7, INPUT_PULLUP);
  mcp1.pinMode(SW8, INPUT_PULLUP);
  mcp2.pinMode(SW9, INPUT_PULLUP);
  mcp2.pinMode(SW10, INPUT_PULLUP);
  mcp2.pinMode(SW11, INPUT_PULLUP);
  mcp2.pinMode(SW12, INPUT_PULLUP);
  mcp2.pinMode(SW13, INPUT_PULLUP);
  mcp2.pinMode(SW14, INPUT_PULLUP);
  mcp2.pinMode(SW15, INPUT_PULLUP);
  mcp2.pinMode(SW16, INPUT_PULLUP);

  mcp1.pinMode(SK1, OUTPUT);
  mcp1.pinMode(SK2, OUTPUT);
  mcp1.pinMode(SK3, OUTPUT);
  mcp1.pinMode(SK4, OUTPUT);
  mcp1.pinMode(SK5, OUTPUT);
  mcp1.pinMode(SK6, OUTPUT);
  mcp1.pinMode(SK7, OUTPUT);
  mcp1.pinMode(SK8, OUTPUT);
  mcp2.pinMode(SK9, OUTPUT);
  mcp2.pinMode(SK10, OUTPUT);
  mcp2.pinMode(SK11, OUTPUT);
  mcp2.pinMode(SK12, OUTPUT);
  mcp2.pinMode(SK13, OUTPUT);
  mcp2.pinMode(SK14, OUTPUT);
  mcp2.pinMode(SK15, OUTPUT);
  mcp2.pinMode(SK16, OUTPUT);

  mcp1.digitalWrite(SK1, 0);
  mcp1.digitalWrite(SK2, 0);
  mcp1.digitalWrite(SK3, 0);
  mcp1.digitalWrite(SK4, 0);
  mcp1.digitalWrite(SK5, 0);
  mcp1.digitalWrite(SK6, 0);
  mcp1.digitalWrite(SK7, 0);
  mcp1.digitalWrite(SK8, 0);
  mcp2.digitalWrite(SK9, 0);
  mcp2.digitalWrite(SK10, 0);
  mcp2.digitalWrite(SK11, 0);
  mcp2.digitalWrite(SK12, 0);
  mcp2.digitalWrite(SK13, 0);
  mcp2.digitalWrite(SK14, 0);
  mcp2.digitalWrite(SK15, 0);
  mcp2.digitalWrite(SK16, 0);

  mcp1.setupInterruptPin(SW1, FALLING);
  mcp1.setupInterruptPin(SW2, FALLING);
  mcp1.setupInterruptPin(SW3, FALLING);
  mcp1.setupInterruptPin(SW4, FALLING);
  mcp1.setupInterruptPin(SW5, FALLING);
  mcp1.setupInterruptPin(SW6, FALLING);
  mcp1.setupInterruptPin(SW7, FALLING);
  mcp1.setupInterruptPin(SW8, FALLING);
  mcp2.setupInterruptPin(SW9, FALLING);
  mcp2.setupInterruptPin(SW10, FALLING);
  mcp2.setupInterruptPin(SW11, FALLING);
  mcp2.setupInterruptPin(SW12, FALLING);
  mcp2.setupInterruptPin(SW13, FALLING);
  mcp2.setupInterruptPin(SW14, FALLING);
  mcp2.setupInterruptPin(SW15, FALLING);
  mcp2.setupInterruptPin(SW16, FALLING);

  clear_mcp_interrupts();

  Blynk.begin(auth, ssid, pass);

attachInterrupt(digitalPinToInterrupt(esp_interrupt_pin), intCallBack, FALLING);
timer.setInterval(2000L, Sensors);
}

void loop()
{
  Blynk.run();
  timer.run();
  
  bool isconnected = Blynk.connected();
  if (isconnected == true) {
    wifiFlag = 1;
    Serial.println("Blynk Connected");
    digitalWrite(wifiLed, HIGH);
  }
  if (isconnected == false) {
    wifiFlag = 0;
    digitalWrite(wifiLed, HIGH);
    delay(400);
    digitalWrite(wifiLed, LOW);
    delay(400);
  }
}

void Sensors()
{
  //your code
}

It appears that you’re using a single MCP23017 chip, yet running the code that is designed for multiple chips.

In addition, if you want help with your own breadboard circuit rather than the Waveshare board then at the very least you’re going to have to post a schematic of your circuit.

Pete.

1 Like