WiFi LoRa 32 (V3) I2C SDA/SCL

I note that, in the pins_arduino.h file for the V3 board, entries for the I2C pins are listed as:

static const uint8_t SDA = 8;
static const uint8_t SCL = 9;

but there are no pins marked either SDA/SCL or GPIO8/GPIO9 in the V3 Pin Map, nor can I see any such pins no the board itself.

Does anyone know how one would access these pins? If it’s not possible to physically access pins 8 and 9, why do these definitions exist? How would they otherwise be used?

I realise that I don’t need to use any specific pins for the I2C bus, but I would generally try to use the default assignments provided by a manufacturer. In the present case, this doesn’t seem possible so I’m wondering why the definitions have been included.

EDITED: And now having looked at the schematic, where GPIO8 & GPIO9 are assigned to LoRa functions, I’m even more puzzled…

GPIO8-9

This may be the definition of the test version, which has not been changed later. I will submit a bug for modification later. As you think, I2C pin can be mapped to any IO.

I am also confused by this and more specifically what I2C pins I can call to use the OLED (it is I2c, no?). I’m finding the HT_ssd1306.h library a bit opaque and would like to use a more documented library (u8g2, or adafruit ssd1306), but I can’t make any headway. I’m finding many examples of people doing this with the V2 but the pinouts for V3 are completely different and don’t have any OLED/SDA or OLED/SCL pins labeled. ???

I’m using the MIT (Daniel Eichhorn) SSD1306 library with the WiFi LoRa 32 V3 board, initialising the display with:

SSD1306 myDisplay(0x3c, SDA_OLED, SCL_OLED);

The I2C pins used for the display are pins 17 (SDA_OLED) and 18 (SCL_OLED), but they are not broken out so there does not appear to be any way to use this [first] I2C bus for anything other than the on-board display. To connect any other I2C device I’ve had to declare a second bus, as something like either:

Wire1.being(SDA,SCL);

or

TwoWire I2CBus2 = TwoWire(1);
 .
 .
I2CBus2.begin(SDA,SCL,400000);

given that the first bus is identified as Wire or TwoWire(0) by default.

This is very helpful, thank you.

Since my post I’ve found success with the U8g2 library by initializing:

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 18, /* data=*/ 17, /* reset=*/ 21);

I also noticed that the 17 and 18 pins do appear to be broken out, they are pads on the bottom of the board.

Ah! Well spotted! Nicely set up for pogo-pin connectors it would seem…

17 and 18 are the i2c sda/scl pins? These pads on the bottom?

yes, although they are there for testing. You can solder to them but the 18 pad on my board lifted after some handling.

I’ve also noticed that works, but only the SOFTWARE I2C works, and is super slow :frowning:
If you try the _F_HW_I2C constructor (with the slightly different param order, btw!) it doesn’t work.
Any ideas why hardware I2C not usable?

I don’t know why i2c isn’t broken out better. However, esp32 boards allow for multiple buses, as mentioned by UniquePete. I found success like so:

Wire1.begin(SDA_2, SCL_2,400000);
youri2cdevice.begin(&Wire1);

with Wire1 being my additional bus, sda-2 and scl-2 being my desired pins, and youri2cdevice being the hardare I’m connecting.

Yes, this is exactly where my problem lies. The included oled display works with the u8g2 library and HW constructor. If I take the 2nd display on the same I2C bus, I can only use it with SW constructor. that’s too slow. hence my idea with the 2nd I2C bus. no idea if that solves my problem. If someone has already successfully implemented this (both displays run with u8g2 with HW Constructor) I would be very interested in the sketch.:pray:

1 Like

If you’re able to solder to the pogos for the second display can you also manually change the address of said display?

As far as having second display on second bus: this thread seems relevant to your issue. I’m not too familiar with the U8g2 library, I quickly jumped to the Adafruit_ss1306 library which has Wire as a parameter in its constructor.

Wire.begin(SDA_OLED, SCL_OLED);
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

I imagine that a second display object could have a dereferenced Wire1 as an argument?

Wire1.begin(SDA, SCL);
Adafruit_SSD1306 oled2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1, OLED_RESET);

maybe?

Can either of you share working code for the V3 that would demonstrate using both the onboard and a secondary OLED display with the adafruit library?

