One of the advantages of the ESP32 microcontrollers over the competitions is dual-core architecture and two I2C buses.

Yes, the I2C bus allows connecting multiple slave devices to single pair of SCL SDA wires. As long as slave device addresses are unique, everything will work just fine: OLED display, LM75 temperature sensor, MPU6050 gyroscope. However, one has to remember that one of the devices can be polled at a time. If the bus is used by, for example, MPU6050, parallel communication with SSD1306 OLED display is not possible.

Here comes the advantage of having multiple I2C buses. Not only you can have more devices of the same type and avoid I2C address conflicts, but you can also take full advantage of 2 ESP32 cores and communicate with multiple devices at the same time.

ESP32 with OLED

In the following example, I will show how to use multiple I2C buses of ESP32 using Espressif core for Arduino.

#include <Wire.h>

//Set pins for I2C1
#define I2C1_SDA_PIN 21
#define I2C1_SCL_PIN 22

//Set pins for I2C2
#define I2C2_SDA_PIN 0
#define I2C2_SCL_PIN 23

TwoWire I2C1 = TwoWire(0); //I2C1 bus
TwoWire I2C2 = TwoWire(1); //I2C2 bus

void setup()
{
    // Init buses
    I2C1.begin(I2C1_SDA_PIN, I2C1_SCL_PIN, 100000); // Start I2C1 on pins 21 and 22
    I2C2.begin(I2C2_SDA_PIN, I2C2_SCL_PIN, 100000); // Start I2C2 on pins 0 and 23
}

void loop() 
{
    //Talk to device connected to I2C1
    I2C1.beginTransmission(0x3c);
    I2C1.write(0x40);
    I2C1.endTransmission();

    //Talk to device connected to I2C2
    I2C2.beginTransmission(0x30);
    I2C2.write(0x45);
    I2C2.endTransmission();
}

Two remarks:

  1. ESP32 use matrix IO that allows mapping any pin to any function
  2. GPIO 34, 35, 36 and 39 are INPUT ONY ports and can not be used as SCL or SDA
  3. Some Arduino compatible libraries do not allow to set I2C bus to use always use I2C1. Refer to the library documentation for details on how to choose I2C bus