Introduction: OLED I2c Display With Arduino

Picture of OLED I2c Display With Arduino

In this instructable I will show you how to connect and test a 0.96" i2c OLED display module to an arduino.


  • Breadboard and hookup wires
  • Arduino (using a nano v3 5v 16mhz clone in this case)
  • External power supply (regulated 5v)
  • The OLED i2c display

I bought my display around 6 months ago, and I can’t seem to find the exact display on ebay now, but searching for “0.96 ssd1306 i2c OLED” shows a whole lot of similar displays. Other sites, like adafruit, got the same displays if you prefer to shop there.

Step 1: Connecting Your Display

Picture of Connecting Your Display

The display is connected by utilizing the i2c pins on your arduino.

Which pins to use for this differs on some arduino models, but on the UNO and NANO you use pin A4 (SDA) and A5 (SCL). If you’re using another arduino, google the pinout and look for SDA and SCL pins. (For example, google “arduino mega pinout”, and check the images).

I first attempted to power my display from my arduinos 5v. This worked, but only halfway – the display fired up, and started cycling the demos in the sketch we will see later on, and then froze after a few seconds.

I then powered my display from my external 5v supply (with common ground to the arduino), which did the trick – the display is now working properly.

The connections from the display:

  • VCC to external 5v
  • GND to external GND
  • SCL to arduino pin A5 (or the SCL pin for your arduino)
  • SDA to arduino pin A4 (or the SDA pin for your arduino)
  • arduino GND pin to external psu GND

Arduino is connected to the computer via an USB cable. The USB powers the arduino.

Step 2: I2c Scanner

Picture of I2c Scanner

To start out, we need to find out the i2c address of the display. To
accomplish this, I use a quick i2c scanner uploaded to the arduino. The scanner code can be found on
Copy and paste the code into your arduino IDE, build and upload, and fire up your serial monitor. If your display are connected, powered and working, you will get an address back from the scanner (in serial monitor). My display shows up at address 0x3C.

Step 3: Libraries

In this instructable I am using the arduino IDE ( and libraries from adafruit downloaded via github.
Link to the libraries:

I will assume you know how to download and install libraries in your arduino IDE. If not, there are tons of nice tutorials/instructions out there on how to get started with the arduino IDE and libraries.

Both libraries below needs to be installed before you are able to continue with this instructable. (SSD1306 library) (GFX library)

Step 4: Test Sketch

Picture of Test Sketch

Now that we know our displays i2c address, we can open the example sketch in our adafruit ssd1306 library.
In your arduino IDE, check your examples menu and locate the 128×64 i2c sketch found under Adafruit SSD1306 (as shown in the picture).
Change the address of the display to whatever the scanner told you, in my case 3x0C.

Compile and upload to your arduino, give it a second, and the display should fire up and show some different display modes.

The demo sketch ends with stars that continues to fall forever. You can copy-paste from the demo sketch to use the display modes that fits your needs.


j3k.2009 (author)2017-01-23

If you're seeing every second line as blank, like I was, you need to edit the library file to uncomment:

`#define SSD1306_128_64`

and comment out

`// #defineSSD1306_128_32`

danieldiasm (author)j3k.20092017-11-09

Now I got it! Thanks!

It was a nice trick

danieldiasm (author)j3k.20092017-11-08

It compiled, but the display got frozen. I believe my display is too simple for that. Anyway, thanks! I've learned something more.

ArifSae (author)j3k.20092017-02-11

sadness not working for me, used correct settings, but still seconds lines blank like interlacing efect

#define SSD1306_128_64
// #define SSD1306_128_32
// #define SSD1306_96_16

Luis A.G1 (author)ArifSae2017-08-09

The same happened to me.

Solution: Check the location where the libraries were installed, you probably have 2 duplicate folders with the libraries. For example:

C: \ Users \ CASA \ Documents \ Arduino \ libraries

C: \ Program Files \ arduino-1.6.9 \ libraries

Delete one of them, just use a destination folder for the libraries and then modify:

#define SSD1306_128_64

// #define SSD1306_128_32

// #define SSD1306_96_16


ArifSae (author)Luis A.G12017-08-10

thanks, checked already, no duplicates, if duplicate library is used it also tells that during compilation in end. Using it as it is for a project and be done with it :)

kschmidt2 (author)2017-10-23

My board for some reason won't compile the 128x64, telling me the height is incorrect, but will compile the 128x32 code, even though, on the box is says it's 128x64. I think I've been ripped off.