I don’t understand how to specify the &Wire address for the onboard display (17, 18).

Bonus points for helping with my second question, if you have any ideas. :slight_smile:

[Connect WiFi LoRa 32 (v3) to TFT display via SPI?](http://How link external TFT via SPI to V3?)

I can’t give you an example using the Adafruit library, and that may simply be because the Adafruit library does not include support for the ESP32-S3 processor (I don’t know if that’s the case, but I tried to load the example provided in the IDE and couldn’t quickly get it to display anything on the onboard display—but I didn’t try very hard, it just didn’t work first time around, so I just went back to the Eichhorn SSD1306 library that I always use), but the following will write to two displays on the two I2C buses.

This is just the setup part of an I2C bus scanner that would normally use a single display, but with the few extra lines of code to define and write something to a second display:

#include <SSD1306.h>            // OLED display
#include <Wire.h>

#define SDA 19
#define SCL 20

SSD1306 display(0x3c, SDA_OLED, SCL_OLED);
SSD1306 display2(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_TWO);

void setup()
{     
  Serial.begin(115200);
  delay(500);
  Serial.println("\nI2C Scanner");
  Serial.print("SDA : ");
  Serial.print(SDA);
  Serial.print(", SCL: ");
  Serial.println(SCL);
  Serial.println();

// Initialise the OLED displays
  
  Serial.println("[setup] Initialise display...");
  pinMode(RST_OLED,OUTPUT);     // GPIO16
  digitalWrite(RST_OLED,LOW);  // set GPIO16 low to reset OLED
  delay(50);
  digitalWrite(RST_OLED,HIGH);

  display.init();
  display.clear();
  display.setFont(ArialMT_Plain_16);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(5,15,"I2C Display 1");
  display.display();

  display2.init();
  display2.clear();
  display2.setFont(ArialMT_Plain_16);
  display2.setTextAlignment(TEXT_ALIGN_LEFT);
  display2.drawString(5,15,"I2C Display 2");
  display2.display();

}

SDA_OLED, SCL_OLED and RST_OLED are all defined in the relevant pins-arduino.h file that is automatically loaded with the board definition. I2C_TWO is defined within the SSD1306 library, which automatically handles the initialisation of both buses (which involves little more than invoking the relevant begin() method on each).

Also, I don’t know whether or not there’s a way to do a hardware reset the second display—I didn’t try—all I was trying to do was to get a simple sketch that wrote to two displays on different I2C buses.

I don’t know if this helps in your situation, but it at least demonstrates the use of two OLED displays on two separate I2C buses.

2 Likes

Hello, thank you for the helpful post - I’m trying to do the same thing. However, with your code only the onboard ssd1306 is activating. I tried two approaches for having two i2c busses. On the second, the usb also got unnaturally hot and sometimes it would go into a cycle of restarting…
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>

#define sc1_oled_scl 18
#define sc1_oled_sda 17
#define sc1_oled_rst 21

#define sc2_oled_scl 20
#define sc2_oled_sda 19

U8G2_SSD1306_128X64_NONAME_1_SW_I2C screen1(U8G2_R0, /* clock=*/sc1_oled_scl, /* data=*/sc1_oled_sda, /* reset=*/sc1_oled_rst);

U8G2_SSD1306_128X64_NONAME_1_SW_I2C screen2(U8G2_R0, /* clock=*/sc2_oled_scl, /* data=*/sc2_oled_sda, /* reset=*/U8X8_PIN_NONE);

// U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display
// U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 16, /* data=*/ 17, /* reset=*/ U8X8_PIN_NONE);   // ESP32 Thing, pure SW emulated I2C

void setup()
{
  Serial.begin(9600);
  Wire.begin(sc1_oled_sda,sc1_oled_scl);
  while (!Serial)
    ;
  Serial.println("OLED Test");
  screen1.begin();
  screen2.begin();
}

void loop()
{
  screen1.firstPage();
  screen2.firstPage();
  do
  {
    screen1.setFont(u8g2_font_ncenB10_tr);
    screen1.drawStr(0, 24, "Hello World screen 1");

    screen2.setFont(u8g2_font_ncenB10_tr);
    screen2.drawStr(0, 24, "Hello World screen 2");
  } while (screen1.nextPage());
}

Second approach:
/*
code done by
Rui Santos

  Complete project details at https://RandomNerdTutorials.com/esp32-i2c-communication-arduino-ide/

 

  Permission is hereby granted, free of charge, to any person obtaining a copy

  of this software and associated documentation files.

 

  The above copyright notice and this permission notice shall be included in all

  copies or substantial portions of the Software.

*/

#include <Wire.h>

#include <Adafruit_Sensor.h>

#include <Adafruit_BME280.h>

#define SDA_1 27

#define SCL_1 26

#define SDA_2 33

#define SCL_2 32

TwoWire I2Cone = TwoWire(0);

TwoWire I2Ctwo = TwoWire(1);

Adafruit_BME280 bme1;

Adafruit_BME280 bme2;

void setup() {

  Serial.begin(115200);

  Serial.println(F("BME280 test"));

  I2Cone.begin(SDA_1, SCL_1, 100000);

  I2Ctwo.begin(SDA_2, SCL_2, 100000);

  bool status1 = bme1.begin(0x76, &I2Cone);  

  if (!status1) {

    Serial.println("Could not find a valid BME280_1 sensor, check wiring!");

    while (1);

  }

 

  bool status2 = bme2.begin(0x76, &I2Ctwo);  

  if (!status2) {

    Serial.println("Could not find a valid BME280_2 sensor, check wiring!");

    while (1);

  }

 

  Serial.println();

}

void loop() {

  // Read from bme1

  Serial.print("Temperature from BME1= ");

  Serial.print(bme1.readTemperature());

  Serial.println(" *C");

  Serial.print("Humidity from BME1 = ");

  Serial.print(bme1.readHumidity());

  Serial.println(" %");

  Serial.print("Pressure from BME1 = ");

  Serial.print(bme1.readPressure() / 100.0F);

  Serial.println(" hPa");

  Serial.println("--------------------");

  // Read from bme2

  Serial.print("Temperature from BME2 = ");

  Serial.print(bme2.readTemperature());

  Serial.println(" *C");

  Serial.print("Humidity from BME2 = ");

  Serial.print(bme2.readHumidity());

  Serial.println(" %");

  Serial.print("Pressure from BME2 = ");

  Serial.print(bme2.readPressure() / 100.0F);

  Serial.println(" hPa");

  Serial.println("--------------------");

 

  delay(5000);

}

Hello,
I’ve a similar issue, but with the DS3231 RTC. This module must be connected to the SDA and SCL pins.
The problem is that I can’t pass as arguments the new SDA and SCL pins, because the method to create the rtc is:
rtc.begin()
If I call the u8g2.begin() before, the RTC will never start (because SDA and SCL ports are been used for the u8g2 OLED display).
There are any solution to solve this? I’m stucked.
Regards

Hello,
I found a solution…
SDA is the GPIO 21 and SCL the 22, and it worked, but after initialize the OLED display with “u8g2.begin()” this GPIO ports change to 15 (SCL) and 4 (SDA).
If after initialize the OLED display connect the I2C modules to 15 and 4, it works.
Other possibility is initialize the Wire library to use 15, 4 GPIO ports (with SoftWire library).
Issue explainig this GPIO port change: https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series/issues/62
Regards

Hello Guys,
I am a bit confused about the conversation. So the SDA Pin is 22 and SCL is 21 or 17,18 ?? Can somebody pls explain the final pins for the I2C (I2C for external Sensors eg)

GPIO17 (SDA) & GPIO18 (SCL) are used for the I2C bus that is connected to the on-board OLED display. These GPIOs are not broken out to pins on the board, although there are pads on the bottom of the board that appear to be connected to these GPIOs.

A second I2C bus can be defined and associated with any other two available pins, restrictions on the use of individual GPIOs specified in the ESP32-S3 datasheet notwithstanding. I have used GPIO19 (SDA) & GPIO20 (SCL) in the test sketch that I previously posted. @sorin-jay suggests that using GPIO19 & GPIO20, as I have done using the SSD1306 library to drive a second OLED display, does not work when using the U82g library, but @clemenlg notes that GPIO4 (SDA) & GPIO15 (SCL) can be used with the U8g2 library. I have no doubt that there will be other pin combinations that will also work, it will just be a matter of defining the ‘second’ I2C bus appropriately.

Ok thank you for the summary :smiley: