A fast SH1106 library (128x64 OLED)

Hi guys,

I’ve just received a 128x64 1.3" OLED display from eBay. What I needed was a simple but fast Arduino library to run it.
After scouring the internet looking for a datasheet for this thing, I modified my PCD8544 library to work with these displays.
It should work with SSD1306 with a little modification to the code. A friend has confirmed that the library works on his SSD1306 based OLED, but it’s not perfect.

  • Please read the topic above for more details on how the library works as they are very similar, make sure you read the information in SH1106_SPI.h file as well.

  • This library defaults to 4MHz SPI (16MHz / 4), but the display I have worked great at 8MHz, so yours may work as well.

  • At 8MHz SPI the speed of this library is very comparable to that of the PCD8544 even though it has more than double the pixel count.

  • begin() function allows you to change several display settings:

// invert - True for inverted display and False for normal.
// fastSpi - True enables a /2 SPI divider, False leaves the divider at the default /4.
// contrast - Sets the contrast of the display, valid values are in the range of 0 - 255 (0x80 = 128).
// Vpp - Sets the charge pump voltage for the display, 0 = 6.4V, 1 = 7.4V, 2 = 8.0V (controller default), 3 = 9.0V
void begin(bool invert = false, bool fastSpi = false, uint8_t contrast = 128, uint8_t Vpp = 0);

Here is a little demo of this display running at 4MHz SPI:

(The times displayed are in microseconds)

So far I’ve tested both versions (with frame buffer and without) and they both seem to be working quite well.
I’d like to hear some feedback from you about it.

SH1106_SPI.zip (9.72 KB)

Good to see the 8544 lib reused !

Hi TheCoolest

I happen to have a few 128x64 OLED displays with 4 pins that claim to support SPI. The data pins are labeled SDA and SCL. Could you please guide me on how to use these displays with your library?

Many thanks

4-pin displays with SDA and SCL have an I2C interface. They won't work with my library without modifying it to use I2C instead of SPI for communicating with the display. I2C is relatively slow, 100KHz by default, compared to 4MHz with SPI, and it also has a higher overhead. I'm not sure it's worth picking my library over other available ones, since it will not be considerably faster.


you can check if the screen response to higher speed using the multi-speed I2C scanner See - http://forum.arduino.cc/index.php?topic=197360.0 -

@TheCoolest A 6-pin unit will be arriving today, thank you. 8)

@robtillaart Thank you for the link.

Could you please ask your friend if he could post the changed library to work with the SSD 1306. Cause my sketch is running out of RAM space I´m looking for a simple library that works with no screen buffer.

I have an SSD1306 text-only library that is pretty compact. In it's minimum configuration a simple "hello world" sketch is about 2.5K in code space and uses about 50 bytes of RAM. It takes about 500 microseconds to write 20 characters to the screen in hardware SPI mode. I modified it from a previous library (SSD1306ASCII) for my own purposes but it seems many other people have this same need for a small, less RAM hungry library. So I am happy to share the latest version if you are interested.


please could you post or pm me a link to the code that doesnt use the ram buffering

Hi TheCoolest,

i just started using your lib, because running out of ram on 328 with a modificated adafruit SD1306 lib. Without the framebuffer its very promising (only 10% RAM usage) but two critical function are missing: setPixel and drawLine is there a way to incorporate these in the non-buffered part?

Also is inverted print possible (for making a simple cursor)?


Has anyone got this library working with a MEGA2560 ?

I have this chinese 1.3’ OLED and got it working (with the SH1106demo from the library) on a UNO but when I connect it to a mega2560 and connect MOSI(D1) to pin 51 and SCK(D0) to pin 52 and the other 3 pins to 8,9,10 (also tried SS(CS) to pin 53 instead of pin 10). But it will not function as on the UNO. Most of the time it is completely dark or there is only one bright horizontal line or there is mostly garbage with a few recognizable characters.
I have the mega2560 and this oled working happy with the U8glib library using this string:

U8GLIB_SH1106_128X64_2X u8g(52, 51, 53, 9, 8 ); // on Oled : D0, D1, CS, DC, RST
or U8GLIB_SH1106_128X64_2X u8g(5, 6, 7, 8 ); // on Oled : D0, D1, CS, DC

whatever set of pins I choose is OK because U8glib uses Software SPI but I need the HW SPI of this SH1106-library for more speed.
I have read the thread about PCD8544/Nokia5110 but did not find any clue for tuning the library for the mega2560.

On the backside of the display, S1&S2 are set to ‘0’ so the oled is wired for 4-SPI

This library use PORTB for access CS,DC and RST signals, assuming D8,D9 and D10 pins. Unfortunately, on Mega 2560 this port is used for SPI interface, and is linked on pins 53(PB0)=SS, 52(PB1)=SCK, 50(PB3)=MISO, 10(PB4), 11(PB5), ...

Here is my solution: Change portB to portC in library;

file: SH1106_SPI.h

// This is the port where the LCD is connected.

define SH1106_PORT PORTC

define SH1106_DDR DDRC // Should be DDRx, x = port name (B, C, D, etc.)

now connect: DC - 37 RST - 36 CS - 35 MOSI - 51 CLK - 52 VCC - 3,3V GND - GND

Good luck :-)

With 0,96 and 1,3 helltec oled (certainly with SSD1306) , this lib is perfect . Just replace in sh1106_spi.h

in void SH1106_SPI::begin() replace 2 lines ...

//this->writeLcd(SH1106_COMMAND, 0xAD); /set charge pump enable/ //this->writeLcd(SH1106_COMMAND, 0x8B); /*external VCC */

this->writeLcd(SH1106_COMMAND, 0x8D); /set charge pump enable/ this->writeLcd(SH1106_COMMAND, 0x14); /*external VCC */

Hi the Coolest, I like your library for SH1106, thank you very much, it works like a charm. Do you have any idea how I could get Umlauts (äöü etc.) to be print?
Thank you very much, Dani

This is really cool. Does this library allow for deferent size fonts? And if not can it be made to do so?

is it possible to change the size in the .h code

from(copy pasted from the code in the .h file):

//This table contains the hex values that represent pixels //for a font that is 5 pixels wide and 8 pixels high static const PROGMEM uint8_t ASCII[][5] = {

to (the size 10,16)

//This table contains the hex values that represent pixels //for a font that is 10 pixels wide and 16 pixels high static const PROGMEM uint8_t ASCII[][5] = {

And how can i have both sizes in the libary?

I have a current project tat I would like to switch from the adafruit lib to this one ( I don't need or want the frame buffer etc). But I cant quite get it to work.

I'm using an Pro Micro and the oled is wired as follows -

VCC - VCC GND - GND CLK - 15 MOSI - 16 CS - 8 D/C - 9

Can anyone clue me in? Thanks.

Hello. I am trying this example from posted library, but it can not even compile for Uno, says Global Variables uses too much memory, over the limit. What am I missing here, why it is so? Thank You!