[solved] ESP-01, i2c, MCP23017 and the arduino IDE

Hi All,

For a project I'm looking to control 4 to 8 motors. I've decided to use the L9110 H-bridge modules. The unit will be wireless, so I'm using the ESP family of microcontrollers. Since the NodeMCU's only have 4 PWM pins, I might as well use an ESP-01, since I'll need the MCP23017 to control more than 2 motors (each motor uses 2 PWM Pins). This way I could also add a display and some buttons for local control.

I am however running into some trouble right from the start. I seem to be unable to find my MCP23017 on the ESP-01's I2C bus. As I understand SDA and SCL pins on the ESP-01 are 0 and 2 (default arduino pins are 4 and 5).

After wiring it, and redoing it on a different breadboard again, trying multiple ESP-01 units (i have 3 lying around), I am at a loss. Per a friend's suggestion I tried to run a blinky sketch on the ESP-01, but I am unable to get them to blink with the arduino example, changing the led pin to 0 or 2.

Since I'm doing this in the arduino IDE, i thought this would be the best place to ask for help.

I've tried switching the wires, I've tried defining the SDA/SCL pins in my sketch, but nothing seems to resolve my issues. I have used the 10K pull-ups on the I2C bus. You name it, I've done it! I've compared the multiple tutorials on the web and they all lead me to the same schematic and wiring.

What is wrong here?

I've even removed all libraries and reinstalled the arduino IDE, to rule out the software being the problem.

As board I have selected "generic ESP8266 module"
Flashing works, with a few hiccups but stable in general.

sketch running:

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

#include <Wire.h>

//ESP-01 i2c pins (arduino defaults to 4/5)
#define SDA 0
#define SCL 2

// tried reversing
//#define SDA 2
//#define SCL 0 

void setup() {

  Serial.begin(115200);
  display_Running_Sketch();
  Serial.println("\nI2C Scanner");
  Serial.print("SDA: ");Serial.println(SDA);
  Serial.print(" SCL: ");Serial.println(SCL);
  
// should work but doesn't.
  Serial.print("Wire.begin(");Serial.print(SDA);Serial.print(",");Serial.print(SCL);Serial.print(")");;
  Wire.begin();

//// i think this is the default order
// Serial.print("Wire.begin(");Serial.print(SCL);Serial.print(",");Serial.print(SDA);Serial.print(")");;
//  Wire.begin(SCL,SDA);

// also tried this...
//Serial.print("Wire.begin(");Serial.print(SDA);Serial.print(",");Serial.print(SCL);Serial.print(")");;
//  Wire.begin(SDA,SCL);

  
}
 
void loop() {
  
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unknow error at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }
  delay(5000);          
}

// displays at startup the Sketch running in the Arduino
void display_Running_Sketch (void){
  String the_path = __FILE__;
  int slash_loc = the_path.lastIndexOf('/');
  String the_cpp_name = the_path.substring(slash_loc+1);
  int dot_loc = the_cpp_name.lastIndexOf('.');
  String the_sketchname = the_cpp_name.substring(0, dot_loc);

  Serial.print("\nArduino is running Sketch: ");
  Serial.println(the_sketchname);
  Serial.print("Compiled on: ");
  Serial.print(__DATE__);
  Serial.print(" at ");
  Serial.print(__TIME__);
  Serial.print("\n");
}

returns:

Arduino is running Sketch: i2c-test
Compiled on: Dec  6 2021 at 19:51:28

I2C Scanner
SDA: 0
 SCL: 2
Wire.begin(0,2)Scanning...
No I2C devices found

Scanning...
No I2C devices found

same for reversing SDA/SCL and for pins 4/5

Your post was MOVED to its current location as it is more suitable.

sda, scl: are those supposed to be the gpio numbers or the "pin" numbers?

The internal LED on an ESP-01 is usually on GPIO 1 (the TX pin)

This shows the I2C pins swapped from what you've done.

That works for me as well. I never use I2C, so whatever i find is through google. Anyway uploading does not seem to be an issue. Keep in mind that GPIO 0 & 2 (and 1 )TX)) can not be pulled HIGH at boot. OOps edit "LOW" GPIO 0, 1 & 2 cannot be pulled "LOW" at boot foe normal boot mode.

If you use wire.begin() without any parameters the wire-library will use those IO-pins that are used as the default for I2C. And these IO-pins are GPIO 4 and 5 which are not accessible on an ESP-01

I did a quoogling with keywords "arduino esp8266 using other io-pins for I2C"

and found this

so user @Deva_Rishi found a tutorial how to use a ESP8266-01 module to use I2C.

To me personal this is too much hassle for using an adapterboard for programming the ESP-01. I prefer using ESP32 nodeMCU-boards with which 8 PWM-channels can be created without any additional chips.

Plug in USB-cable upload code and it is ready to run the 8 PWM-channels

best regards Stefan

In setup you have to replace, Wire.begin(); by
Wire.begin(0,2); //Wire.begin(sda, scl)

Those are redefinitions of the pins 4/5 used by default. Setting these constants provides wire.begin(); with the (according to examples on the interwebs) correct pin numbers, instead of the inaccessible pins 4 & 5. If you look at the code you can see all the different pins I tried, commented out.

As mentioned in my posted code I have tried swapping the pins. I've checked and re-checked. The wiring is solid, and if it wasn't I have already switched the data wires. Numerous times.

Is that relevant? This should not be a problem utilising them for I2C, if I'm correct..? I have used these exact units in the past to switch relays and read data from a DHT22 through these GPIO (0/2) pins, so I am confused why I can't seem to get this working, since it should be so simple. I do remember having switched pins 0/2 in my prototype, which might also be due to the GPIO labels being switched, but that was easily remedied in the code..

The ESP is running so it's getting enough current from my USB/Serial converter, but maybe the MCP23017 doesn't. But then, still, I should be able to get an LED blinking without the MCP, I would think.

Does anyone think it might be related to my ancient 2011 iMac no longer receiving updates?

A friend suggested I switch to platformIO but I lack python 3 on this system, so installing didn't work out (at least not without going down another rabbithole that could take up another free day :smiley: )

Hi Stefan,

Don't become a parent if all you can do is throw money at a problem :wink:

Either way, I have an SPI display, some modules, and other stuff lying around I'd like to use finally, since I already own it. I have a very good use for the extra 8 outputs of the 16 that the mcp provides.

You are very welcome to this topic. I can see however, that you did not read the provided testing code, so you are just going off in a random direction.

If you would read the code, you would see that I redefined pins SDA/SCL to 0/2, I have also tried 2/0, 4/5 5/4, (commented out) all yielding the SAME result. It is very likely not a problem with pin numbers, but with the hardware (either ESP or the chip, or both) or an outdated library. Or I have a tumor and can no longer adequatly interpret reality. Infinite possibilities.

Either way, redefining SDA/SCL (and then confirming this through Serial console which you can observe in the code), automatically hands Wire.begin() the right parameters.

I very much appreciate your attention and time, it is however good custom to read a text to to avoid repeating ourselves and doing futile labour.

I am not on Mac, But it may have something to do with it still working. Apples are supposed to stop working when the warrantee expires (within a day or 2 of that)

Don't become a parent if you can't afford it :wink:

If you've tried everything, and as far as i know it works on any pin on an ESP. So if the ESP runs normally, do the pins ?
What ESP core are you using ?
And is the I2C library that you are using ESP8266 specific ?
Anyway, questions you probably asked yourself, but we could use that information.

It depends what and how you connect things up, but since you are powering up correctly anyway, no it is probably not, but when you test the output of the pins, it may be handy knowledge. I've had ESP-01's where i have had just damaged GPIO pins, where GPIO 0 & 2 (or 1) had somehow fused together, but were fully functional for the rest.

Having a short look, going for a pee and a wonder around the house, and coming back to the screen and a new topic, does that as well. No need to post anything.

Decided to try again, this time with a better image of the MCP23017 found here Your suggestion turned out helpful!

What also helped, I'm guessing, is giving the MCP23017 a dedicated power supply. This I tried before, but the breadboard power supply wasn't powerful enought to power both the MCP and the ESP (so it appears).

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

#include <Wire.h>

//ESP-01 i2c pins (arduino defaults to 4/5)
#define SDA 0
#define SCL 2

// tried reversing
//#define SDA 2
//#define SCL 0 

void setup() {

  Serial.begin(115200);
  display_Running_Sketch();
  Serial.println("\nI2C Scanner");
  Serial.print("SDA: ");Serial.println(SDA);
  Serial.print(" SCL: ");Serial.println(SCL);
  
// should work but doesn't.
//  Serial.print("Wire.begin(");Serial.print(SDA);Serial.print(",");Serial.print(SCL);Serial.print(")");;
//  Wire.begin();

//// i think this is the default order
 Serial.print("Wire.begin(");Serial.print(SCL);Serial.print(",");Serial.print(SDA);Serial.print(")");;
  Wire.begin(SCL,SDA);

// also tried this...
//Serial.print("Wire.begin(");Serial.print(SDA);Serial.print(",");Serial.print(SCL);Serial.print(")");;
//  Wire.begin(SDA,SCL);

  
}
 
void loop() {
  
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unknow error at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }
  delay(5000);          
}

// displays at startup the Sketch running in the Arduino
void display_Running_Sketch (void){
  String the_path = __FILE__;
  int slash_loc = the_path.lastIndexOf('/');
  String the_cpp_name = the_path.substring(slash_loc+1);
  int dot_loc = the_cpp_name.lastIndexOf('.');
  String the_sketchname = the_cpp_name.substring(0, dot_loc);

  Serial.print("\nArduino is running Sketch: ");
  Serial.println(the_sketchname);
  Serial.print("Compiled on: ");
  Serial.print(__DATE__);
  Serial.print(" at ");
  Serial.print(__TIME__);
  Serial.print("\n");
}

now yields

Scanning...
I2C device found at address 0x20
done

which is exactly what I wanted :smiley: I now know the correct wiring and can begin assembly on protoboard. Thanks all! I'll mark this solved and leave this here for anyone else struggling. (and also me, because I have terrible memory)

1 Like

The ESP is quite power hungry, this i know.

Yes it seems the ESP likes some juice, since the MCP's datasheet mentions the 1µA idle usage as a strong point :stuck_out_tongue:

All wifi chips like juice. They need it to produce transmit RF power.