ESP32 UNO - SSD1309 OLED Display
Need a sharp, bright screen for your ESP32 Uno? A 2.42 inch SSD1309 OLED needs only four wires and gives you 128x64 pixels of crisp monochrome output. Plug it into the ESP32 Uno form board, add the DIYables_OLED_SSD1309 library, and your sketch can print text, draw shapes and scroll pictures on this I2C OLED display.

By the end, you can:
- Wire a 2.42 inch SSD1309 OLED to the I2C pins of the ESP32 Uno
- Show text and numbers in different sizes
- Draw lines, boxes, circles and triangles, and show a bitmap
- Scroll the screen with hardware scrolling and change the contrast
- Load custom Adafruit GFX fonts
Components You Need
| 1 | × | ESP32 Uno-form Board | |
| 1 | × | USB Cable Type-A to Type-C (for USB-A PC) | |
| 1 | × | USB Cable Type-C to Type-C (for USB-C PC) | |
| 1 | × | SSD1309 I2C OLED Display 128x64 (2.42 inch) | |
| 1 | × | Jumper Wires |
Or you can buy the following kits:
| 1 | × | DIYables Sensor Kit (18 sensors/displays) |
Additionally, some of these links are for products from our own brand, DIYables .
What Is the SSD1309 2.42-Inch OLED?
By the end of this part, you know what the chip does and why it matters for your wiring.
An OLED pixel makes its own light, so black is truly black and you can read the screen from any angle. The SSD1309 is the driver chip behind many 128×64 OLED panels. Its commands are close to the SSD1306 chip, so code moves between the two with small changes.
| Feature | SSD1309 Module |
|---|---|
| Resolution | 128×64 pixels |
| Interface | I2C (two signal wires) |
| Default I2C address | 0x3C (some modules use 0x3D) |
| Panel supply | external, built into the module as a boost circuit |
| Maximum panel voltage | up to 16V (SSD1306 stops near 4.2V) |
| Color | fixed by the glass - white, blue, yellow, green or two-tone |
Good to know: you cannot change the color in code. Software only turns each pixel on or off.
Pins of the I2C Module
A typical module has four pins.
| Pin | Job |
|---|---|
| GND | Ground |
| VCC | Power input - 5V on most modules, 3.3V if your module allows it |
| SCL | I2C clock line |
| SDA | I2C data line |

※ NOTE THAT:
- Pin order is different between brands. Read the silkscreen labels on your module before you connect anything.
- This guide was checked with the 2.42 inch SSD1309 OLED from DIYables. Other 2.4 or 2.42 inch SSD1309 modules should behave the same way.
ESP32 Uno Pinout
Every Uno header pin on the ESP32 Uno form board has its own GPIO number, and your sketch uses that number. Look at the diagram first, then find the SDA and SCL pins you need for the OLED.

How to Connect the OLED
By the end of this part, four wires link the OLED and the ESP32 Uno.

This image is created using Fritzing. Click to enlarge image

