Hello everyone,
I’m struggling to get a simple “Hello ESP32-S3!” sketch working on my ESP32-S3 Dev Module when using PlatformIO. In Arduino IDE the exact same code drives my SSD1306 (128×32) OLED display over I²C without issues. However, in PlatformIO, nothing ever appears on the screen—no error messages, just a blank display. I’m hoping someone can spot what I’m missing or suggest debugging steps. Below is a complete summary of my setup, wiring, code, platformio.ini
, and troubleshooting steps so far.
1) Hardware Setup
- Board: ESP32-S3 Dev Module (the built-in USB port is connected to my PC)
- Display: SSD1306 128×32 OLED (I²C interface)
- VCC → 3.3 V on ESP32-S3
- GND → GND
- SDA → GPIO 4
- SCL → GPIO 5
- (The module has onboard pull-ups on SDA/SCL; if yours does not, you’ll need two 4.7 kΩ–10 kΩ pull-ups to 3.3 V.)
I verified that wiring is correct: SDA and SCL are not swapped, and power/ground are solid.
2) platformio.ini
This is my entire PlatformIO configuration. I deliberately removed any Adafruit SSD1306/GFX libraries to avoid conflicts and only included U8g2:
[env:esp32s3]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
lib_deps =
olikraus/U8g2@^2.34.22
- board = esp32-s3-devkitc-1 matches the “ESP32-S3 Dev Module” definition.
lib_deps
installs the U8g2 library (version ≥ 2.34.22).
I ran pio run --target clean
and then pio run
to ensure everything was rebuilt from scratch.
3) Code in src/main.cpp
Below is the exact sketch I’m using. Note that it drives the OLED over hardware I²C on GPIO 4/5. In Arduino IDE this code displays “Hello ESP32-S3!” just fine. In PlatformIO it compiles and uploads with no errors, but the OLED remains blank.
#include <Wire.h>
#include <U8g2lib.h>
// ----------------------------------------------------------------
// 1) Configure U8g2 for SSD1306 128×32 over HW-I2C
// SDA = GPIO 4, SCL = GPIO 5
// ----------------------------------------------------------------
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(
U8G2_R0, // no rotation
/* reset=*/ U8X8_PIN_NONE,
/* clock=SCL=*/ 5, // GPIO 5 → SCL
/* data=SDA=*/ 4 // GPIO 4 → SDA
);
void setup() {
Serial.begin(115200);
delay(500);
// ----------------------------------------------------------------
// 2) Initialize I2C bus on SDA=4, SCL=5
// (U8g2 internally calls Wire.begin(), but we force it here)
// ----------------------------------------------------------------
Wire.begin(4, 5);
// Optional: Wire.setClock(100000); // force 100 kHz if pull-ups are weak
// ----------------------------------------------------------------
// 3) Initialize SSD1306 @ I2C address 0x3C
// ----------------------------------------------------------------
if (!u8g2.begin()) {
Serial.println("Error: SSD1306 not responding at 0x3C");
while (true) {
delay(100);
}
}
// ----------------------------------------------------------------
// 4) Draw “Hello ESP32-S3!” once
// ----------------------------------------------------------------
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(0, 16, "Hello ESP32-S3!");
u8g2.sendBuffer();
}
void loop() {
// Nothing to do in loop—content remains static
}
Wire.begin(4, 5)
remaps the hardware I²C bus to pins 4 and 5.- After
u8g2.begin()
, the code clears the display buffer, sets a font, draws the string at coordinates (0, 16), and sends the buffer.
No compile errors occur, and the serial monitor prints nothing (because I have no debug prints except the potential initialization failure). The OLED remains black.
4) Troubleshooting Steps Already Taken
- Clean/Rebuild
- Ran
pio run --target clean
→pio run
→pio run --target upload
. - Confirmed upload succeeded with no errors or warnings.
- I²C Scanner Sketch
I replacedmain.cpp
with a minimal I²C scanner to see if 0x3C is present on (4, 5):
#include <Wire.h>
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin(4, 5);
Serial.println("I2C Scanner started on SDA=4, SCL=5...");
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.print("Device found at 0x");
if (addr < 16) Serial.print('0');
Serial.println(addr, HEX);
}
}
Serial.println("Scan complete.");
}
void loop() {}
- Result: No device found at 0x3C.
- This indicates the SSD1306 is not responding on pins 4/5.
- Tried Alternative I²C Pins
Since many ESP32-S3 boards route I²C by default to GPIO 21/22, I modified the code to:
cpp
CopiaModifica
Wire.begin(21, 22);
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE, 22, 21);
And physically wired SDA→21, SCL→22. Then reran the I²C scanner.
- Result: Device found at 0x3C on (21, 22). OLED responds.
- But with those changes, the “Hello ESP32-S3!” sketch using (21, 22) works correctly in PlatformIO.
- Conclusion from Scanning
- The OLED module does not respond on (4, 5) despite having pull-ups.
- Wiring to (21, 22) is the only way the display shows up in PlatformIO.
- Hypothesis
For some reason, on my ESP32-S3 Dev Module in the PlatformIO environment, GPIO 4/5 are not enabled as a usable I²C bus by default, or the board definition conflicts with other peripherals. However, in Arduino IDE, it seemed thatWire.begin(4, 5)
“just worked” (perhaps the Arduino core auto-enabled pull-ups differently). On PlatformIO, the preconfigured variant of Wire foresp32-s3-devkitc-1
appears to prefer GPIO 21/22 as the hardware I²C pins and might not multiplex 4/5 without additional configuration.
5) Current Working Configuration
To get the display working under PlatformIO, I had to switch to pins 21/22:
#include <Wire.h>
#include <U8g2lib.h>
// Use HW-I2C on SDA=21, SCL=22 instead of 4/5
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(
U8G2_R0,
/* reset=*/ U8X8_PIN_NONE,
/* clock=SCL=*/ 22, // GPIO 22 → SCL
/* data=SDA=*/ 21 // GPIO 21 → SDA
);
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin(21, 22);
if (!u8g2.begin()) {
Serial.println("Error: SSD1306 not responding @ 0x3C");
while (true) { delay(100); }
}
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(0, 16, "Hello ESP32-S3!");
u8g2.sendBuffer();
}
void loop() {}
With this change, the display shows the text correctly. But I specifically want to understand:
- Why
Wire.begin(4, 5)
worked in Arduino IDE (showed “Hello ESP32-S3!” on GPIO 4/5), but in PlatformIO with the same board definition it did not. - Ideally, I’d like to continue driving the screen on pins 4 and 5 (they’re more convenient on my custom wiring), so I need to either reconfigure PlatformIO’s I²C driver or understand why those pins are not available by default.
6) Questions & Requests for Help
- Is there a PlatformIO-specific setting (e.g. in
platformio.ini
or board JSON) that disables or remaps GPIO 4/5 from acting as an I²C bus onesp32-s3-devkitc-1
? - How can I force-enable I²C on pins 4/5 when using PlatformIO? (Perhaps a build flag or board override?)
- Why does the Arduino IDE core allow
Wire.begin(4, 5)
to work out of the box, whereas PlatformIO (with the same core version) does not? - If switching to pins 21/22 is the only reliable solution in PlatformIO, what is the recommended “PlatformIO-style” way to document this in my project so others know to wire to 21/22 instead of 4/5?
Any insight into how PlatformIO’s espressif32 platform handles I²C remapping on the S3 would be greatly appreciated. Thank you in advance for your help!
—
(Feel free to ask for any additional details or board-revision info—I want to ensure my explanations are clear.)