How to Display an Image on an SSD1306 OLED with Arduino
This comprehensive guide walks you through connecting a 0.96" or 0.91" I2C SSD1306 OLED to an Arduino, converting any PNG or JPG logo into a flash-friendly C byte array, and running tested code to draw it.
Step 1: Hardware Wiring (I2C)
The vast majority of 0.96-inch monochrome OLEDs communicate over I2C with four pins: GND, VCC, SCL, and SDA.
| OLED Pin | Arduino Uno / Nano | ESP32 (Default) | ESP8266 (NodeMCU) |
|---|---|---|---|
| GND | GND | GND | GND |
| VCC | 5V or 3.3V (check module) | 3.3V | 3.3V |
| SCL | Pin A5 | GPIO 22 | D1 (GPIO 5) |
| SDA | Pin A4 | GPIO 21 | D2 (GPIO 4) |
Note: Most breakout boards include an on-board 3.3V voltage regulator and I2C pull-up resistors, making them safe for 5V Arduino Uno pins.
Step 2: Install Adafruit Libraries
In the Arduino IDE:
- Navigate to Sketch → Include Library → Manage Libraries...
- In the search filter, type
Adafruit SSD1306and click Install. - When prompted to install dependencies (such as
Adafruit GFX LibraryandAdafruit BusIO), click Install All.
Step 3: Convert Your Image with OLED Bitmap Converter
Arduino microcontrollers have strictly limited memory. Rather than loading an uncompressed image file from an SD card, you convert the graphic into a 1-bit monochrome array stored in flash program memory (PROGMEM).
- Open the OLED Bitmap Converter.
- Upload your PNG, JPG, or BMP file.
- Select 0.96" 128x64 SSD1306 and Arduino Uno.
- Adjust the brightness threshold slider to eliminate noise, and check Invert if your original is black on white.
- Copy the generated Arduino code.
Step 4: The Complete Working Arduino Sketch
Here is a tested sketch demonstrating how to define the bitmap in flash, initialize the display at address 0x3C, and render the graphic:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// 64x64 pixel sample logo stored in PROGMEM (512 bytes)
const unsigned char logo_bmp[] PROGMEM = {
0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x18, 0x18, 0x3f, 0x00, 0x00,
// ... remaining rows generated by the converter ...
};
void setup() {
Wire.begin();
// Most 128x64 OLEDs use 0x3C; some variants use 0x3D
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
// If initialization fails, loop indefinitely
for (;;);
}
display.clearDisplay();
// drawBitmap(x, y, bitmap_data, width, height, color)
// Centering a 64x64 bitmap on a 128x64 display: x = (128 - 64)/2 = 32
display.drawBitmap(32, 0, logo_bmp, 64, 64, SSD1306_WHITE);
display.display();
}
void loop() {
// Static image display
}
Step 5: Combining Graphics and Text
You can combine drawBitmap with text headers, sensor readouts, or borders on the same screen:
display.clearDisplay();
// Draw a 32x32 battery/sensor icon on the left
display.drawBitmap(0, 16, icon_bmp, 32, 32, SSD1306_WHITE);
// Draw title and value on the right
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(42, 18);
display.print("SENSOR 1:");
display.setTextSize(2);
display.setCursor(42, 32);
display.print("24.5 C");
display.display();
Common Gotchas & Troubleshooting
- Blank Screen: If nothing renders, your display might be set to I2C address
0x3D. Changedisplay.begin(SSD1306_SWITCHCAPVCC, 0x3C)to0x3D. - Mirrored Image: If your logo renders reversed, you used an XBM (LSB-first) array. Re-export using SSD1306 Bitmap Generator for Adafruit.
- 2-Pixel Shift: If the graphic is shifted and the right edge shows sparkling static, your screen is an SH1106, not an SSD1306. Check our OLED Troubleshooting Diagnostic Guide.