This image is created using Fritzing. Click to enlarge image
| OLED Pin | Connect To |
|---|---|
| VCC (Vin) | 5V |
| GND | GND |
| SDA | SDA (GPIO21) |
| SCL | SCL (GPIO22) |
Good to know: on the ESP32 Uno, pins A4 and A5 are NOT I2C. They are input-only analog pins. Use the dedicated SDA and SCL header pins. Wire.begin() already uses GPIO21 and GPIO22, so the code needs no pin setting.
WARNING
ESP32 Uno pins are 3.3V logic and are NOT 5V tolerant. Most 2.42 inch modules have an onboard regulator, so SDA and SCL stay at 3.3V even with 5V on VCC. If your module pulls SDA and SCL up to 5V, power it from the 3.3V pin if it supports that, or add an I2C level shifter.
Set Up the Library and Learn the Pattern
By the end of this part, the library is installed and you know the five steps every OLED sketch follows.
Step 1 — Add the DIYables_OLED_SSD1309 library
- Open Arduino IDE and click the Libraries icon in the left bar.
- Type "DIYables_OLED_SSD1309" in the search box and pick the one made by DIYables.
- Hit Install and wait for it to finish.
- Search for DIYables_OLED_SSD1309 created by DIYables and click the Install button.
- The IDE asks for a dependency, the Adafruit GFX Library. Say yes with Install All.
Step 2 — Learn the sketch pattern
Each sketch includes the headers, builds a display object, starts the display in setup(), draws into a memory buffer, and sends the buffer to the screen with display().
Headers:
Size of the panel, 128 wide and 64 high:
Display object (the -1 means no reset pin is wired):
Start-up inside setup():
Next you draw with calls like clearDisplay(), drawPixel() or print(). The panel stays unchanged until oled.display() runs.
※ NOTE THAT:
Every example below uses the SSD1309 OLED 128×64 (2.42 inch) and the DIYables_OLED_SSD1309 library on the ESP32 Uno.
Upload and Test any example
- First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
- Build the circuit by following the wiring table above.
- Plug in the USB Type-C cable between the ESP32 Uno and your computer.
- Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
- Install the libraries from Step 1 if you have not done so.
- Copy the code of an example below into Arduino IDE.
- Upload the sketch and wait for "Done uploading".
- Look at the OLED. The picture shows up a second after the board restarts.
- Pro tip: keep the Serial Monitor open at 9600 baud while you test. If you see "SSD1309 allocation failed", the board cannot reach the OLED, so check SDA, SCL and the I2C address first.
Example 1 — Hello World
By the end of this part, the screen shows your first message.
| Code Part | What It Does |
|---|---|
| display.begin() | Starts the OLED at address 0x3C |
| setTextSize(1) | Small 6×8 characters for the first line |
| setTextSize(2) | Large 12×16 characters for the word DIYables |
| display.display() | Sends the buffer to the screen once |
| loop() | Stays empty because the picture never changes |
The screen shows a greeting, a big word and a small label. If this works, your wiring and library are fine.
Example 2 — Text and Numbers
By the end of this part, you can print different sizes, integers, floats and hex numbers.
| Code Part | What It Does |
|---|---|
| setCursor(x, y) | Chooses where the next text starts |
| println(F("...")) | Prints fixed text and keeps it in flash, not RAM |
| println(12345) | Prints an integer in decimal |
| println(1.2345) | Prints a float with two decimals |
| println(0xABCD, HEX) | Prints a number in hexadecimal |
You see two text sizes first. After that, the screen clears and lists the three number formats.
Display Function Reference
| Function | What It Does |
|---|---|
| oled.clearDisplay() | Empties the frame buffer |
| oled.display() | Pushes the buffer out to the panel |
| oled.drawPixel(x, y, color) | Sets or clears one pixel |
| oled.setTextSize(n) | Text size factor n - size 1 is 6×8 pixels, size 3 is 18×24, up to 8 |
| oled.setCursor(x, y) | Sets where the next character is drawn |
| oled.setTextColor(SSD1309_PIXEL_ON) | Draws text with a see-through background |
| oled.setTextColor(SSD1309_PIXEL_OFF, SSD1309_PIXEL_ON) | Draws text with a solid background |
| oled.println("message") | Prints a string and starts a new line |
| oled.println(number) | Prints an integer in decimal |
| oled.println(number, HEX) | Prints an integer in hexadecimal |
| oled.startscrollright(start, stop) | Moves the picture right, between two pages |
| oled.startscrollleft(start, stop) | Moves the picture left, between two pages |
| oled.startscrolldiagright(start, stop) | Moves the picture up and right |
| oled.startscrolldiagleft(start, stop) | Moves the picture up and left |
| oled.stopscroll() | Stops any running scroll |
| oled.setContrast(value) | Sets brightness from 0 to 255 |
| oled.dim(true/false) | Switches between the lowest brightness and the last contrast |
| oled.invertDisplay(true/false) | Swaps lit and dark pixels in hardware |
Put Text in the Middle of the Screen
A centered title looks tidy on a small display. Follow this article to measure your text and place it in the middle; the method is the same on the ESP32 Uno: How to vertical/horizontal center on OLED.
Example 3 — Shapes
By the end of this part, you can draw every basic shape.
The library is built on Adafruit_GFX, so you get pixels, lines, rectangles, circles, triangles and rounded boxes. The sketch shows each shape as an outline, then filled with inverted pixels.
Each pattern stays on screen for 1.5 seconds, then the next one appears.
Example 4 — Hardware Scrolling
By the end of this part, the text moves without any work from the CPU.
The chip has a scroll engine with four modes: right, left, diagonal right and diagonal left. Give each mode a first page and a last page. One page is a strip 8 pixels high, which gives pages 0 to 7 on this screen.
※ NOTE THAT:
Call display() first, then start the scroll. Do not draw while a scroll runs - call stopscroll() before you draw again.
Each mode runs for 3 seconds, then stops for half a second.
Example 5 — Bitmap Images
By the end of this part, your own logo can appear on the OLED.
The OLED cannot read PNG or JPG files. Turn the picture into a C array with the free image2cpp online tool:
- Open the converter and add a PNG, JPG or BMP file.
- Set the canvas to 128×64 or smaller.
- Choose Arduino code for the output.
- Copy the array it prints into your code.

The example shows a 16×16 heart, then a full-screen DIYables logo, then inverts the whole display.
※ NOTE THAT:
- The bitmap must fit the screen (128×64 for the 2.42 inch module).
Example 6 — Contrast and Dim
By the end of this part, you can set the brightness in code.
The brightness has 256 levels. setContrast() selects an exact level, while dim() toggles between the lowest level and the last one you set.
The brightness fades up to full, fades down to zero, then dims and returns.
Example 7 — Custom Fonts
By the end of this part, the screen can show serif, sans and mono fonts.
Adafruit GFX ships many FreeFont typefaces. Include a font header and call setFont(). Pass NULL to setFont() when you want the default font again.
※ NOTE THAT:
- With a custom font, the cursor Y value is the text baseline, not the top-left corner.
- Fonts live in flash memory. The ESP32 Uno has 4MB of flash, so you can mix several fonts in one sketch.
Video Tutorial
See the ESP32 Uno build in action in the video below. It runs a "robot eyes" animation that changes mood when you tap a TTP223 touch sensor on D13 (GPIO18).
Good to know: the demo reads analogRead(2) on A0 (GPIO2) only to seed the random number generator. It does not need analogSetAttenuation.
ESP32 Uno vs UNO R4 for This Project
By the end of this part, you know what changes when you move this OLED project from the UNO R4 to the ESP32 Uno.
| Item | Arduino UNO R4 | ESP32 Uno |
|---|---|---|
| Logic voltage | 5V | 3.3V |
| I2C pins | A4 and A5 | SDA (GPIO21) and SCL (GPIO22) |
| OLED libraries | DIYables_OLED_SSD1309 and Adafruit GFX | same libraries, no change |
| Touch sensor in the demo | D13 | D13 (GPIO18) |
| Random seed in the demo | analogRead(A0) | analogRead(2) on A0 (GPIO2) |
| Arduino IDE board | Arduino UNO R4 WiFi | ESP32 Dev Module |
The OLED sketches run as they are. Only the two I2C wires move to the SDA and SCL header pins. Check that your OLED keeps SDA and SCL at 3.3V.
Go Wireless: Send Messages to the OLED
By the end of this part, you have an idea for showing phone text on this screen.
The ESP32 Uno has WiFi and Bluetooth, so the OLED can show messages from your phone. Type a line in a chat page, and your sketch prints it on the display with the same println() calls you used above.
Try These Next
- Print a live sensor value on the OLED and update it every second.
- Show a centered title and a small clock line.
- Build your own bitmap logo and scroll it across the screen.
- Add the touch sensor from the demo and change screens with each tap.
Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| No COM port in Arduino IDE | CH340 driver missing or a charge-only USB cable | Install the CH340 driver and use a data USB Type-C cable |
| Upload fails with "Failed to connect" or "Waiting for download" | Board not in upload mode | Hold the BOOT button when the upload starts, then release it |
| Display stays black | Wires on A4 and A5, or a loose jumper | Move SDA to the SDA (GPIO21) header and SCL to the SCL (GPIO22) header, then recheck VCC and GND |
| Serial Monitor prints the allocation error | The OLED does not answer at the address in the sketch | Scan the bus, then set SCREEN_ADDRESS to the address you see (0x3C or 0x3D) |
| Compile error about a missing header | One of the two libraries is not installed | Add DIYables_OLED_SSD1309 and Adafruit GFX in the Library Manager |
| Picture is garbled or shifted | Module uses another chip such as SH1106 | Check the chip on your module and use a matching library |
| Picture flickers or the board reboots | Poor USB power or long thin jumpers | Try a stronger USB port, a shorter cable and shorter I2C wires |
| Nothing changes after drawing | display() is never called | Call oled.display() after your drawing code |
| Strange characters in Serial Monitor | Wrong baud rate | Set the Serial Monitor to 9600 baud |
| Robot eyes demo does not react to touch | Touch sensor wired to the wrong pin | Connect the TTP223 I/O pin to D13 (GPIO18) and power it from 3.3V |
I2C address scanner
Upload this sketch to find the real address of your OLED, then open the Serial Monitor at 9600 baud.
When the OLED is found, you see:
FAQ
Which ESP32 Uno pins connect to an SSD1309 I2C OLED?
Plug the two I2C wires into the SDA (GPIO21) and SCL (GPIO22) headers. A4 and A5 will not work for I2C here. The default Wire.begin() already uses these two pins.
Can I power the 2.42 inch OLED from 5V?
Yes, most modules have a regulator and run from 5V. The point to check is the SDA and SCL level, because ESP32 Uno pins are not 5V tolerant. If your module pulls them to 5V, use 3.3V power or an I2C level shifter.
Will the UNO R4 OLED code work on the ESP32 Uno?
Yes. The DIYables_OLED_SSD1309 and Adafruit GFX libraries work on both boards. Only the wiring changes, since I2C moves from A4 and A5 to the SDA and SCL header pins.
Why does my SSD1309 OLED show nothing?
First check the wires and the I2C address. Then make sure your code calls display(), because drawing only changes the memory buffer. Also confirm that your module uses the SSD1309 chip and not the SH1106.
Can I change the OLED color in code?
No. The glass of the panel sets the color, so code can only turn pixels on or off.
How do I find the I2C address of my OLED?
Run the scanner sketch in the Troubleshooting section. Most SSD1309 modules use 0x3C, and some use 0x3D.
Can I share the I2C bus with other sensors?
Yes. I2C is a shared bus, so more modules can sit on the same two wires if their addresses differ. The scanner lists every address it hears.
Can I show a web page message on the OLED with the ESP32 Uno?
Yes. The ESP32 Uno has WiFi and Bluetooth, so a phone can send text that your sketch prints with println(). See the Go Wireless section for ready tutorials.
Do I need the CH340 driver for this board?
Often yes on Windows. If no COM port shows up, install the CH340 driver and try a data-capable USB Type-C cable.
Can I use an OLED shield or other Uno shields on the ESP32 Uno?
The header has the Uno shape, so many shields fit, but check the GPIO map. Shields that use A4 and A5 for I2C will not work, because those pins are not I2C on this board.
What if my project needs more pins than the Uno headers give?
The ESP32 Uno has a few extra holes near the power header. GPIO32 and GPIO33 offer I/O, PWM and analog on ADC1, so they also work while WiFi is on. GPIO15 offers I/O, PWM and analog on ADC2. Add pin headers by soldering, then use the plain GPIO number in your sketch. For an OLED project, GPIO32 and GPIO33 suit extra buttons or an analog sensor. Watch out for two things. First, GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code, so use GPIO32 and GPIO33 first. Second, never use the six holes under the digital header (SD0-SD3, CMD, CLK = GPIO6-GPIO11). They are wired to the flash chip, and using them crashes the board.