danieldiasm (author)kschmidt22017-11-08

Happened to me also...but on Aliexpress those displays are so cheap that I don't even minded. I thought mine wasn't working on the beginning, the address told my the manufacturer is wrong.

kschmidt2 (author)danieldiasm2017-11-09

All well and good but mines from a local retailer and was something like $15 or so. Not really thrilled but it works I guess. I might check the .h file though.

danieldiasm made it! (author)2017-11-08

I got this display a long time ago, back then I could not make it work (using the address told by the manufacturer), I also wasn't good at programming, electronics and my understanding wasn't so refined.

The only difference is my display worked with128x32 (the xcompiler cursed me for trying with the 64 library) and the image looks like interlaced video...

Anyway, thanks! I've almost thrown in the trash another day...

Your tutorial was great! Good advices, clear and concise, well explained.

Thank you!

TheRadMan made it! (author)2017-11-04

Jean0x7BE: I verified your ible. Good writing and nice touch on I2C scan steps. John

General Information

GM009605 China OLED [White] display counterfeits have 4 pins across top, GND and VDD and SCK and SDA. Definitely I2C bus. Shipped configured for 3C address. Your images show board with VCC then GND and this board is Adafruit legit. But mine was $4 CDN and still works (not sure for how long).

At 3.28 Vdc, peak current was 17.6mA (58mW) with all pixels ON.

At 5.05 Vdc, bench test P.S. reads peak 12.3mA (62mW) all pixels ON.

Tip: I found text mono-inversion command [OLED.setTextColor(BLACK,WHITE);].

Caution ; many China supplied pin jumpers are/become/ *open* because pin plugs are bad/cheap/inferior and the wire male-male jumper is *open circuit*.

Advice: Check all male jumpers after use; pull up and out of breadboard carefully. (I make my own DuPont females and Pin male jumpers for rapid develo). Many of these comments could be attributed to open jumpers; check by swapping your jumpers. If cables are *disturbed/open* during operations, then user must hit RESET button once; the OLED does NOT recover; it just goes dark until the board+program is reset. I think Clock and Data are synchronized but disturbed if disconnected while Ardy/Wemos/STM32 are still spitting out the I2C 'stream'.

WEMOS D1 MINI (ESP8266) with IoT : same deal as this Instructible, pins are SCK (clocking) D1 pin, SDA (data) D2 pin, powered by 3.3V. Bright display of 20chars x 4lines with under 20mA of draw for battery operation. \cool/

More advice: ADAFRUIT_SSD_1306.H has to be edit-modded for size 128x64; see comments within files and everywhere on Inet.

Ardy IDE 1.8.4 works OK with both SSD_1306 library .H (header) and .CPP (C-preprocessor) files, as well as GFX library.

Let me know if you find a *command* description for OLED. library commands in a handy PDF reference on the Inet. Please and thanks.

AnderR3 (author)2017-09-09

Sorry if I am wrong and my bad english.. but I have a big question.

Anybody can explain how if the driver SSD1306 has 281 pins aprx, 90 pins are for the commons and the segments (128x64) to the display directly, then a flex of 30 tracks (for data bus, with differential signals in D 0:7, power and staffs like that..)

How the hell can program a librarie to comand all that logic with 2 pins, SCL and SDA?? (which testing with a tester I saw they are connected to two pins of the flex cable.)

I think understand the communication between a MPU and a controller of a display inside when you use all the connections clearly, for example the tipical lcd1602 with arduino at least it uses the D4:7 buses and other pins like W/R etc.. at that way in my unexperience is easier to understand.

Thank you.

ledom (author)AnderR32017-10-17

This is because the SSD1306 incorporates a an I2C receiver which converts the serial communications into instructions that are then used to drive the display. Think of it as an intelligent serial to parallel converter.

FaisalMal (author)2017-09-14


My OLED is a just white color I want to change to different color.

Is it possible?

Thank you and wish you a nice day.

Alex_1998 (author)FaisalMal2017-10-07

I suppose, it is impossible. The colour is unchangeable, it defined by the used OLED type.

FaisalMal (author)Alex_19982017-10-08

Is there different ROLES with the same controller but different color? because as you can see up there it's blue .

Alex_1998 (author)FaisalMal2017-10-08

Yes, you are rigth. The same SSD1306 controller can supplied with blue or white monohrome display panels.

