Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and other free resources.
Don't worry -- youre-mail address is totally secure. I promise to use it only to send you MicroZine.

How to Drive the SSD1306 OLED LCD display

This section is all about using an SSD1306 OLED (Organic LED) display that's 128 pixels wide by 64 pixels high, but this is a very tiny display (0.96""), so you may need a magnifier to see what's going on (you can get the slightly larger version at 1.3". Even though they are small you can use larger font sizes and graphics to display useful information on them, and they are low cost.

ssd1306 spi mode arduino interface

In the examples below you can test out the different libraries "Adafruit SSD1306" and U2G8. While the Adafruit is specific to a few versions of the hardware the U2G8 library (Universal graphics 8 bit library) can be used with many, many different display modules. In a way this is good since you can use the same drawing functions but you also have more constructor options to look at, and selecting the right one may not be so easy.

I found on my first attempt that the U2G8 library would not operate the display using what I thought were the correct initialisation settings so I gave up with that and tried the Adafruit library which worked 1st time (There was a slight problem with line skipping - see the solution below - that was not reliably addressed on the web).

In fact the Adafruit library sits on top of a graphics library (Adafruit GFX)so you are really using the same drawing functions and only changing the top code for the hardware.

back view of ssd1306

The u8g2 library does work but there are different ways of using the display so you not only have to use the correct constructor for the display you have, but you also have to use the correct number of pins in that constructor (you may or may not have a reset line!).

A further complication is that there are several different screen buffer modes (these are also selected by the constructor) - and for these screen buffer modes different functions are required to operate the display and these functions do not mix. The examples bellow uses the correct constructor and buffer drive code. It sounds complicated but once understood, you can optimise the display and buffering for your system

An option within the U2G8 library is for direct output of screen data which means zero buffering - See the sections on u8x8 library. This means you get all your RAM back with text output but no graphics - but this can be a useful option for severely constrained designs.

Rear view detail of OLED

ssd1306 back view

SSD1306 Pinout Connections

The SSD1306 is capable of working in either 4 wire SPI mode, 3wire SPI mode or I2C mode. This breakout board lets you change the function by moving resistors around (desolder and re-solder). It is set up for you as 4 wire SPI operation (this is the fastest operational mode). The examples below use 4 wire SPI..

ssd1306 front view compared to thumb size

Pin Name Signal description SPI Name I2C Name Arduino Uno pin
GND Ground (0V) Ground (0V) Ground (0V) GND
Vcc Power Supply Power Supply Power Supply 5V
D0 Clock into display SCK SCL 13
D1 Data into display MOSI SDA 11
RES Reset 10
DC Data/Command 9
CS Chip Select CS 8
Note: pin 12 is missed out as pin 13 (SCK) and 11 (MOSI) [for reference (not used here pin 12 is MISO)] are the only pins that attach to the internal hardware SPI module. For the first few examples in this page the internal hardware is not used, so the interface is using bit-banged software driven operation i.e. any pins could be used. See later for speed improvements when using the hardware SPI interface.

The Arduino Uno pins used above are are for SPI mode where the internal hardware SPI module is used - if the hardware SPI mode is used then these pins (13, 11) must be used. In the examples below comparison is made between software and hardware SPI modes to show speed differences. Software mode could be useful in situations where pins 11 and 13 are already in use.

Software Library and versions

Arduino IDE Version

Version : 1.6.4

Library versions

Adafruit SSD1306 : 1.1.2

Adafruit GFX : 1.2.2 (The Adafruit OLED library uses this library for core graphics operations).

u8g : 1.19.1 (used for speed comparison tests)

u8g2 (replaces u8g as an improved solution) : 2.15.2

Library Installation

To install a Library search for the library name:

If you do not see the library as an entry when you click the menus:

Sketch-->Include Library

Then select manage libraries :

Sketch-->Include Library -->Manage Libraries...

Search for and install "<library name>" using the "Filter Your Search" form.

Adafruit SSD1306 Library Examples

Adafruit library Setting the screen size

For the Adafruit Library you have to set the size of the display in one file (if it does not already match what you are using e.g. 128x64).

Warning: If you see half the lines skipped on the display (and do not see the microseconds displayed at the bottom) then the library thinks you are using a 32 bit high display when you are in fact using a 64 bit high display. All you do is follow the instructions below to set the correct display size in the Adafruit library code.

To find the installed adafruit code you will need to go to your documents folder and find the link similar to that below:


Edit the file: Adafruit_SSD1306.h

Scroll down to the following section that has the label "SSD1306 Displays":

Notice how the default #define is defined for a 128x32 display - this is what causes line skipping when you use a 128x64 display and the #define is set to 128x32; Just comment out this line and uncomment the line containing: SSD1306_128_64.

    SSD1306 Displays
    The driver is used in multiple displays (128x64, 128x32, etc.).
    Select the appropriate display below to create an appropriately
    sized framebuffer, etc.

    SSD1306_128_64  128x64 pixel display

    SSD1306_128_32  128x32 pixel display


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

Adafruit GFX Reference

U8G2 Library usage

The u8g2 library replaces the original u8g (universal 8bit graphics) library. It is a re-write and the main feature you will find, if you look at the source code, is that the initialisation routines are using the u8x8 library functions. This makes sense since the intialisation routines have to be the same whether you are later on going to buffer the data or not.

The u8x8 library is a stripped down library that includes no display buffering which means it uses less memory resources and means that a microcontroller without much RAM can use the display - for text display. This is likely why the old u8g library was dropped in favour of the u8g2 library (so that this functionality could be split out and used independently).

The u8g2 library adds buffering on top of the u8x8 library to provide the same functionality as the u8g library.

How to make the SSD1306 u8g2 Library work

One "gotcha" with the u8g2 library is that it uses many constructors of the form:

U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /*
data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);

U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /*
data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);

Note: The parameter U8G2_R0 specifies display rotation in 90 degrees R0 is zero R1 is 90 etc. See the u8g2 reference for details on constructor use [See the link to that reference in a section below].

TIP: Lots of constructor codes are already available in the examples provided with the library. To access those examples use the following IDE menu instructions:

The above examples are taken from the example code that you can find in the arduino IED:

Sketches --> Examples -->u8g2 --> "full buffer" and "page buffer".

Then uncomment the relevant constructor in the example code that you use. Note that not all constructors are in those examples so check the constructor reference link (below) if you don't find your device.

The two top constructors are nearly identical except for the digit 1 (single buffer) and the letter F (full buffer).

For Single buffer use the following function scheme must be used:

  do {
    /* all graphics commands have to appear within the loop body. */    
    u8g2.drawStr(0,20,"Hello World!");
  } while ( u8g2.nextPage() );

