ESP32 S3 UNO - SSD1309 OLED Display

This ESP32 S3 Uno SSD1309 OLED tutorial shows you how to connect a 2.42 inch 128x64 I2C OLED display to the ESP32 S3 Uno form board and draw on it with Arduino code. The same steps work for modules sold as 2.4 inch OLED. You will show text, numbers, shapes and pictures, then make the screen scroll and change its brightness with the DIYables_OLED_SSD1309 library.

ESP32 S3 Uno SSD1309 OLED 128x64

In this tutorial, you will:

  1. Wire a 2.42 inch SSD1309 I2C OLED to the SDA and SCL pins of the ESP32 S3 Uno
  2. Print text and numbers on a 128x64 OLED display
  3. Draw lines, rectangles, circles and triangles, and show bitmap images
  4. Use hardware scrolling and control the OLED contrast
  5. Use custom Adafruit GFX fonts on the screen

Hardware Preparation

1×ESP32 S3 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)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Overview of the SSD1309 2.42-Inch OLED Display

Knowing a little about the driver chip helps you pick the right library and avoid wiring mistakes. It also explains why some code written for other OLED screens almost works, but not quite.

An OLED screen has no backlight. Each pixel makes its own light, so black areas are truly black, the contrast is very high, and you can read the screen from almost any angle. The SSD1309 is the driver chip that controls a 128×64 pixel OLED panel. Its command set is close to the popular SSD1306, so code moves between the two with only small changes.

How the SSD1309 differs from the SSD1306

The SSD1309 has no built-in charge pump, so the panel needs an outside VCC supply. You do not need to worry about this: ready-made 2.42 inch and 2.4 inch breakout boards carry their own boost circuit. The SSD1309 also accepts a much higher panel voltage, up to 16 V, while the SSD1306 stops at about 4.2 V.

Screen color

The color you see (white, blue, yellow, green, or a two-color layout) comes from the OLED glass itself. You cannot change it in code.

I2C interface

This tutorial talks to the display over the I2C bus. It needs only two signal wires, SDA and SCL, and other I2C modules can share the same two wires.

SSD1309 OLED Pinout (I2C Module)

A typical 2.42 inch SSD1309 I2C module has four pins. Here is what each one does.

Pin Function
GND Ground, connect to a GND pin of the ESP32 S3 Uno
VCC Power input for the module (5V on most boards, or 3.3V if your module supports it)
SCL I2C clock line
SDA I2C data line
SSD1309 OLED Pinout

※ NOTE THAT:

  • Pin order is not the same on every brand. Always read the labels printed on your module before you connect any wire.
  • This guide was tested with the 2.42 inch SSD1309 OLED display from DIYables. Other 2.4/2.42 inch SSD1309 modules should work the same way.

ESP32 S3 Uno Pinout

The image below shows the pinout diagram of the ESP32 S3 Uno form board. Use it to find the SDA and SCL header pins and their GPIO numbers before you wire the OLED.

ESP32 S3 Uno pinout diagram

Wiring Diagram — ESP32 S3 Uno & SSD1309 OLED 128×64

On the ESP32 S3 Uno, the I2C bus is on the SDA (GPIO8) and SCL (GPIO9) header pins, not on A4 and A5 like on a classic Uno. The diagram and the photo below show the four wires you need.

The wiring diagram between ESP32 S3 Uno SSD1309 OLED 128x64

This image is created using Fritzing. Click to enlarge image

ESP32 S3 Uno SSD1309 OLED 128x64 real wiring

This image is created using Fritzing. Click to enlarge image

OLED Module Pin ESP32 S3 Uno Pin
VCC (Vin) 5V
GND GND
SDA SDA (GPIO8)
SCL SCL (GPIO9)

WARNING

The ESP32 S3 Uno pins are 3.3V only and are NOT 5V tolerant. Most 2.42 inch SSD1309 modules have an onboard regulator, so their SDA and SCL lines stay at 3.3V even when VCC is 5V. If your module pulls SDA and SCL up to 5V, power it from the 3.3V pin instead (if the module supports it), or put an I2C level shifter between the module and the board.

※ NOTE THAT:

