ESP32-C3 SSD1306 OLED Simulator: Wiring, Code and a Live Circuit
This is a 0.96 inch SSD1306 OLED, 128 by 64 pixels, wired to an ESP32-C3 DevKitM-1 over I2C and running live: the board writes two lines of text, draws a box and counts the seconds in it. It uses the Adafruit SSD1306 and GFX libraries, exactly as a tutorial would.
Four wires: power, ground, SDA to GPIO 8 and SCL to GPIO 9. The ESP32-C3 is a 3.3 V board, so the display runs from 3V3.
- 3.3 V logic
- Library: Adafruit_SSD1306.h
- I2C address 0x3C
- SDA 8, SCL 9
Wiring the SSD1306 OLED to the ESP32-C3
Every connection in the circuit above, with the board’s own pin names.
| SSD1306 OLED pin | ESP32-C3 pin | Why |
|---|---|---|
| VCC | 3V3 | The usual blue module runs from 3.3 V, and its I2C pull-ups then pull to 3.3 V too. |
| GND | GND | Common ground. |
| SDA | GPIO 8 | ESP32-C3’s I2C data line, where Wire.begin() puts it. |
| SCL | GPIO 9 | ESP32-C3’s I2C clock line. |
On the ESP32-C3, Wire.begin() uses GPIO 8 for SDA and GPIO 9 for SCL, the Arduino core’s choice; Wire.begin(sda, scl) moves the bus to any two other pins. The display answers at address 0x3C, the address almost every 0.96 inch module ships with.
Pins to leave alone on the ESP32-C3
GPIO 8 carries the onboard LED and GPIO 9 is the BOOT button, and both are also the default I2C pins. GPIO 2, 8 and 9 are strapping pins, and only GPIO 0 to 4 can read an analog voltage.
On a real bench
The ESP32-C3 DevKitM-1 is small enough to sit on one breadboard with room for the SSD1306 OLED beside it. Its USB port goes through a USB-to-serial chip; the cheaper SuperMini boards use the C3’s own USB, where Serial needs USB CDC on boot turned on in the IDE.
The code
The sketch the circuit above runs. Open it in the editor, change a line and press Run: it compiles in your browser.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// 128 x 64 pixels, on the I2C bus: SDA GPIO 8, SCL GPIO 9
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("No SSD1306 at 0x3C");
for (;;) {}
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 0);
display.println("ESP32-C3");
display.setTextSize(1);
display.println("SSD1306 OLED");
display.drawRect(0, 40, 128, 24, SSD1306_WHITE);
display.display();
Serial.println("OLED ready");
}
void loop() {
// A counter in the box, redrawn twice a second.
display.fillRect(2, 42, 124, 20, SSD1306_BLACK);
display.setCursor(8, 48);
display.print("Up for ");
display.print(millis() / 1000);
display.print(" s");
display.display();
delay(500);
}
Adafruit_SSD1306 display(128, 64, &Wire, -1) describes a 128 by 64 panel on the Wire bus with no reset pin. display.begin(SSD1306_SWITCHCAPVCC, 0x3C) starts the controller at its address and returns false if nothing answers there, which the sketch reports on the serial monitor rather than drawing into thin air.
Every drawing call (println, drawRect, fillRect) changes a copy of the screen in the board’s RAM. Nothing reaches the glass until display() sends the whole frame, 1024 bytes, over I2C. That is why the loop clears its box, draws the new number and calls display() once.
The frame buffer is 1 KB, which the ESP32-C3 (RISC-V) has room for many times over. The font in the simulator is a 5 by 7 one with capitals, digits and punctuation, so lower case prints as capitals here.
Common mistakes with the SSD1306 OLED on the ESP32-C3
Forgetting display()
Every call before display() only changes the copy in RAM. A sketch that draws and never calls display() leaves the screen black, and that is the most common "my OLED does not work" there is.
Expecting the bus on the old ESP8266 pins
Tutorials written for the ESP8266 put I2C on GPIO 4 and 5. On an ESP32-C3 DevKitM-1 Wire.begin() uses GPIO 8 and GPIO 9. Either wire it there or call Wire.begin(sda, scl) before display.begin() with the pins you used.
Mixing up the 128x32 module
The 128 by 32 OLED uses the same chip and the same address, but the constructor needs 128, 32. Built for 64 rows, everything is drawn half off the panel.
Questions and answers
Can I test an SSD1306 OLED with an ESP32-C3 DevKitM-1 without the hardware?
Yes. The circuit at the top of this page is an ESP32-C3 DevKitM-1 with a SSD1306 OLED, running in your browser on a simulated ESP32-C3 (RISC-V). Every pixel the sketch sends is drawn on the simulated panel, so you can lay out a screen before the module arrives. Press Run it in the editor to change the wiring or the code; it is free and needs no account.
Which pins are SDA and SCL on the ESP32-C3?
On the ESP32-C3, Wire.begin() uses GPIO 8 for SDA and GPIO 9 for SCL, the Arduino core’s choice; Wire.begin(sda, scl) moves the bus to any two other pins.
Does the display work at 3.3 V?
Yes, and on an ESP32-C3 DevKitM-1 it should be powered from 3V3. The common modules have a regulator and pull-ups that then pull SDA and SCL to 3.3 V, which is what the ESP32-C3 (RISC-V) expects.
Can I use U8g2 instead of the Adafruit library?
U8g2lib.h compiles here too. The page uses Adafruit_SSD1306 because it is what most tutorials start from, and its calls (setCursor, print, display) carry over to the other Adafruit displays.
Build your own SSD1306 OLED project
Open this circuit in the editor, change the wiring or the code, and keep your version in a free account.