thomas30 (author)FaisalMal2017-10-05

Most of these small OLED displays can only use black and white

ChipStewart made it! (author)2017-06-03

I got the code to load and the display to light, but everything seems to be in a narrow band at the top (photo left). After the 128x64 fix, the band got even narrower (photo right). Any idea why?

tercel89 (author)ChipStewart2017-09-05

You may have SH1106, rather than SSD1306. Watch

dipa57 made it! (author)ChipStewart2017-06-04

Same problem:

PhilWheat (author)dipa572017-08-04

I'm running into the same issue as well - two different boards, so it doesn't appear to be a hardware or wiring problem.

jerry.ericsson2 (author)2017-09-02

Tried the code with the distance sensor, works good as well, I just happend to have some of those laying around in a parts bin. I am not sure what I was going to do with them when I ordered them several years ago, I think some sort of ghost sensor for my niece who is a paranormal nut case and goes hunting ghosts all the time.

jerry.ericsson2 (author)2017-09-02

For those with the yellow top and blue bottom, these are OLED'S there are no real leds on them, the yellow is actually a piece of yellow tape placed on the screen to show the yellow content. They were designed for some cheap MP3 player or something that had a menu up there, of course nobody really want's MP3 players any more so the screens are easier to peddle then the players.

jonahk38 (author)2017-08-24

i had the same problem with the alternating lines showing up. however after seeing @j3k.2009 's point about commenting them all out I started thinking. each of the # define lines had instructions on width and height. so i changed from the middle line uncommented toe the top line uncommented in that section. That is because the top line is 128 64. That matches the resolution of these screens.

demetrioudemetrios (author)2017-07-25


illumation_ (author)2017-02-06

Why you don't need any pull-up resistors?

Samuel Huff (author)illumation_2017-06-03

The Arduino implements internal pullup resistors

JavierP124 (author)2017-05-24

Great tutorial. Thank you very much. Mine works perfectly now!

DominicB30 made it! (author)2016-07-03

Thanks for the lesson, I butchered the provided code and mashed it up with code for reading a AM2302 temp sensor .... now I have something practical...a digital readout of temp and humidity. Make sure you get the right I2c address. way cool.

#include <SPI.h>
#include <Wire.h>
#include "DHT.h"
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
#define DHTPIN 2
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
Adafruit_SSD1306 display(OLED_RESET);

void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