A4 and A5 are plain analog pins on the ESP32 S3 Uno. Do not wire the OLED to them. Wire.begin() uses GPIO8 (SDA) and GPIO9 (SCL) by default, so the code needs no pin settings.

Getting Started — SSD1309 OLED with ESP32 S3 Uno

Before you upload any example, you need the right library and a basic idea of how an OLED sketch is built. Every example in this tutorial follows the same pattern, so it pays to learn it once.

Step 1: Install the DIYables_OLED_SSD1309 Library

  1. Open the Library Manager — in Arduino IDE, click the Libraries icon on the left bar.
  2. Search — type "DIYables_OLED_SSD1309" and find the library made by DIYables.
  3. Install — click the Install button.
  • Search for DIYables_OLED_SSD1309 created by DIYables and click the Install button.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Library Manager
Type:
All
Topic:
All
DIYables_OLED_SSD1309 by DIYables
Supports 128x64 and 128x32 SSD1309-based monochrome OLED displays over I2C. API compatible with Adafruit_SSD1306. Extends Adafruit_GFX for full graphics support. Works with all Arduino-compatible boards. More info
1.0.2
INSTALL
Newbiely.ino
···
1 void setup() {
Output
Serial Monitor
Ln 1, Col 1
ESP32S3 Dev Module on COM15
1
  1. Add the dependency — Arduino IDE asks you to also install the Adafruit GFX Library. Click Install All.

Step 2: Basic Programming Structure

Every SSD1309 sketch does five things. It includes the headers, creates a display object, starts the display in setup(), draws into a memory buffer, and finally sends that buffer to the screen with display().

Include the headers

#include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h>

Set the screen size

The 2.42 inch module is 128 pixels wide and 64 pixels tall.

#define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels

Create the display object

Pass -1 as the reset pin, because the module's reset line is not connected.

// Create an SSD1309 display instance on the default I2C bus (SDA = GPIO8, SCL = GPIO9) DIYables_OLED_SSD1309 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

Start the display in setup()

// Initialize the SSD1309 — use address 0x3C (default for most modules) if (!oled.begin(SSD1309_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1309 allocation failed")); while (true); }

After this, you call drawing functions such as clearDisplay(), drawPixel() or print(). Nothing shows on the screen until you call oled.display().

※ NOTE THAT:

Every code example in this guide is written for the SSD1309 OLED 128×64 (2.42 inch) with the DIYables_OLED_SSD1309 library, running on the ESP32 S3 Uno.

Quick Steps to run any example below

  1. New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
  2. Wire it up as shown in the diagram above.
  3. Connect the board to your computer with a USB Type-C cable.
  4. Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
  5. Install the library as shown in Step 1, if you have not done it yet.
  6. Copy the code of the example and paste it into Arduino IDE.
  7. Upload — click the Upload button and wait for "Done uploading".
  8. Check the screen — the OLED shows the result a moment after the board restarts.
  9. Tip: if the screen stays dark, open the Serial Monitor at 9600 baud. A "SSD1309 allocation failed" message means the board cannot talk to the OLED, so check the wiring and the I2C address.

ESP32 S3 Uno Code — Hello World on SSD1309 OLED

Start with the simplest test. If this sketch works, your wiring, library and I2C address are all correct.

The code starts the display, prints "Hello, World!" in small text, then "DIYables" in a bigger size, and a short label at the bottom. Everything is drawn once in setup(), so loop() stays empty.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-ssd1309-oled-display */ /* * DIYables OLED SSD1309 – Hello World * Prints text in two sizes on the 2.42 inch 128x64 I2C OLED. * Compatible with the ESP32 S3 Uno form board (I2C on SDA = GPIO8, SCL = GPIO9). */ #include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C DIYables_OLED_SSD1309 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(9600); if (!display.begin(SSD1309_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1309 allocation failed")); for (;;); } display.clearDisplay(); display.setTextSize(1); // 6x8 pixels per character display.setTextColor(SSD1309_PIXEL_ON); // turn pixels on display.setCursor(0, 0); display.println(F("Hello, World!")); display.println(); display.setTextSize(2); // 12x16 pixels per character display.println(F("DIYables")); display.setTextSize(1); display.println(); display.println(F("SSD1309 OLED 128x64")); display.display(); // push buffer to screen } void loop() { }

ESP32 S3 Uno Code — Display Text on SSD1309 OLED

Text is what most projects show, so it helps to see the options in one place. This example goes one step further than Hello World.

The sketch first shows two text sizes, one after the other. Then it clears the screen and prints an integer, a float and a hex number. The F() macro keeps fixed strings in flash memory instead of RAM.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-ssd1309-oled-display */ /* * DIYables OLED SSD1309 – Display Text Demo for ESP32 S3 Uno * Demonstrates text display features on 2.42" SSD1309 128x64 I2C OLED. */ #include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C DIYables_OLED_SSD1309 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(9600); if (!display.begin(SSD1309_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1309 allocation failed")); for (;;); } delay(2000); // wait for initializing display.clearDisplay(); // clear display display.setTextSize(1); // text size = 1 display.setTextColor(SSD1309_PIXEL_ON); // set text color display.setCursor(0, 10); // set position to display display.println(F("Text size = 1")); // display text display.display(); // update display delay(2000); display.setTextSize(2); // text size = 2 display.setCursor(0, 30); // set position to display display.println(F("Size = 2")); // display text display.display(); // update display delay(2000); display.clearDisplay(); // clear display display.setTextSize(1); display.setCursor(0, 0); display.println(F("Display integer:")); display.println(12345); display.println(); display.println(F("Display float:")); display.println(1.2345); display.println(); display.println(F("Display HEX:")); display.println(0xABCD, HEX); display.display(); // update display } void loop() { }

Useful Display Functions Reference

Keep this list nearby when you write your own sketches. These are the SSD1309 functions you will use most with the DIYables library.

Function What it does
oled.clearDisplay() Clears the buffer, all pixels off
oled.display() Sends the buffer to the OLED so changes become visible
oled.drawPixel(x, y, color) Turns one pixel on or off
oled.setTextSize(n) Scales the font by n (1 = 6×8, 2 = 12×16, up to 8)
oled.setCursor(x, y) Moves the text cursor to pixel (x, y)
oled.setTextColor(SSD1309_PIXEL_ON) Text color only, with a see-through background
oled.setTextColor(SSD1309_PIXEL_OFF, SSD1309_PIXEL_ON) Text color with a solid background
oled.println("message") Prints a string and goes to the next line
oled.println(number) Prints a number in decimal
oled.println(number, HEX) Prints a number in hexadecimal
oled.startscrollright(start, stop) Hardware scroll to the right from page start to page stop
oled.startscrollleft(start, stop) Hardware scroll to the left
oled.startscrolldiagright(start, stop) Hardware scroll diagonally to the right
oled.startscrolldiagleft(start, stop) Hardware scroll diagonally to the left
oled.stopscroll() Stops any running hardware scroll
oled.setContrast(value) Sets the brightness (0 to 255)
oled.dim(true/false) Dims to minimum, or goes back to the last contrast
oled.invertDisplay(true/false) Swaps on and off pixels in hardware

How to Vertically and Horizontally Center Text on the SSD1309 OLED

Centered text looks much cleaner on a small screen. The guide below shows how to measure the text and place it in the middle, and it works the same way on the ESP32 S3 Uno: How to vertical/horizontal center on OLED

ESP32 S3 Uno Code — Draw Shapes on SSD1309 OLED

Shapes let you build gauges, frames, icons and simple games. The DIYables_OLED_SSD1309 library is built on Adafruit_GFX, so you get all its drawing functions for free.

This sketch loops through pixels, lines, rectangles, circles, rounded rectangles and triangles. Each shape is drawn first as an outline and then filled with SSD1309_PIXEL_INVERSE, which flips the pixels and makes nice ring patterns. Every pattern stays on the screen for 1.5 seconds.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-ssd1309-oled-display */ /* * DIYables OLED SSD1309 – Draw Shapes for ESP32 S3 Uno * Cycles through every shape primitive on the 2.42" SSD1309 128x64 OLED. */ #include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C DIYables_OLED_SSD1309 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(9600); if (!display.begin(SSD1309_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1309 allocation failed")); for (;;); } display.clearDisplay(); } void loop() { // --- Pixels --- display.clearDisplay(); for (int16_t i = 0; i < display.width(); i += 4) { display.drawPixel(i, i * display.height() / display.width(), SSD1309_PIXEL_ON); } display.display(); delay(1500); // --- Lines --- display.clearDisplay(); for (int16_t i = 0; i < display.width(); i += 8) { display.drawLine(0, 0, i, display.height() - 1, SSD1309_PIXEL_ON); } for (int16_t i = 0; i < display.height(); i += 8) { display.drawLine(0, 0, display.width() - 1, i, SSD1309_PIXEL_ON); } display.display(); delay(1500); // --- Rectangles --- display.clearDisplay(); for (int16_t i = 0; i < display.height() / 2; i += 4) { display.drawRect(i, i, display.width() - 2 * i, display.height() - 2 * i, SSD1309_PIXEL_ON); } display.display(); delay(1500); // --- Filled rectangles (inverse) --- display.clearDisplay(); for (int16_t i = 0; i < display.height() / 2; i += 6) { display.fillRect(i, i, display.width() - 2 * i, display.height() - 2 * i, SSD1309_PIXEL_INVERSE); } display.display(); delay(1500); // --- Circles --- display.clearDisplay(); for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 5) { display.drawCircle(display.width() / 2, display.height() / 2, i, SSD1309_PIXEL_ON); } display.display(); delay(1500); // --- Filled circles (inverse) --- display.clearDisplay(); for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 6) { display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1309_PIXEL_INVERSE); } display.display(); delay(1500); // --- Rounded rectangles --- display.clearDisplay(); for (int16_t i = 0; i < display.height() / 2 - 2; i += 4) { display.drawRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i, display.height() / 4, SSD1309_PIXEL_ON); } display.display(); delay(1500); // --- Filled rounded rectangles (inverse) --- display.clearDisplay(); for (int16_t i = 0; i < display.height() / 2 - 2; i += 4) { display.fillRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i, display.height() / 4, SSD1309_PIXEL_INVERSE); } display.display(); delay(1500); // --- Triangles --- display.clearDisplay(); for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 5) { display.drawTriangle( display.width() / 2, display.height() / 2 - i, display.width() / 2 - i, display.height() / 2 + i, display.width() / 2 + i, display.height() / 2 + i, SSD1309_PIXEL_ON); } display.display(); delay(1500); // --- Filled triangles (inverse) --- display.clearDisplay(); for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 6) { display.fillTriangle( display.width() / 2, display.height() / 2 - i, display.width() / 2 - i, display.height() / 2 + i, display.width() / 2 + i, display.height() / 2 + i, SSD1309_PIXEL_INVERSE); } display.display(); delay(1500); }

ESP32 S3 Uno Code — Hardware Scrolling on SSD1309 OLED

Scrolling text catches the eye, and the SSD1309 can do it by itself. The chip moves the picture, so your ESP32 S3 Uno code is free to do other work.

There are four scroll modes: right, left, diagonal right and diagonal left. Each one takes a start page and a stop page. A page is a band 8 pixels tall, and a 64-pixel screen has pages 0 to 7. The sketch below prints "DIYables" and then runs each mode for 3 seconds.

※ NOTE THAT:

Call display() to send your content to the OLED before you start a scroll. Do not draw new content while a scroll is running — call stopscroll() first.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-ssd1309-oled-display */ /* * DIYables OLED SSD1309 – Scroll Text * Demonstrates all four hardware scroll directions on the 2.42" OLED. * Compatible with the ESP32 S3 Uno form board (I2C on SDA = GPIO8, SCL = GPIO9). */ #include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C DIYables_OLED_SSD1309 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(9600); if (!display.begin(SSD1309_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1309 allocation failed")); for (;;); } display.clearDisplay(); display.setTextSize(2); display.setTextColor(SSD1309_PIXEL_ON); display.setCursor(10, 24); display.println(F("DIYables")); display.display(); delay(2000); } void loop() { // Scroll right across all pages display.startscrollright(0x00, 0x07); delay(3000); display.stopscroll(); delay(500); // Scroll left display.startscrollleft(0x00, 0x07); delay(3000); display.stopscroll(); delay(500); // Diagonal scroll right display.startscrolldiagright(0x00, 0x07); delay(3000); display.stopscroll(); delay(500); // Diagonal scroll left display.startscrolldiagleft(0x00, 0x07); delay(3000); display.stopscroll(); delay(500); }

ESP32 S3 Uno Code — Display Bitmap Image on SSD1309 OLED

A logo or an icon makes your project look finished. The OLED cannot read a PNG or JPG file, so you first turn the picture into a C byte array. The free image2cpp online tool does this for you:

  1. Upload your image (PNG, JPG, BMP and so on).
  2. Set the canvas size to 128×64 or smaller.
  3. Choose Arduino code as the output format.
  4. Copy the array it creates into your sketch.
image to bitmap array

The example switches between a small 16×16 heart in the middle of the screen and a full-screen DIYables logo. After that, it inverts the whole display for 2 seconds.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-ssd1309-oled-display */ /* * DIYables OLED SSD1309 – Display Image Demo for ESP32 S3 Uno * Displays bitmap images on the 2.42" SSD1309 128x64 I2C OLED. */ #include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C DIYables_OLED_SSD1309 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // 16x16 heart bitmap const unsigned char heart16x16[] PROGMEM = { 0x00, 0x00, 0x03, 0xc0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x0f, 0xf0, 0x03, 0xc0, 0x00, 0x00 }; // 128x64 DIYables logo bitmap const unsigned char diyablesLogo[] PROGMEM = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x7f, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x7f, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xc0, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0x80, 0x00, 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x03, 0x80, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x03, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x7f, 0xff, 0x00, 0x0f, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x7f, 0xff, 0x80, 0x0f, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x7f, 0xff, 0x80, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x7f, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x7f, 0xff, 0xf0, 0x7f, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xfe, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xfe, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x7f, 0xff, 0xf0, 0x7f, 0xff, 0xc0, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x7f, 0xff, 0x80, 0x07, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x7f, 0xff, 0x80, 0x07, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xe0, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x03, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x07, 0x80, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0xe0, 0x00, 0x7f, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x00, 0x1f, 0xe0, 0x00, 0x1f, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x7f, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x7f, 0xfc, 0x00, 0x03, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; void setup() { Serial.begin(9600); if (!display.begin(SSD1309_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1309 allocation failed")); for (;;); } delay(2000); display.setCursor(0, 0); } void loop() { // Display 16x16 heart icon display.clearDisplay(); display.drawBitmap((SCREEN_WIDTH - 16) / 2, (SCREEN_HEIGHT - 16) / 2, heart16x16, 16, 16, SSD1309_PIXEL_ON); display.display(); delay(2000); // Display full-screen DIYables logo display.clearDisplay(); display.drawBitmap(0, 0, diyablesLogo, 128, 64, SSD1309_PIXEL_ON); display.display(); delay(2000); // Invert display display.invertDisplay(true); delay(2000); display.invertDisplay(false); delay(500); }

※ NOTE THAT:

  • The bitmap must not be bigger than the screen (128×64 for the 2.42 inch module).

ESP32 S3 Uno Code — Contrast and Dim on SSD1309 OLED

Brightness control saves power and keeps the screen easy to read in a dark room. The SSD1309 has 256 contrast steps, from 0 to 255.

The sketch draws a test pattern, then slowly raises the contrast to full and lowers it again with setContrast(). After that, it uses dim() to jump to the lowest brightness and back.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-ssd1309-oled-display */ /* * DIYables OLED SSD1309 – Contrast & Dim * Sweeps contrast from 0→255→0 then toggles dim mode on the 2.42" OLED. * Compatible with the ESP32 S3 Uno form board (I2C on SDA = GPIO8, SCL = GPIO9). */ #include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C DIYables_OLED_SSD1309 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(9600); if (!display.begin(SSD1309_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1309 allocation failed")); for (;;); } // Draw a test pattern so the contrast changes are visible display.clearDisplay(); display.fillRect(0, 0, 64, 32, SSD1309_PIXEL_ON); display.fillRect(64, 32, 64, 32, SSD1309_PIXEL_ON); display.setTextSize(1); display.setTextColor(SSD1309_PIXEL_INVERSE); display.setCursor(16, 28); display.println(F("Contrast Demo")); display.display(); delay(2000); } void loop() { // Ramp up for (int c = 0; c <= 255; c += 5) { display.setContrast((uint8_t)c); delay(30); } delay(1000); // Ramp down for (int c = 255; c >= 0; c -= 5) { display.setContrast((uint8_t)c); delay(30); } delay(1000); // Quick dim toggle display.dim(true); // minimum brightness delay(2000); display.dim(false); // restore delay(2000); }

ESP32 S3 Uno Code — Custom External Fonts on SSD1309 OLED

The built-in font is small and blocky. For a nicer look, the Adafruit GFX library comes with many FreeFont typefaces: Serif, Sans and Mono, each in regular, bold and italic, in several sizes.

To use one, include its header file and call setFont(). The sketch below shows the built-in font first, then FreeSerif 9pt, FreeSansBold 12pt and FreeMono 9pt, each for 3 seconds. Call setFont(NULL) to go back to the built-in font.

※ NOTE THAT:

  • With an external font, the cursor Y position is the text baseline, not the top-left corner. This is different from the built-in 5×7 font.
  • External fonts are stored in flash memory. Small boards like the classic Uno (32 KB flash) run out of space fast, but the ESP32 S3 Uno has megabytes of flash, so you can use several fonts in one sketch.
/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-ssd1309-oled-display */ /* * DIYables OLED SSD1309 – External Fonts * Cycles through three FreeFont typefaces on the 2.42" SSD1309 OLED. * Compatible with the ESP32 S3 Uno form board (I2C on SDA = GPIO8, SCL = GPIO9). */ #include <Wire.h> #include <Adafruit_GFX.h> #include <DIYables_OLED_SSD1309.h> #include <Fonts/FreeSerif9pt7b.h> #include <Fonts/FreeSansBold12pt7b.h> #include <Fonts/FreeMono9pt7b.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C DIYables_OLED_SSD1309 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(9600); if (!display.begin(SSD1309_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1309 allocation failed")); for (;;); } display.clearDisplay(); display.display(); } void loop() { // ── Built-in 5×7 font ── display.clearDisplay(); display.setFont(NULL); display.setTextSize(1); display.setTextColor(SSD1309_PIXEL_ON); display.setCursor(0, 0); display.println(F("Built-in 5x7 font")); display.println(); display.setTextSize(2); display.println(F("DIYables")); display.display(); delay(3000); // ── FreeSerif 9pt ── display.clearDisplay(); display.setFont(&FreeSerif9pt7b); display.setTextSize(1); display.setTextColor(SSD1309_PIXEL_ON); display.setCursor(0, 14); // Y = baseline display.println(F("FreeSerif 9pt")); display.setCursor(0, 38); display.println(F("DIYables OLED")); display.setCursor(0, 58); display.println(F("Hello World!")); display.display(); delay(3000); // ── FreeSansBold 12pt ── display.clearDisplay(); display.setFont(&FreeSansBold12pt7b); display.setTextSize(1); display.setTextColor(SSD1309_PIXEL_ON); display.setCursor(0, 20); display.println(F("SansBold")); display.setCursor(0, 52); display.println(F("DIYables")); display.display(); delay(3000); // ── FreeMono 9pt ── display.clearDisplay(); display.setFont(&FreeMono9pt7b); display.setTextSize(1); display.setTextColor(SSD1309_PIXEL_ON); display.setCursor(0, 14); display.println(F("FreeMono 9pt")); display.setCursor(0, 34); display.println(F("0123456789")); display.setCursor(0, 54); display.println(F("!@#$%^&*()")); display.display(); delay(3000); }

SSD1309 OLED Diagnostics with ESP32 S3 Uno

A blank screen after upload is the most common problem with OLEDs. Go through these checks one by one.

Check the wiring

Make sure SDA goes to SDA (GPIO8), SCL goes to SCL (GPIO9), and VCC and GND are connected. On the ESP32 S3 Uno, A4 and A5 do not work for I2C.

Check the driver chip

This library is made for the SSD1309. A module with another chip, such as the SH1106, will not respond the right way.

Find the I2C address

Most SSD1309 modules use 0x3C, but some use 0x3D. Upload the I2C scanner sketch below and open the Serial Monitor at 9600 baud to see the real address.

// I2C address scanner — prints every detected device to the Serial Monitor // ESP32 S3 Uno: SDA = GPIO8, SCL = GPIO9 (default Wire pins) #include <Wire.h> void setup() { Wire.begin(); Serial.begin(9600); Serial.println("I2C Scanner"); } void loop() { byte error, address; int nDevices = 0; Serial.println("Scanning..."); for (address = 1; address < 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.print(address, HEX); Serial.println(" !"); nDevices++; } else if (error == 4) { Serial.print("Unknown error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } if (nDevices == 0) Serial.println("No I2C devices found"); else Serial.println("done"); delay(5000); }

When the OLED is found, the Serial Monitor shows something like this:

∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
I2C Scanner Scanning... I2C device found at address 0x3C ! done
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2

Call display()

The SSD1309 library draws into a buffer in RAM. Nothing shows on the screen until you call oled.display().

Check the power

The 2.42 inch module needs more current than small OLEDs, about 20–40 mA at full brightness. Use a good USB cable and port so the board gets enough power.

FAQ

Which ESP32 S3 Uno pins do I use for the SSD1309 I2C OLED?

Use the SDA (GPIO8) and SCL (GPIO9) header pins. On this board A4 and A5 are analog pins only, not I2C. Wire.begin() already uses GPIO8 and GPIO9, so you do not need to set the pins in code.

Can I power the 2.42 inch OLED from 5V on the ESP32 S3 Uno?

Yes, most 2.42 inch SSD1309 modules run from 5V and have their own regulator. The important part is the SDA and SCL voltage, because ESP32 S3 Uno pins are not 5V tolerant. If your module pulls these lines up to 5V, use 3.3V power (if the module supports it) or an I2C level shifter.

Does the same code work on the UNO R4 and the ESP32 S3 Uno?

Yes. The DIYables_OLED_SSD1309 library and the Adafruit GFX library work on both boards, and the example sketches are the same. Only the wiring changes: on the ESP32 S3 Uno, use the SDA and SCL header pins instead of A4 and A5.

Can I change the color of the SSD1309 OLED in code?

No. The color comes from the OLED panel itself (white, blue, yellow, green or two colors). The code can only turn each pixel on or off.

Can I connect other I2C sensors together with the OLED?

Yes. I2C is a shared bus, so you can connect more modules to the same SDA and SCL pins. Each device must have a different address. Run the I2C scanner to check that all of them show up.

What if my project needs more pins than the Uno headers give?

The ESP32 S3 Uno has two extra rows of holes with more GPIOs. GPIO15 and GPIO16 offer I/O, PWM and analog. GPIO45 and GPIO35–GPIO42 offer I/O and PWM. GPIO47 and GPIO48 are output only, with PWM. Solder pin headers to use them and write the GPIO number in code. For an OLED project, GPIO35–GPIO42 are good for extra buttons, and GPIO15/16 fit analog sensors. Be careful with two things. First, GPIO47 and GPIO48 may run at 1.8V instead of 3.3V on some modules (especially ones with "V" in the name, like R8V or R16V), so 3.3V devices can be damaged or act strangely. Second, GPIO0, GPIO3 (D6), GPIO45 and GPIO46 (D9) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code. Use the other extra pins first.

Troubleshooting

Problem Possible Cause Solution
No COM port in Arduino IDE USB driver missing or board not in upload mode Install the CP210x or CH340 driver, try another USB cable, or hold BOOT while you press RESET
Screen stays dark OLED wired to A4/A5 or a loose wire Connect SDA to SDA (GPIO8) and SCL to SCL (GPIO9), and check VCC and GND
"SSD1309 allocation failed" in Serial Monitor Wrong I2C address or no I2C link Run the I2C scanner and put the found address (0x3C or 0x3D) in SCREEN_ADDRESS
Code does not compile DIYables_OLED_SSD1309 or Adafruit GFX library missing Install both libraries from the Library Manager
Picture is garbled or shifted The module uses another driver chip such as SH1106 Check the chip on your module and use a library made for that chip
Screen flickers or resets Weak USB power or long thin wires Use a better USB port and cable, and keep the I2C wires short
Nothing changes after drawing display() is not called Call oled.display() after your drawing functions
Serial Monitor shows strange characters Wrong baud rate Set the Serial Monitor to 9600 baud

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!