Arduino OLED display tutorial: wiring, setup, and code
Overview
Monochrome 0.96-inch OLED displays are among the most versatile components for Arduino projects. With high contrast, wide viewing angles, and low power consumption, they provide an ideal user interface for sensor readouts, status dashboards, and menus.
This tutorial covers the complete setup process for I2C-based OLED screens: identifying display controller hardware, wiring to Arduino Uno and Nano boards, installing necessary libraries, and rendering text, shapes, and bitmap images.
Key topics covered:
-
Hardware identification – distinguishing I2C from SPI modules and SSD1306 from SH1106 controllers.
-
I2C wiring – connecting power, ground, SDA, and SCL lines correctly.
-
Library setup – installing Adafruit GFX and Adafruit SSD1306.
-
Text rendering – initializing the display buffer and printing custom text.
-
Graphics and bitmaps – drawing geometric shapes, activating hardware scrolling, and rendering custom icons.
Understanding your OLED display
Before wiring the display, confirm three hardware specifications:
-
3.3V vs. 5V logic – most breakout modules include an onboard low-dropout (LDO) regulator and level shifter, allowing safe operation at both 3.3 V and 5 V. Always verify your specific board specs before powering.
-
I2C vs. SPI communication – check the pin header on your board. If it has four pins labeled
GND,VCC,SCL, andSDA, it uses the I2C bus. Modules with six or seven pins (labeledCS,DC,MOSI,CLK) use SPI. This guide focuses on the 4-pin I2C version. -
SSD1306 vs. SH1106 controller chips – modules look identical from the front, but may use either an SSD1306 or SH1106 driver IC. The SSD1306 uses a 128×64 internal RAM buffer, while the SH1106 uses a 132×64 buffer. For basic text, the
Adafruit_SSD1306library works on both, though SH1106 displays may show a small 2-pixel margin offset.
Wiring the OLED display to an Arduino
The wiring shown below uses an Arduino Nano 33 BLE Sense, but the pin connections are identical on the classic Arduino Uno and standard Arduino Nano.
Standard I2C pin mapping:
- VCC to 3.3V or 5V (matches the logic voltage of your microcontroller)
- GND to Arduino GND
- SCL (serial clock) to Arduino pin A5
- SDA (serial data) to Arduino pin A4
Note: On standard ATmega328P boards (Uno and Nano), pins A4 (SDA) and A5 (SCL) are hardware-wired to the internal I2C bus. On boards with separate SDA and SCL header pins above digital pin 13, those pins connect internally to the same A4 and A5 lines.
Arduino Nano wiring diagram

Arduino Uno wiring diagram

Displaying text with Adafruit SSD1306
To control the display, install two libraries using the Arduino IDE Library Manager (Tools > Manage Libraries…):
- Adafruit GFX Library – provides core graphics primitives (lines, circles, text rendering).
- Adafruit SSD1306 – handles hardware-level display communication and buffer management.
Once installed, upload the following sketch to initialize the screen and print text:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Initialize the display with -1 if the module does not have a dedicated reset pin
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
// 0x3C is the standard I2C address for most 128x64 OLED modules
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 10);
display.println("Subscribe");
// Push the internal buffer to the physical screen
display.display();
}
void loop() {
}
Note: The Adafruit library renders all text and shapes into an internal RAM buffer on the Arduino. You must call
display.display()after drawing operations to push that buffer over I2C to the OLED controller.
Hardware scrolling, shapes, and bitmap graphics
The Adafruit_GFX library enables graphics operations beyond basic text strings:
-
Hardware scrolling – activate smooth horizontal or diagonal scrolling with
display.startscrollright(0x00, 0x0F)without continuous CPU rendering. -
Geometric primitives – draw rectangles, rounded boxes, circles, and triangles using functions like
display.drawTriangle(...)anddisplay.fillCircle(...). -
Monochrome bitmap graphics – render logos, custom icons, and sensor graphs by converting images into 1-bit monochrome byte arrays and rendering them with
display.drawBitmap().
Download all example sketches and the Python bitmap conversion script from the GitHub project repository.
To control physical motion alongside visual feedback, see the Arduino servo motor tutorial.
Saved you some time? Support my work with a coffee – thank you! ☕
FAQ and troubleshooting
Why is my Arduino OLED display blank?
A blank screen is almost always caused by an incorrect I2C address or a missing display.display() call. Most modules use address 0x3C, while some use 0x3D.
To find the address:
- Open the built-in I2C scanner via File > Examples > Wire > i2c_scanner.
- Run the sketch and check the Serial Monitor for detected device addresses.
- Verify SDA connects to A4 and SCL connects to A5.
- Ensure your code calls
display.display()after writing to the buffer.
How do I find the I2C address of my OLED display?
Upload the standard Arduino I2C scanner sketch and open the Serial Monitor at 9600 baud. The scanner interrogates every address on the bus and reports responding devices. Many breakout boards also print the default address or show a solder jumper label on the back PCB.
Should I power the OLED display from 3.3V or 5V?
Most 4-pin I2C modules include an onboard 662K voltage regulator that accepts 3.3 V to 5 V. Connect VCC to 3.3V when using 3.3V microcontrollers (such as the Nano 33 BLE Sense or ESP32) and to 5V when using 5V boards (such as the Uno or classic Nano). If your module lacks an onboard regulator, supply strictly 3.3V.
Does the SSD1306 library work with SH1106 displays?
The SSD1306 library works for basic text on SH1106 displays, but the SH1106 contains a 132-column RAM buffer instead of 128 columns. This mismatch can produce a 2-pixel vertical shift or random noise artifacts along screen borders. If this occurs, switch to a driver library designed for the SH1106 controller, such as Adafruit SH110X or U8g2.
What is the difference between I2C and SPI OLED displays?
I2C requires only two signal pins (SDA and SCL), making wiring straightforward and leaving other pins free for sensors. SPI requires four or five signal pins (MOSI, CLK, DC, CS, and reset) but transfers data at much higher clock rates, enabling smoother animations and faster refresh cycles.