void loop() {

int h = dht.readHumidity();

// Read temperature as Fahrenheit (isFahrenheit = true)
int f = dht.readTemperature(true);

display.print("TEMP "); display.print(f); display.println("F");
display.print("Humid: "); display.print(h); display.println("%");


WesP13 (author)DominicB302017-02-18

I want to use your code to read the temp sensor but i am getting an error when i try to compile. any ideas? i did grab the DHT.h code from here -

DominicB30 (author)WesP132017-02-19

a common compile error (for me anyway) is caused by not selecting the right board in the tools>board>boardmanager menu.

are you getting a specific error?

AxelH11 (author)2016-10-10

Thanks for the guide!

I got the code working (had the height problem in the library). And the nano seems to happily take the code. But there is no sign of life from the display. Should it give some sign of life when powered on or does it need to be correctly wired and programed to even light up?

Im worried that my display is a doa, or should I give it some time and search for errors?

BTW: my display are labeled SCK instead of SCL, other than that compleatly identical to the example. (It is labeled SCL on ebay where I bought it).

ArifSae (author)AxelH112017-02-11

i read somewhere this is issue of buffering, check adafruit forums.

ankit.pitroda (author)2016-04-27

Hello there

It's an awesome tutorial.

I want to know in the basic code of testing the 128x32 i2c display they are using reset pin. But there is no reset pin on my OLED display.

Second, I got the flickering display even after giving the external 5V.

What should I do??


Adwsail (author)ankit.pitroda2017-01-27

Tie both GNDs together on the nano.

prampec (author)ankit.pitroda2016-11-10

The lack of the reset pin seams to be normal.

But this instruction is wrong. You shouldn't let the example code using pin4 as a non-connected reset pin. Instead you should modify the example not using any parameters while constructing the display. (This will lead to a default value -1 to be set as reset pin, and it is handled by the Adafruite driver.)

Also worth to mention that there are SPI-ready versions of this display board, that are also supported by the Adafruite driver. (Buy Adafruite products to support them developing drivers!)

Adwsail (author)2017-01-27

it took me 2 days to get it working but it now works great. FYI, the 2 god connections on the nano are not the same. The one between RST and D2 works great. The one on the other side does not, impedance is too high on my Chinese clone. Tie the 2 together and all is well. That little lesson cost me a lot of time.

dmainmon made it! (author)2017-01-25

Works. Great primer.

AlvinN14 made it! (author)2017-01-22

This is the very first thing I've made with the arduino, the steps were easy, even though I've never tinkered with this before. Thank you.

adrlau (author)2017-01-17

thanks fore help withe the display.

this work great.

i needed this to my stopwatch projekt

sahils100 made it! (author)2016-12-25

Making a marauders map for myself, thanks to you, easily got started with the display.

bigfilsing. (author)2016-12-22

There's a typo in Step 4 >>3x0C should be 0x3C (as per the scan in step 2)

abilly made it! (author)2016-11-28

I took this one step further and added the HC-SR04. I have it outputting the average distance readings to the screen, as well as serial monitor. Thanks for the help!


#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

// Pins

const int TRIG_PIN = 11;

const int ECHO_PIN = 12;

// Anything over 400 cm (23200 us pulse) is "out of range"

const unsigned int MAX_DIST = 23200, MIN_DIST = 150;

float avgDist = 0, dist, cm,inches;

int pingCount,avgCount;

unsigned long pulse_width;

void setup() {


// The Trigger pin will tell the sensor to range find


digitalWrite(TRIG_PIN, LOW);

// We'll use the serial monitor to view the sensor output


// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)

// init done

// Show image buffer on the display hardware.

// Since the buffer is intialized with an Adafruit splashscreen

// internally, this will display the splashscreen.



// Clear the buffer.


// draw a single pixel

display.drawPixel(10, 10, WHITE);

// Show the display buffer on the hardware.

// NOTE: You _must_ call display after making any drawing commands

// to make them visible on the display hardware!





void loop() {

unsigned long t1;

unsigned long t2;

// Hold the trigger pin high for at least 10 us

digitalWrite(TRIG_PIN, HIGH);


digitalWrite(TRIG_PIN, LOW);

// Wait for pulse on echo pin

// while ( digitalRead(ECHO_PIN) == 0 );

pulse_width = pulseIn(ECHO_PIN,HIGH);

// Calculate distance in centimeters and inches. The constants

// are found in the datasheet.

cm = (pulse_width*0.034)/2;// / 58.0;

inches = (pulse_width*0.0133)/2; // 148.0;


//set average distance and reset it every x pings



pingCount= 1;


else {

dist= dist+inches++;

avgDist = dist/pingCount;





if (avgDist < 10){

// playTone(); //previously had it play tones over a piezo based on distance from the sensor


else {

// noTone(piezo);


// Wait at least 60ms before next measurement



void printReadings()


// Print out results

if ( pulse_width > MAX_DIST ) {

Serial.println("Out of range");




display.println("Out of range");



else if (pulse_width <MIN_DIST) {


Serial.println("Object to close!!") ;




display.println("Object to close!!");



else {


Serial.print(" pc \t");


Serial.print(" avgInch \t");


Serial.print(" cm \t");


Serial.println(" in");





display.print(" pc \t");


display.print(" avgInch \t");


display.print(" cm \t");


display.println(" in");








johnnyfrx made it! (author)2016-11-20

Very Cool. Thank you for sharing!

julianwiggins (author)2016-10-24

Good work! Nice to get an ebay impulse purchase going so easily. Many thanks!

SriharshaB1 (author)2016-10-21

Very clear instructions and could make it in less than 5 minutes. Thanks a lot

sddennis (author)2016-10-20

Just did it. Thanks for the information. You are spot on about the address 0x3C.

One more thing: there is a glitch in the 128x64 i2c example, before the Setup section, there is a static char bitmap. You must add const on the line just before static in order for it to compile. The error message is pretty clear but it bears mentioning.

Keep up the good work!

I really want to see more ways to use this display. There seems to me no real manual..

WilIiam made it! (author)2016-10-07

It works!

JaneE3 (author)WilIiam2016-10-18

Great, you can find different color and sizes in this amazon store

About This Instructable



Bio: Computer geek who stumbled upon arduino and electronics in general a while ago.
More by Jean0x7BE:AC light 433 mhz radio controlled timer with arduinoOLED i2c display with arduino
Add instructable to: