Problem using CJMCU-2317 MCP23017

I am using a CJMCU-2317 to expand the outputs of a NodeMCU esp8266. I have it wired as the following diagram:

My intention is being able to turn multiple relays on and off. I tried this configuration to test the idea, though the final project will differ because I'll have even more outputs, more I2C and SPI devices and I will use a esp32 instead of the esp8266; however, the basic idea of using the MCP23017 to expand the I/O is the same.

The relay module I am using is the one with optocouplers for isolation, in another post I found that the best way to use it is with a separate power supply as show here (I use a 12V power supply through a buck converter to get 5V).

The problem is that when using the MCP23017 outputs to activate the relays (as shown in the first diagram) it can only energize one relay at a time, but not two at the same time. This is an issue, since my project requires up to 4 relays on at the same time. If instead I use the digital outputs from the esp8266 to activate the relays I can successfully energize two relays at the same time. So I am thinking there's an issue either with my setup or my code, which is the following (first code is for MCP23017 outputs, second one for esp8266 outputs).

mcp outputs:

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

Adafruit_MCP23X17 mcp;
#define relay1 0 //A0
#define relay2 8 //B0
// SETUP
void setup(){
  Serial.begin(9600);
  Serial.println("NODEMCU and MCP23017 Relay Test");

  if (!mcp.begin_I2C()) {
    Serial.println("I2C Error.");
    while(1);
  }
    
  // configure pin as outputs
  mcp.pinMode(relay1, OUTPUT);
  mcp.pinMode(relay2, OUTPUT);
  // set them high so relays are off
  mcp.digitalWrite(relay1,HIGH);
  mcp.digitalWrite(relay2,HIGH);
}

// MAIN LOOP
void loop(){
  // start flickering
   Serial.println("Relay 1 ON");
   mcp.digitalWrite(relay1,LOW); // relay1 is energized
   delay(2500);
   Serial.println("Relay 2 ON");  
   mcp.digitalWrite(relay2,LOW); // relay2 is energized 
   delay(2500);  
   Serial.println("Relay 1 OFF");
   mcp.digitalWrite(relay1,HIGH); // relay1 is de-energized
   delay(2500);
   Serial.println("Relay 2 OFF");  
   mcp.digitalWrite(relay2,HIGH); // relay2 is de-energized 
   delay(2500);   
}

esp outputs:

#define relay1 D5
#define relay2 D6

// SETUP
void setup(){
  Serial.begin(9600);
  Serial.println("NODEMCU (Digital Only) Relay Test");
    
  // configure pin as outputs
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  // set them high so relays are off
  digitalWrite(relay1,HIGH);
  digitalWrite(relay2,HIGH);
}

// MAIN LOOP
void loop(){
  // start flickering
   Serial.println("Relay 1 ON");
   digitalWrite(relay1,LOW); // relay1 is energized
   delay(2500);
   Serial.println("Relay 2 ON");  
   digitalWrite(relay2,LOW); // relay2 is energized 
   delay(2500);  
   Serial.println("Relay 1 OFF");
   digitalWrite(relay1,HIGH); // relay1 is de-energized
   delay(2500);
   Serial.println("Relay 2 OFF");  
   digitalWrite(relay2,HIGH); // relay2 is de-energized 
   delay(2500);   
}

I would really appreciate any help or recommendations.

Vcc going to the relay module from the NodeMCU must be 5 V, not 3.3 V!

(Your diagram does not show any connection to Vcc on MCP23017 or relay module!)

Plus the ground of the processor and the MCP23017 is not connected to the power supply.

You said it was working with 8266. Were you supplying the relay board logic with 5V on its VCC or with 3.3V? Depending on the opto isolator, I guess you may be able to get it to switch off its LED if you power it with 5V and supply 3.3V logic HIGH. I have similar relays but I am using 5V to power the optos and control its logic.

Whoops, the diagram was incorrect. I am just learning how to use EasyEDA so that's why I missed the VCC connection, but in practice I do have it connected to VIN which is 5V.

I actually did that on purpose, as I read that having a common ground between the microcontroller and the relay board power supply would affect the opto isolation. Should I have a common ground for everything instead?

I was supplying the relay board with 5V on its VCC coming from the 8266 VIN. So yes, when using the digital outputs from the 8266, the board is powered by 5V but the logic is 3.3V. Could the issue be that the MCP23017 is being powered by 5V? When using the MCP module, the LEDs from the relay do turn on and off according to my program, however the relays do not energize when both Relay 1 and 2 are on. They only energize individually.

In a 3.3V design, the MCP should be powered with 3.3V. I however don't suspect that to be the root cause of your problem.

