Arduino OLED Display Library

There are many different sizes of OLED displays that are compatible with the Arduino. I bought some cheap mini I2C OLED from ebay, works pretty well but the library the seller provides was very difficult to understand, so I decided to write my own library OLED driver.

Understanding How the OLED Display Works

Before we go onto explain how we use the library, I think it’s important that we understand how the OLED display works.

How the OLED Display is Communicated with Arduino

The OLED display is connected to the Arduino using i2c buses, so the “wire” library is used here. As you might know i2c communication allows multiple devices to share the same connection, and each device will have a specific address in hex number between 0x00 and 0xFF. You need to specify the device address in order to talk to the device you want.

Within the OLED display, there are many register, each register controls a certain functionality, such as inverting the display colour, or powering down the display. Again each register will have a unique hex address between 0x00 and 0xFF.

So to tell the display to do something, you basically need 3 parameters: device address, register address and the command. The code example would be:

Wire.beginTransmission(devAddr);
Wire.write(regAddr); 
Wire.write(data);
Wire.endTransmission(); // stop transmitting

For example, to shut down the display of address 0x3C, we change the data in register 0x40 (command register), with value 0xAE, which is the shutdown command.

Wire.beginTransmission(0x3C); // might be different for your display
Wire.write(0x80);
Wire.write(0xAE);
Wire.endTransmission(); // stop transmitting

There are mainly only two registers we need to know here, the command register (mentioned above), and data register, which we use to control the pixels on the screen. For more details on the registers and commands, check out the datasheet.

How to Control Each Pixel on Screen

The matrix arrangement on the display is quite confusing. The screen is divided  into “8 pages” (I know it’s not divided into rows, but pages), and 128 columns. Each page-column unit contains 8 pixels. We control the 8 pixels unit with one hex number (which can be seen as 8-bit-binary number, and each bit controls a pixel).

page-column-arduino-096-i2c-oled-display

oled-matrix-arrangement

For example, display a dot on the top left corner, we need to send a hex number 0x01 (B0000 0001) to the data register, e.g.

Wire.beginTransmission(0x3C); // might be different for your display
Wire.write(0x40);
Wire.write(0x01);
Wire.endTransmission(); // stop transmitting

example-oled-display

To get to the next column, we just need to send the next data, the pointer will automatically increment. Depends on which Addressing Mode we are using, by the time we get to the end of the page columns (col127), we will either move down to the next page automatically (Horizontal Addressing), or the pointer will be reset back to the first column of the same page (Page Addressing). There is also a third addressing mode – the vertical addressing mode. But I don’t think it’s useful so I won’t discuss it here.

So that’s pretty much you need to know to get started coding the OLED Display for Arduino.

Circuit Connection

The OLED I bought is a mono colour, I2C 0.96′ 128×64 OLED display which is about $14. I like I2C because it’s very simple (only 2 data connections), and it leaves other pins available for other devices.

arduino-oled-display-connection

How to use the Library

First Declare Library <OzOLED.h>, an object OzOled will be created automatically. Then initialize the object with “init()” function. You can then use “printString()” function to print text on the screen. Here is a quick example.

#include <Wire.h>
#include <OzOLED.h>

void setup(){

  OzOled.init();  //initialze SEEED OLED display
  OzOled.printString("Hello World!"); //Print the String

}

void loop(){

}

There are many more functions you can use, check out the library for more.

OLED Display Library Download

I might not have time to work on this library and keep it up to date, so free feel to customize as you need to.

https://code.google.com/p/ozoled-oled-display-096-i2c-driver-library/source/browse/OzOLED.zip

