Arduino OLED Display Tutorial (SSD1306 – I2C & SPI)

by Rachana Jain in Circuits > Arduino

111 Views, 0 Favorites, 0 Comments

Arduino OLED Display Tutorial (SSD1306 – I2C & SPI)

Interfacing OLED Display Module with Arduino.png

Ever wanted to display sensor data, messages, or graphics on your Arduino project in a clean and modern way? OLED displays make this incredibly easy while offering much better visuals than traditional LCDs.

In this project, you’ll learn how to connect a small OLED display to Arduino and use it to show text and simple graphics. This setup is commonly used in IoT devices, wearable electronics, and compact embedded systems where clarity and low power consumption are important.

By the end, you’ll understand both I2C and SPI methods so you can choose what fits your project best.

Supplies

Components Required

  1. Arduino Nano
  2. 0.96" OLED Display (SSD1306, 128×64)
  3. Jumper wires
  4. Breadboard (optional)
  5. USB cable

Understanding the OLED Module

SPI OLED Display Pinout.png

Unlike LCDs, OLED displays don’t need a backlight. Each pixel emits its own light, which results in:

  1. High contrast (deep blacks)
  2. Wide viewing angles
  3. Lower power consumption

The display is controlled by the SSD1306 driver, which has its own memory. That means your Arduino sends data once, and the display takes care of refreshing itself.

👉 This makes it efficient and perfect for small embedded projects.


OLED Pinout

I2C OLED

  1. GND → Ground
  2. VCC → 3.3V–5V
  3. SCL → Clock
  4. SDA → Data


SPI OLED

  1. GND → Ground
  2. VCC → Power
  3. SCK → Clock
  4. MOSI → Data
  5. CS → Chip Select
  6. DC → Data/Command

Working Principle

OLED displays operate by emitting light directly from each pixel, eliminating the need for a backlight. This results in deeper blacks, better visibility, and lower power consumption compared to LCD technology.

The SSD1306 controller includes a 1KB internal buffer (GDDRAM) that stores pixel states. The display is divided into pages and columns, where each bit corresponds to a pixel. When the Arduino sends data via I2C or SPI, it is written to this memory, and the controller continuously refreshes the display.

This architecture reduces processing overhead on the microcontroller and allows smooth rendering of text, shapes, and bitmaps.

Hardware Setup and Connections

doc_pics.png
Slide3.PNG

I2C Connection (Recommended for Simplicity)

For most beginners and standard applications, I2C is the preferred method due to minimal wiring:

  1. Connect VCC of OLED to Arduino 5V
  2. Connect GND to Arduino GND
  3. Connect SCL to Arduino A5
  4. Connect SDA to Arduino A4

This setup is widely supported by libraries and works reliably for text and basic graphics.

SPI Connection (For High-Speed Applications)

If your application requires faster updates or more complex graphics:

  1. Connect VCC → 5V
  2. Connect GND → GND
  3. Connect SCK → D10
  4. Connect MOSI → D9
  5. Connect CS → D12
  6. Connect DC → D11

SPI communication uses dedicated lines, enabling faster data transfer compared to I2C.

Basic OLED Functionality

Displaying Text on OLED Display
/*
Code to display Strings on I2C OLED display as well as SPI OLED display, user has to update the user configuartion based on OLED used
by www.playwithcircuit.com
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSans12pt7b.h>
// USER CONFIGURATION
#define OLED_TYPE 1 // 0 = I2C, 1 = SPI
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// I2C CONFIG
#if OLED_TYPE == 0
#define OLED_ADDR 0x3C
#define OLED_RESET -1 // I2C OLED display doesn't have Exposed reset pin
#endif
// SPI CONFIGURATIONS
#if OLED_TYPE == 1
#define OLED_MOSI 9
#define OLED_CLK 10
#define OLED_DC 11
#define OLED_CS 12
#define OLED_RESET -1 // if SPI OLED display doesn't have Exposed reset pin then its value is -1 else set it to 13 and connect it with pin 13
#endif
// DISPLAY OBJECT
#if OLED_TYPE == 0
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#else
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
OLED_MOSI,
OLED_CLK,
OLED_DC,
OLED_RESET,
OLED_CS);
#endif
// SETUP
void setup() {
// this serial port is to display error, if occurred during OLED init
Serial.begin(9600);
// begin
#if OLED_TYPE == 0
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("SSD1306 init failed");
while (1)
;
}
#else
if (!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println("SSD1306 init failed");
while (1)
;
}
#endif
}
void loop() {
// clear the Display
display.clearDisplay();
// draw Pixel on screen
display.drawPixel(10, 10, WHITE);
display.drawPixel(20, 10, WHITE);
display.drawPixel(30, 10, WHITE);
display.display();
delay(3000);
// Display the text on OLED
display.clearDisplay();
display.setCursor(0, 20);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print("Hello OLED Display");
display.display();
delay(3000);
// printing hex numbers
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(2);
display.println("Number: ");
display.println(255);
display.println("HEX:");
display.print(255, HEX);
display.display();
delay(3000);
// using write function
display.clearDisplay();
display.setCursor(0, 0);
display.write(3);
display.write(0x20);
display.write(4);
display.write(0x20);
display.write(5);
display.write(0x20);
display.write(6);
display.write(0x20);
display.display();
display.setTextSize(1);
delay(3000);
// changing font
display.clearDisplay();
display.setFont(&FreeSans12pt7b);
display.setCursor(0, 30);
display.setTextColor(WHITE);
display.print("FreeSans12pt7b");
display.display();
delay(3000);
// Reset to default font
display.setFont(NULL);
// inverting the display
display.clearDisplay();
display.setCursor(0, 20);
display.setTextSize(2);
display.print("Invert Testing");
display.display();
delay(3000);
display.invertDisplay(true);
delay(3000);
display.invertDisplay(false);
// scrolling right
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println("Scroll Right");
display.display();
display.startscrollright(0x00, 0x07);
delay(3000);
display.stopscroll();
// scrolling left
display.clearDisplay();
display.setCursor(0, 0);
display.println("Scroll Left");
display.display();
display.startscrollleft(0x00, 0x07);
delay(3000);
display.stopscroll();
// scrolling diagonally right
display.clearDisplay();
display.setCursor(0, 0);
display.println("Diag Right");
display.display();
display.startscrolldiagright(0x00, 0x07);
delay(3000);
display.stopscroll();
// scrolling diagonally left
display.clearDisplay();
display.println("DiagLeft");
display.display();
display.startscrolldiagleft(0x00, 0x07);
delay(3000);
display.stopscroll();
// clear the display
display.clearDisplay();
display.display();
}

Conclusion

Interfacing an OLED display with Arduino is a practical and scalable solution for adding visual output to embedded systems. With support for both I2C and SPI, it offers flexibility for different project requirements—from simple sensor displays to advanced graphical interfaces.

For engineers developing production-ready designs, integrating OLED displays into custom PCBs can significantly improve reliability and reduce wiring complexity.

For complete step-by-step instructions, detailed explanations, and implementation guidance, refer to the full tutorial:

👉 https://playwithcircuit.com/interfacing-oled-display-with-arduino/