Where does the 5V (Vin) come from? USB from PC? Or something else. I did tests with a Nano a while ago using a LCD and two relays, powered from a PC; switching both relays on at the same time reduced the brightness of the display indicating that the PC is battling to provide sufficient power.

It may be an entirely separate power supply. Which is of course, the point of using the isolated relay driver.

That is absolutely correct. :+1:

That does not tell you much.

It begins to sounds as if the LM2596 regulator - or the 12 V power supply - is not able to provide much current at all.

You need to supply "Vcc" with 5 V to make it work. There are two LEDs (including the opto-isolator and a green indicator) in series.

The opto isolators on those boards are a sham, you can not use them without a common ground.

Really? what is wrong with the circuit I cited, and how does a common ground magically make it work?

I think the "not sharing ground" practice only works if at least one of the power supplied plugged into the wall has an isolation transformer.

Given that each and every mains power supply should already have transformer isolation, how would that be relevant?

If both ac adapters are plugged into the same outlet, I suspect the ground of both adapters may be not isolated.

What adapters have you used that actually have a ground pin? :frowning:

I pretend to hear "negative" when someone says ground from ac adapter because that's what I imagine happens, negative of the DC is connected to ground on a board. These negatives of different AC adapters are not isolated from each other.

Update: I still can't get the thing to work.

I was quite busy with school so it's been a while since I tried to make the thing work. I had the intuition that the output pins of the MCP23017 could not deliver the necessary current to power more than one relay at once.

According to the manufacturer (https://ww1.microchip.com/downloads/en/devicedoc/20001952c.pdf), each output pin of the MCP23017 can deliver a maximum of 25mA and a maximum current out of Vss of 150mA. I thought that maybe I had setup my relay board in a wrong way, so I measured currents using an Arduino UNO connected as shown

I found that each digital pin outputs a current of 1.91mA, much less than the 25mA limit of the MCP23017. Then I checked the output current of the 5V Separate power supply, for each relay it was about 65mA, so it draw around 240mA when all relays where powered on.

As before, the relay board works perfectly if I use the digital output pins of a microcontroller (esp8266,esp32, Uno, I've tried these so far). When I use the mcp23017 with the UNO, with one relay is ON the currents are as follows:

MCP23017 output pin: 0.4 mA @ 5.03V
Separate power supply: 27 mA

I am thinking that I may have a malfunctioning CJMCU-2317. In the world of electronics, is it possible to get a malfunctioning IC? It's just weird that it works perfectly when using the digital outputs of a microcontroller and the current values are fine. But then I try the CJMCU-2317 and the currents make no sense at all. I also occasionally get some kind of relay flickering, which I believe is due to the lower current values not generating as strong a magnetic field inside the relay. BTW, I tested the CJMCU-2317 with LEDs instead of relays and in that way it can power two led's at once without an issue.

This really is frustating at this point, any recommendations or alternatives? All I really want is being able to control a lot of relays with I2C from an esp32

Can you confirm that you have actually connected the GND on the input side of the relay board to the GND of the Arduino/MCP23017 combination? Otherwise you'll always keep running into issues with the GND of the separate 5V supply floating with respect to the GND from your DC/computer power supply, causing all sorts of 'inexplicable' problems.
Since I see no requirement of optical isolation and your relay board actually seems to have only a single GND anyway, I'd just make sure to connect all GNDs together.
I know @Paul_B said that the point of having optical isolation is to not connect GNDs together, but this ONLY works if the relay board is actually laid out appropriately for it. I don't think that's the case with the relay board in the picture above, as it should have two separate GND connections (one for the relays, one for the led-side of the optocouplers, usually the latter being positioned close to/along with the In1 etc. inputs).

What is the supply voltage of your MCP 23017 ?
The spec sheet says input must be 0.8 VDD or higher so it you use 3.3 v then it is too low.


It you power the MCP 23017 with 3.3 v, then it will be ok.

I am using the 5V and GND pins from the UNO, or alternatively the Vin and GND pins of the ESP. The A0,A1,A2 pins are connected as follows inside the CJMCU-2317

I just tried it with the GND of the separate supply and the ground from the Arduino together and nothing changed. I also tried powering the Arduino with another separate power supply and again nothing changed. Finally, I powered both the Arduino and the relay board from the same power supply... and nothing changed.

Wondering why OP is using a port expander.
The NodeMCU has enough I/O to drive that 4-realy module directly.

VCC of relay module to NodeMCU 5volt, relay inputs to free pins,
Jumper removed, JD-VCC/ground to separate external relay supply.
Leo..