78 thoughts on “Arduino OLED Display Library

  1. Igor

    Neat little library! Well done!
    But, I’ve noticed that some decimal numbers are printed wrong when using printNumber(). First of all the numbers are truncated and not rounded but the real problem is with numbers beginning with zero after decimal point, for example:

    OzOled.printNumber( (float) -0.00199, 3, 0, 0) prints -0.1 !

    Reply
  2. nopphong

    This is good library with some problem.For me i have problem when restart arduino and then the lcd will never work again.
    i like this easy to understand and easy to use very much so i try to make it really work.

    The problem is from Ozoled,init have some problem in it.I think it from it missing some init command that i don’t know what is it. So i take easy way.Erase all this library init and replace with init from other lcd program.

    I take init sequence from this http://robotcantalk.blogspot.in/2015/03/interfacing-arduino-with-ssd1306-driven.html
    and edit OzOled.h and OzOled.cpp .I put all the define part in OzOled.h and init part in OzOled.cpp and add Ozoled.clearScreen();
    It work like a charm.

    Reply
  3. kim chan

    Hi Oscar
    #include
    #include

    void setup(){
    Serial.begin(9600);

    }

    void loop(){
    int a = analogRead(A0);
    Serial.print(a);
    OzOled.init(); //initialze SEEED OLED display

    OzOled.printString( 0, 15, a); //Print the String.

    }
    Uploads a code or three $ 5 * oled that output. Help me!.

    Reply
  4. marten

    Hi Oscar

    Hello, could you please put in a larger font ? the size is so small that i need reading glasses :(

    I have tried a oled font generator, but the format seems wrong ..

    Very nice work btw.

    Reply
  5. Carl Pedersen

    Hi Oscar
    Great library, thanks for sharing.
    I like it is non-buffered and just update the characters in question.
    For your information, I made a few changes in my copy .
    Easy to modify to use text on SH1100 controlled oleds.
    I added a few functions in order to flip the display vertically as well as adding (a usable) font for the range 128 to 255, iso8855-1 like, and only made changes in printChar() to accomodate for unsigned char output. It adds about 1K to the code size.

    Carl

    Reply
    1. Olav Gullaksen

      Hi Oscar
      Thanks a lot for this tiny and easily used library. After implementing the two additional lines as mentioned by frederic4950 it works well. But I cannot figure out how to output a variable ??

      To Carl Pedersen,
      I have problems with writing a variable using the printChar function.
      Can you maybe release your code for using unsigned char output ?

      Br, Olav

      Reply
      1. Carl Pedersen

        Hi Olav Gullaksen,
        Sorry for the later reply, but here are the changes.
        Note that I use a #define LATIN1 to allow characters greater than 127.

        /***
        * printChar takes signed char as input, but converts to unsigned
        * before output in order to print chars > 127
        */
        void OzOLED::printChar(char C, byte X, byte Y){

        if ( X < 128 )
        setCursorXY(X, Y);

        byte c = C;
        //Ignore unused ASCII characters. Modified the range to support multilingual characters.
        #ifdef LATIN1
        c = (C < 0)?(C + 256):C;
        if(c 127 && c < 161) )
        #else
        if(c 127)
        #endif
        c=’*’; //star – indicate characters that can’t be displayed

        for(byte i=0; i<8; i++) {

        //read bytes from code memory
        sendData(pgm_read_byte(&BasicFont[c-32][i])); //font array starts at 0, ASCII starts at 32. Hence the translation

        }
        }

  6. Bob

    Hi Oscar
    Great library – I can seen how to print text in quotes, but is there any way to print a String variable? Can’t see any examples.

    Reply
  7. Andreas Spiess

    Excellent work! I ported it to Attiny platform (using TinyWireM library) and included the charge pump code.

    I called it TinyOzOLED: github.com/SensorsIot/TinyOzOled

    The project is shown on Youtube: youtu.be/mKPKQm0uPBQ

    Reply
  8. Devis

    Hi hello,
    thanks for great work about OLED.
    I`ve some question:
    1. how should I do, if I want the display is big alphabet or number?
    2. I have RTC, but I don`t know how to display in OLED, her is the RTC example:
    ———————————————————————————————————————————————————–
    #include
    #include

    RTC rtc(DST_ON);

    void setup()
    {
    Serial.begin(9600);
    while(!Serial);
    delay(1000);
    }

    void loop()
    {
    Data d = rtc.getData();

    // GET DATE:
    Serial.print(d.year); Serial.print(“/”);
    Serial.print(d.month); Serial.print(“/”);
    Serial.print(d.day); Serial.print(” “);

    // GET TIME:
    Serial.print(d.hour24h); Serial.print(“:”);
    Serial.print(d.minutes); Serial.print(“:”);
    Serial.println(d.seconds);

    delay(1000);
    }

    Reply
  9. Tom

    Hi Oscar – Thanks for sharing the code! I was able to get this working on an attiny841 with some modifications. Nice work!!!

    Reply
  10. frederic4950

    Hello,

    Be careful to those who use the heltec.cn OLED module, SDA and SCL pins are reversed from the above connection diagram.
    Thanks to Colin, I have added the two following line after OzOled.init() call in the “Hello World” example to have a correct display :
    OzOled.sendCommand(0x8d);
    OzOled.sendCommand(0x14);
    (Perhaps it is better to put them in OzOLED.cpp as Colin said).

    Thank you Oscar Liang

    Best regards

    Reply
  11. irun4fundotca

    should this also work on a Teensy 3.1 I have tried a few times using every set of i2c pins and dont seem to have anything displayed using the hello world example

    Reply
  12. Bernd Blumberg

    I bought this display on ebay but it doesn´t work.

    ebay.de/itm/171803863493?_trksid=p2060353.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

    Does anyone know what to change in the library ?

    Bernd

    Reply
  13. Stuart

    I was getting compilation errors with the example scripts that use your logo:

    static unsigned char OscarLogo[]

    Here is the compilation error
    =============================================================
    Arduino: 1.6.1 (Mac OS X), Board: “Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)”

    Build options changed, rebuilding all
    In file included from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/WString.h:29:0,
    from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:26,
    from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Stream.h:26,
    from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/libraries/Wire/Wire.h:26,
    from OLED_Scroll_Right.ino:1:
    OLED_Scroll_Right.ino:4:34: error: variable ‘OscarLogo’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
    Error compiling.

    This report would have more information with
    “Show verbose output during compilation”
    enabled in File > Preferences.
    ==========================================================

    I changed static to const and the sketches now compile and run.

    Reply
  14. bula87

    I tried to use your lib but I find out that sometimes, if OLED has been shut down during some operation, next initialization was unsuccessful. In other hand when I flashed SW with Adafruit lib -> OLED was restarted and next time your lib worked fine. So now I am using init procedure from Adafruit lib with rest of your solution and now everything works fine. So, please check your init function to fix this issue. Thanks for your work because your lib is the smallest one I was able to find.

    Reply
    1. sergio

      Hi bula87.
      please, I’m having the same problem.
      Can you send your skeet to help me?
      thank you very much

      Reply
    2. Willy

      Hi bula87, I have the same problem, could you please send me the fixed lib please?
      I love Oz’s Library, but whenever the Arudino shuts down, I have to load Adafruit code before loading Oz code to display something.

      Reply
  15. Andre Saggin

    Hi,
    I’m having problems using the Oled Display… I’m not sure about the problem.
    The code is compiling and uploading, but the display do not show anything.

    I’m beginning in electronics so can you help me?
    Why do we connect the display to analog inputs? Can I change those pin?

    Down there people say about this commands…
    sendCommand(0x8d);
    sendCommand(0x14);
    What do they mean?

    pin connection
    Gnd->Gnd
    5V->Vcc
    4A->SDA
    5A->SCL

    Thanks in advance.

    Reply
    1. Oscar Post author

      This is I2C connection, A4 and A5 in this case are not analog pins, they are i2C pins. You cannot change these pins.
      Not sure about 0x8d or 0x14, google it.

      Reply
    2. Andre Matos

      Hello I have same problem, after compile and start lcd using U8glib, if I compile an use OzOLed it works, but if I reboot board, display don’t show anything , any idea about this problem ? thanks

      Reply
  16. Lee

    Hi

    Great library, I need one with a smaller footprint that the others.

    I have one question.. Due to the way my OLED is fitted I need to rotate the output by 180*

    How do I do this?

    Thanks in advance

    Reply
  17. DANS

    Clemzo,

    Mail me buddy, I am more than happy to give you a copy of the modified Lib.

    I am still tweaking it adding more, I want to tweak the text print routine so uses standard print format to enable storage in progmem and not ram.

    :)

    [email protected]

    Happy coding :)

    Reply
  18. DANS

    Hi Oz,

    I must say firstly awesome job on the library. One problem I have encountered is it does not init sdd1306 chipset correctly. I have hacked the Adafruit lib and added init code to your library now works a treat.

    Question: with print big number font, what tool can I use to generate an additional full stop and percentage sign to add to this font for displaying voltage with a decimal point and humidity sign ?

    Fantastic Job, your library I have chosen because of small memory footprint. A+

    Dan

    Reply
    1. Oscar Post author

      Thank Dans!
      There are lots of free tools on the internet, just google “oled font generator”. I bought the oled from a chinese seller on ebay, and they supplied a simple software, can’t find it anymore, it’s been a long time!

      Reply
    2. Clemzo

      Hi, thank’s for the great Tuto.
      Dans, is it possible you give me your modifications because I try to use an Oled 128×64 i2C with ssd1106 on Raspberry Pi and I have great difficults.

      Thank you very much.

      Reply
  19. Oleg

    just received my package. find your library very helpful! (Adafruit’s not fits my memory) and have some brightness problem on both pieces.. at maximum .setBrightness(254) it lit very very dim… any ideas where might be the problem? using 10K pull-up resistor. [email protected]: https://www.dropbox.com/s/dnvfxrixaizd7xp/Photo%2023-01-15%2018%2033%2031.jpg?dl=0

    Reply
    1. Oleg

      i found. the problem was in “charge pump” setting. my screen with it turned off (by default) stays dim and almost unreadable.

      sendCommand(0x8d);
      sendCommand(0x14);

      and my display is bright and shining :)) thanx!

      Reply
  20. peter

    The OLED on your picture says: “flexible i2c port assignment allows use of more than 1 oled” this is something i am looking for, any idea if it is posible to change the i2c adress of the display? they are cheap but so small iwas thinking about using two of them simltiously.
    Peter

    Reply
  21. PeteWK8S

    In my sketch I have several declared variables that are returned as numerical values. How do I print those variables results to the display at a specific location (page mode). example : print(RX_Frequency) 8,0 ??

    Reply
    1. Oscar Post author

      have you checked the examples i provided in the library?
      example OLED_PrintNumbers.ino
      that should answer your question.

      Reply
  22. Oleg

    Hi, I use your library, it works, but right vertical strip of width one pixel, how to fix it? This is similar forgive shift by one pixel to the left?
    Thank you!

    Reply
    1. raymondw

      I’ve received a new display and run into the same “problem”
      Already tried couple of things but seems to stay to much to the left.
      Did you found a solutions for this?

      “Old” Adafruit display workes like a charm!
      Really like the Ozoled software!

      Reply
  23. Nick

    Hello Oscar! I have this problem: After power off and restart Arduino text, the display shows the “top down”!!! I don’t know – why is it? Following the reboot, nothing. All remains to the top of your feet! And yet – I can’t increase the font size, and transfer from one line to the next! ( if the text does not fit on one line, it is not transferred to the second…) Help me Please! Here is my sketch: #include
    #include
    #include “DHT.h”

    #define DHTPIN 7 // what pin we’re connected to

    #define DHTTYPE DHT11 // DHT 11
    DHT dht(DHTPIN, DHTTYPE);

    void setup(){

    OzOled.init(); //initialze OLED display

    OzOled.clearDisplay(); //clear the screen and set start position to top left corner
    OzOled.setNormalDisplay(); //Set display to Normal mode
    OzOled.setPageMode(); //Set addressing mode to Horizontal Mode
    {

    OzOled.printString(“DHTxx test!”);

    dht.begin();
    }

    }

    void loop(){
    {
    // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds ‘old’ (its a very slow sensor)
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    // check if returns are valid, if they are NaN (not a number) then something went wrong!
    if (isnan(t) || isnan(h)) {
    OzOled.printString(“Failed to read from DHT”);
    delay(1000);
    } else {
    OzOled.printString(” Humidity: “);
    OzOled.printNumber(h);
    OzOled.printString(“% “);
    delay(4000);

    OzOled.clearDisplay();
    OzOled.printString(” TEMP: “);
    OzOled.printNumber(t);
    OzOled.printString(“* C”);
    delay(4000);

    OzOled.clearDisplay();

    }
    }
    }
    It would be desirable that the temperature and humidity are displayed on the center screen and large font. And, of course, was not turned over “to the top of the legs when turning the power off and reboot. THANK you very much!

    Reply
  24. LynconGabriel

    So, i’m was working in my own library using you oZoLed library. I was Implemented the full ASCII table, and others things, like BMP arrays. I’m looking the adafruit and u8glib library, and they can control a independent pixel in the display, example:

    DrawPixel(0,0); //this is a example

    i tried use this code in my library:

    sendData(0x01);

    they draw a single pixel, but when i change to de next line, they cue some pixels off and then turn on a pixel, away from the other pixel line..

    Can you help me to fix this?

    SORRY FOR MY ENGLISH, I’M BRAZILIAN AND I’M LEARNING HOW TO SPEAK ENGLISH haha :D
    thanks!

    Reply
  25. Colin

    Hi Oscar,
    Problem solved!
    After much study of the data sheet ( and trial and error), I found that including the lines

    sendCommand(0x8d); // charge pump regulator
    sendCommand(0x14); //


    in the init() section of the OzOLED.cpp file bring everything to life!

    Regards,

    Colin

    Reply
      1. Jo

        Well it nearly worked.
        I had a display with large numbers and after re-powering all characters were upside down!
        Loading a sketch with adafruit drivers and loading my program with your library brought if back to normal.
        Strange!
        But I must say I love your library. all other libraries I know consume more than 1K RAM, the Ardafruit library takes up about 1.5KB. Not much left for adding a useful program.
        Using your library and a small display program I have not even used up 300 bytes!

    1. Andrey Vlasov

      Colin,

      I also stumbled on initialisation problem and your solution resolved it. Thank you.

      Oscar, I contacted you from other page (my apology for using wrong way of communication). I confirm that Colin’s solution works for

      OLED 0.96″ 128×64 I2C interface with four pins VCC, GND, SCL, SDA — top: yellow bottom: blue with I2C address printed on the back of display 0x78 (real I2C address is 0x3C as it was confirmed by i2c_scanner).

      ebay.com/itm/Yellow-Blue-0-96-IIC-I2C-Serial-LCD-Display-Module-F-Arduino-STM32-128×64-OLED-/291341369509?pt=LH_DefaultDomain_0&hash=item43d54c80a5

      Oscar, please integrate Colin’s findings into your library.

      Andrey

      Reply
    2. Stuart

      I can confirm this worked for me too. Had to change the OLED_ADDRESS to 0x3C instead of 0x78 as Andrey discovered (I bought the same OLED screen) and with these two lines added I have “Hello World” up and running.

      Thanks for this.

      Reply
    3. Tom

      ok I got it working (at least it seems so far:

      sendCommand(0x8d); // charge pump regulator
      sendCommand(0x14); // VCC
      sendCommand(0xA0 | 0x1); //
      sendCommand(0xC8); //

      not too sure what exactly last two commands do yet, but it does put everything “straight” it seems

      Reply
  26. Colin

    Hi Oscar,
    I like your library as it does not use as much SRAM as the Adafruit lib. I have tested the examples and they all work but there is an odd problem.
    When I load an Adafruit example it displays correctly. I then load up one of your examples and this also works.
    Now if I turn off the power and then turn it on again, the OLED display does not light. Switching the power off and on with the Adafruit examples does not cause a problem.
    It seems that there is some setting in the Adafruit init() that allows the display to light but when the 5v supply is removed, this feature is reset.
    I had also noticed that Adafruit examples do not display unless the Adafruit_SSD1306::display function is used. Is there an equivalent in your library? I am afraid that my C++ knowledge is only very limited!

    Regards,

    Colin

    Reply
    1. Jo

      I found the same issue. After I read this psot, I just pulled the powersupply (USB plug) and put it in again. No more display; also not after reset
      According to the above advice I loaded a small oscilloscope scetch based on the Adafruit drivers for the OLED. The lights were back on. And then I loaded your program again and all was good..

      Reply
  27. Steven

    You might want to look at the u8glib library. I’ve been using that to controller the same OLED display and it works great.

    It works with both Arduino (I’ve had it working on Arduino Uno) and AVR (on my atmega328p).

    Reply
  28. tryer

    C:Program Files (x86)ArduinolibrariesOzOLEDOzOLED.cpp: In member function ‘void OzOLED::init()’:
    C:Program Files (x86)ArduinolibrariesOzOLEDOzOLED.cpp:448: error: ‘TWBR’ was not declared in this scope

    Reply
    1. Pete

      I am getting this same 448 error ‘TWBR’ not declared in this scope…in the OzOLED.cpp

      What causes this or better what was the solution so compiling can start??

      Reply
      1. Oscar Post author

        are you using a different micro controller? (i.e. you are not using the Arduino UNO?)
        a quick google gave me this: forum.sparkfun.com/viewtopic.php?f=14&t=38031

  29. The.ONE

    Could you please re-upload library? I downloaded it, but it says that the archive is damaged. Thanks in advance!

    Reply
  30. Halil

    Hey! Great library, I wanted to use this display to program a game, Should i work with hex numbers array and bitwise operations for screen updates or would working with X and Y coordinates and a binary array function be a better idea?

    Reply
    1. Oscar Post author

      depends on how much needs to be change each frame (each time). If it’s not a lot, for example, only a few characters, it’s better to update only these characters, ie with X and Y coordinator.

      Reply
  31. Nico Verduin

    Got the Oled today
    Downloaded the lib
    loaded the demo …..AND…..
    Works like a charm!!!!!

    Reply
  32. Mahouny

    Hi,
    could you please re-upload your OLED library ?
    The zip file on google code seems to be broken.
    Kind regards,
    Richi

    Reply
  33. Filipe

    Great work putting this library up. Many thanks for this!

    I, being a beginner at programming, found this extremely helpful, as all other libraries make you sweat just to type something on the screen.

    May I suggest you put up a list of how to work with all the functions on your library? I went through the library files and figured the little stuff out, but it would be awesome to use all the features it has.
    Yeah I know…. N00bs give a lot of trouble don’t they? =)

    Reply
    1. Oscar Post author

      Hi, thanks for the support.
      have you checked out the example sketches in the library? I used almost all the functions in the examples (i might have missed a few functions which I just came up with after I wrote the example sketches)

      Reply
  34. Rickard Nordström Pettersson

    I should be very greatful to take a look at your library, i sitting to create my own for SSD1306 and looks like they working a lot the same.

    Send me a e-mail if you whant to share the code, i am looking forward to see your e-mail ;-)

    Reply
    1. Oscar

      Yes, functionality wise they will be roughly similar to the ones out there, but I am just trying to make one that can be easily accessed and use the least resourse possible.
      I should soon publish my code, maybe in a few days time…

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Are you Robot? *

I only check blog comments once or twice a week, if you want a quick reply you can post your question on this forum IntoFPV.com... You might get a faster response from me there (multirotor related only).