For Full buffer use the following function scheme must be used:

void loop(void) {
  // ... write something to the buffer 

u8g2 Reference

Examples above are from the function reference page

u8g2 Constructor Reference

More information is in the u8g2 constructor reference:

u8g2 Fonts

One are that u2g8 does very well is to draw good looking fonts. These can be a bit hard to find so here is the link to a font chooser and definitions:

u8x8 Reference

Using the u8x8 Library

This section is all about the alternative Universal LCD driver u8x8. The u8x8 is all about low memory footprint and higher speed. To make the code operate faster sacrifices have to be made. In this case all graphics capabilities are thrown out and all fonts are fitted into an 8x8 area of memory.

This library comes with the u8g2 library and is intended to do a bare minimum of text output in order to save a lot of memory and operate a bit faster than the u8g2 library. You should use this library if you must save memory and only require text output.

Warning: The u8x8 and u8g2 do not do line wrap - they just start again on the same line - manually insert \n into a string to goto to the next line or write a small algorithm similar to:

char *msg="Now is the time for all good men to come to the aid the party."

"The quick brown fox jumps over a lazy dog ";

char *msg="Now is the time for all good men to come to the aid the party."
                   "The quick brown fox jumps over a lazy dog ";

  // Code snippet : wrap a string to display
  byte i,y;
  // u8x8 does not wrap lines.
  y = 0;
  for (i=0;i<strlen(msg);i++) {
    if ((i % 16)==0 && i!=0) y++; 
     u8x8.setCursor(i % 16,y);      

u8x8 Simplification

By treating the output screen in a simple way i.e. blocks of 8x8 bits 8 bits can be transferred at a time without any processing so it means you don't need to know what was there before. For graphics operations you have to retrieve the contents of the screen before updating it. This is because the screen driver uses bytes to represent 8 pixels on the screen

Consider changing a single pixel because you want to draw a line from top to bottom, in each byte as you go down the left side of the screen from top to bottom. To change the left most bit as you go down, if you only write that bit to the screen it erases what was in the other bits. So instead you have to read the screen byte and OR in the left most pixel and then write it back to the display.

The u8x8 mode treats each screen position as a block of 8x8 so it always fills that block and so never needs to read back the screen data. That means no buffer is required but at the same time no graphics can be used.

Screen Buffering

The SSD1306 does not have a facility to read back the value for SPI and I2C modes - it does allow it for 8080 mode but check the datasheet. For SPI and I2C modes a copy of the screen state (for graphics) must be stored in the Arduino memory. The screen size 128x64 in bytes is 16*64 = 1024 Bytes. This is half the available RAM in the Arduino UNO. In high speed operation a double buffer can be used so you may need 2k!

So you can see a higher spec chip is required even for modest screen modes (you can just about get away with the uno for this display using single buffer mode) but with the library in use you are only left with about 500 RAM bytes (from the library code and the buffer together using about 1500 Bytes). This is for graphics mode. If you ditch graphics then you can use u8x8 and save RAM and flash memory.

Think about using a display with 256 colours per pixel! (hopefully that display can be read back to save having to have a buffer because it would be big).

Download Software Examples

There are four example sketches in the zip file:

  1. ssd1306_yt_text_adafruit
  2. ssd1306_ty_test_u8glib
  3. ssd1306_test_u8x8
  4. ssd1306_jfm_u8g2

To download the sketches click this link.

Speed Tests Non Hardware SPI/Hardware SPI

A video online gives some examples of speed testing the display (see below for video link).

I used some of the same code but for the Adafruit library got a faster result: someone has been improving the library speed! It was the slower one in that video.

Test SSD1306
OLED 128x64
U8Glib u8g2 u8x8
[no graphics]
Software SPI
Minimal text, us display.
29.9ms [36ms] 32ms 42ms 7.6ms [no graphics]
Software SPI
Memory use for above: Flash,SRAM
10,976 (38%),
1,340, (65%)
7578 (23%),
276 (13%)
8,134 (25%),
583 (28%)
5,589 (17%),
383 (18%)
Software SPI
Full text *, us display.
53ms [77ms] 87ms 159ms 42ms [no graphics]
Hardware SPI module.
Minimal text, us display.
8ms 21.4 35ms 5.2ms [no graphics]
Hardware SPI module.
Full text *, us display.
(41% faster cf sw)
(11% faster cf sw)
(6% faster cf sw)
29.3ms [no graphics]
(30% faster cf sw)

* - See code for text starting, and ending: "Now is the time ...lazy dog".

[] Times detailed in video [ ].

Note: u8g2 uses single buffer mode for these experiments.

Note: The single buffering mode for u8g2 alters the buffer size so less RAM is used - when lots of the screen is updated more SRAM is used (for the full text output SRAM used is: 691 (figure is not shown in table above) - still much less than I expected).

Notice how much faster the u8x8 operation is 5.2ms (but you can't do graphics).

Notice also how adfruit library is the fastest when using the SPI hardware module but more resource is used up.

UG82 Full buffer comparison : compared to the Adafruit library.
Test SSD1306
OLED 128x64
Software SPI
Minimal text, us display.
29.9ms [36ms] 23.5ms
Software SPI
Memory use for above: Flash,SRAM
10,976 (38%),
1,340, (65%)
8,108 (25%)
1,479 (72%)
Software SPI
Full text *, us display.
53ms [77ms] 71ms
Hardware SPI module.
Minimal text, us display.
8ms 16.9ms
Hardware SPI module.
Full text *, us display.
(41% faster cf sw)

Hardware SPI is 50% faster for the Adafruit library, compared to the u8g2 library in full buffer mode. In this mode both are using comparable resources of Flash memory and SRAM.

Speed and Resource Test Conclusions

The SPI hardware module is used much better in the Adafruit library so execution speed is faster in all cases comparing hardware SPI modes. Even when using software SPI, execution is faster for the adafruit library.Comparing full buffer mode: Using hardware SPI, operation is 50% faster for the Adafruit library compared with the u8g2 library.

The u8g2 library has comparable speed and memory usage (for softwre SPI mode) when in full buffer mode compared to the Adafruit library i.e. the adafruit library is using full buffer mode.

The u8g2 provides several buffer options that trade speed and memory size allowing useful operation even when only using 600 SRAM Bytes for the screen. This is useful for memory constrained systems (Arduino Uno R3) when you don't need high speed screen updates and need to be able to use more SRAM.

Finishing up

I hope you found this guide useful.

How are you going to use this type of OLED display in your projects?

Please let me know by taking a few moments to leave a facebook comment below.

New! Comments

Have your say about what you just read! Leave me a comment in the box below.

Privacy Policy | Contact | About Me

Site Map | Terms of Use

Visit our Facebook Page:

   Click Here

Recent Articles

  1. How to use the BMP280 Barometric Pressure chip with the Arduino

    How to use the BMP280 for weather pressure measurement or altitude change detection.

    Read more

  2. The TCS230 Color Sensing Chip: How it works and how to use it.

    How to use the TCS230 (/TCS3200) Color detector chip and easily add it to any of your projects.

    Read more

  3. All about the MC78M05BDTRKG Linear Voltage Regulator

    How to use MC78M05BDTRKG for maximum current without using too large a heatsink pad and how to select the optimum input voltage.

    Read more

  4. Fixed point: A fast and easy way to save tons of microcntroller flash memory

    How to use fixed point maths to save microcontroller memory by avoiding use of the floating point library.

    Read more

  5. How to use the DHT22 (or DHT11) with an Arduino; Full code, description and device differences.

    Essential Guide to the DHT22/11 humidity sensor with library code guide and Full Arduino Tutorial. Learn how to Easily determine Humidity, Dew point and Heat Index.

    Read more

  6. The Essential I2C Tutorial: All you need to know about I2C...

    I2C tutorial: Learn all about the 2 wire I2C serial protocol. Learn how easy it is to use, how it works and when to use it...

    Read more

Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's


- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan


"Awesome site,
very, very easy and nice
to navigate!"

- Matt

Learn Microcontrollers

"Interested in

Sign up for The
Free 7 day guide:


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."

- Dave


"Your site is a great
and perfect work.

- Suresh


"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.

- Anon

Back to Top