Interfacing SSD1306 OLED Display with Arduino

Most of us would be familiar with the 16×2 Dot matrix LCD display that is used in most of the projects to display some information to the user.  But these LCD displays have a lot of limitation in what they can do. In this tutorial we are going to learn about OLED displays and how to use them Arduino. There are lots of types of OLED displays available in the market and there are lots of ways to get them working. In this tutorial we will discuss about its classifications and also which will be best suited for your project.

 

Hardware Required:

  • 7pin 128×64 OLED display Module (SSD1306)
  • Arduino UNO/Nano
  • Breadboard
  • Connecting Wires
  • Computer/Laptop

 

Getting to know about OLED Displays:

The term OLED stands for “Organic Light emitting diode” it uses the same technology that is used in most of our televisions but has fewer pixels compared to them.  It is real fun to have these cool looking display modules to be interfaced with the Arduino since it will make our projects look cool. We have covered a full Article on OLED displays and its types here.

 

Monochrome 7-pin SSD1306 0.96 OLED display Monochrome 7-pin SSD1306 0.96 OLED display back side

 

We are using a Monochrome 7-pin SSD1306 0.96” OLED display. The reason for choosing this display is that it can work on three different communications Protocols such as the SPI 3 Wire mode, SPI four wire mode and IIC mode. This tutorial will cover how to use the module in SPI 4-wire mode as it is the fastest mode of communication and the default one.

 

The pins and its functions are explained in the table below.

Pin Number

Pin Name

Other Names

Usage

1

Gnd

Ground

Ground pin of the module

2

Vdd

Vcc, 5V

Power pin (3-5V tolerable)

3

SCK

D0,SCL,CLK

Acts as the clock pin. Used for both I2C and SPI

4

SDA

D1,MOSI

Data pin of the module. Used for both IIC and SPI

5

RES

RST,RESET

Resets the module (useful during SPI)

6

DC

A0

Data Command pin. Used for SPI protocol

7

CS

Chip Select

Useful when more than one module is used under SPI protocol

In this tutorial we will simply operate the module in 4-Wire SPI mode, we will leave the rest for some other tutorial.

Arduino community has already given us a lot of Libraries which can be directly used to make this a lot simpler. I tried out a few libraries and found that the Adafruit_SSD1306 Library was very easy to use and had a handful of graphical options hence we will use the same in this tutorial. But, if your project has a memory/speed constraint try using the U8g Library as it works faster and occupies less program memory.      

 

Hardware and connections:

The Circuit Diagram for SSD1306 OLED interfacing with Arduino is really simple and is shown below

Arduino interfacing with Monochrome OLED display circuit

We simply have establish a SPI communication between the OLED module and Arduino. Since the OLED runs on 3V-5V and consumes very little power it does not need an external power supply. You can simply use wires to make the connection or use a breadboard as I have used so that it is easy to experiment. The connection is also listed in tale below

S.No

Pin Name on OLED module

Pin Name on Arduino

1

Gnd, Ground

Ground

2

Vdd, Vcc, 5V

5V

3

SCK, D0,SCL,CLK

10

4

SDA, D1,MOSI

9

5

RES, RST,RESET

13

6

DC, A0

11

7

CS, Chip Select

12

 

Note: You will not be able to visualize any backlight/glow on the OLED module just by powering it. You have to program it correctly to notice any changes on the OLED display.

 

Programming the SSD1306 OLED display for Arduino:

Once the connections are ready you can start programming the Arduino. As said earlier we will be using the Adafruit library and GFX library for working with this OLED module. Follow the steps to test run your OLED display.

 

Step 1: Download the Adafruit Library and the GFX library from Github using the link below

  1. Adafruit Library
  2. GFX Graphics Library

 

Step 2: You should have download two Zip files. Now add them to your Arduino by following

 Sketch->Include Library -> Add Zip library as shown below. Then select the library we just downloaded. You can select only one library at a time, hence you have to repeat this step again.

including library for Arduino interfacing with OLED display

 

Step 3: Launch the example Program by selecting File->Examples->Adafruit SSD1306 -> SSD1306_128*64_SPI.ino as shown in the image below.

using example arduino code- for interfacing OLED display

 

Step 4: Inside the example program on top of line 64 add the line “#define SSD1306_LCDHEIGHT 64” as shown in the image below.

code for Arduino interfacing with OLED display

 

Step 5: Now upload the program and you should see the OLED display firing up with the default Adafruit example code as shown in the below picture. The full working video is given at the end.

 

This example program shows you all possible graphics that could be displayed in the OLED screen. This code should be enough for you to create bitmaps, draw lines/circles/rectangles, play with pixels, display char and string with different fonts and size etc...

If you want to understand the Library and its functions better you can read further. Each junks of the code is split and explained with the help of comment lines. Complete code is given at the end of this Article

 

Displaying and clearing the screen:

Writing on OLED screen is just like writing on a black board, we have to write the values and then clean it before it could be overwritten. The following commands are used to write and clear the display

display.display(); //Write to display
display.clearDisplay(); //clear the display

 

Displaying a Character Variable:

To display the content inside a variable the following code can be used.

   char i=5; //the variable to be displayed
  display.setTextSize(1);  //Select the size of the text
  display.setTextColor(WHITE);  //for monochrome display only whit is possible
  display.setCursor(0,0); //0,0 is the top left corner of the OLED screen
  display.write(i); //Write the variable to be displayed

 

Drawing a Line,Circle,Rectange,Triangle:

If you want add some symbols to your display you can use the following code to draw any of the following

display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE);
//void drawLine( x0,  y0,  x1,  y1, color);

display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
//void drawRect( x0, y0,  w, h,  color);

display.drawTriangle(display.width()/2, display.height()/2-i,display.width()/2-i,display.height()/2+i,     display.width()/2+i, display.height()/2+i, WHITE);
//void drawTriangle( x0,  y0,  x1,  y1,  x2,  y2,  color);

display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
//void drawCircle( x0,  y0,  r,  color);

 

Drawing a String to the Screen:

The following chunk of code can be used o display any message in the screen at a particular place and size

  display.setTextSize(2); //set the size of the text
  display.setTextColor(WHITE); //color setting
  display.setCursor(10,0); //The string will start at 10,0 (x,y)
  display.clearDisplay(); //Eraser any previous display on the screen
  display.println("Circuit Digest"); //Print the string here “Circuit Digest”
  display.display(); //send the text to the screen

 

Displaying a bitmap image:

One untrusting thing that can be done with the OLED module is that it can be used to display bitmaps. The following code is used to display an bitmap image

static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };
display.drawBitmap(XPO], YPOS, bitmap, w, h, WHITE);
//void drawBitmap( x,  y,  *bitmap,  w,  h,  color);

 

As you can see, in order to display an image the bitmap data must be stored in the program memory in form of PROMGMEM directive. Simply put, we have to instruct the OLED display what to do with each pixel by passing it a sequence or values from a n array as shown above. This array will contain the bitmap data of the image.

 

It might sound complicated but with the help of a web tool it is very much easy to convert an image into a bit map values and load them into the above array.

Simply load the image and adjust the settings to get your preferred preview of the image. Then click “Generate Code” copy the code and paste it into your Array. Upload the program and you are all done. I tried displaying a batman logo and this is how it turned out.

convert image into bit map values OLED-display

batman logo on Monochrome 7 pin SSD1306 0.96-OLED display

 

There are still a lot of things that you can do with these libraries. To know the complete possibilities visit the Adafruit GFX graphics Primitives page.

Hope you got this running and ready to implement an OLED display in some of your projects. If you had any problem share them in the comment section and I will try my best to rectify them.

Code: 

/*********************************************************************
This is an example for our Monochrome OLEDs based on SSD1306 drivers

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/category/63_98

This example is for a 128x64 size display using SPI to communicate
4 or 5 pins are required to interface

Adafruit invests time and resources providing this open source code, 
please support Adafruit and open-source hardware by purchasing 
products from Adafruit!

Written by Limor Fried/Ladyada  for Adafruit Industries.  
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// If using software SPI (the default case):
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

/* Uncomment this block to use hardware SPI
#define OLED_DC     6
#define OLED_CS     7
#define OLED_RESET  8
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
*/

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

#define SSD1306_LCDHEIGHT 64
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

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

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC);
  // init done
  
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();

  // 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!
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw many lines
  testdrawline();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw rectangles
  testdrawrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw multiple rectangles
  testfillrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw mulitple circles
  testdrawcircle();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw a white circle, 10 pixel radius
  display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  testdrawroundrect();
  delay(2000);
  display.clearDisplay();

  testfillroundrect();
  delay(2000);
  display.clearDisplay();

  testdrawtriangle();
  delay(2000);
  display.clearDisplay();
   
  testfilltriangle();
  delay(2000);
  display.clearDisplay();

  // draw the first ~12 characters in the font
  testdrawchar();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw scrolling text
  testscrolltext();
  delay(2000);
  display.clearDisplay();

  // text display tests
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Hello, world!");
  display.setTextColor(BLACK, WHITE); // 'inverted' text
  display.println(3.141592);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print("0x"); display.println(0xDEADBEEF, HEX);
  display.display();
  delay(2000);
  display.clearDisplay();

  // miniature bitmap display
  display.drawBitmap(30, 16,  logo16_glcd_bmp, 16, 16, 1);
  display.display();

  // invert the display
  display.invertDisplay(true);
  delay(1000); 
  display.invertDisplay(false);
  delay(1000); 
  display.clearDisplay();

  // draw a bitmap icon and 'animate' movement
  testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
}

void loop() {
}

void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  uint8_t icons[NUMFLAKES][3];
 
  // initialize
  for (uint8_t f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS] = random(display.width());
    icons[f][YPOS] = 0;
    icons[f][DELTAY] = random(5) + 1;
    
    Serial.print("x: ");
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(" y: ");
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(" dy: ");
    Serial.println(icons[f][DELTAY], DEC);
  }

  while (1) {
    // draw each icon
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
    }
    display.display();
    delay(200);
    
    // then erase it + move it
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
      // move it
      icons[f][YPOS] += icons[f][DELTAY];
      // if its gone, reinit
      if (icons[f][YPOS] > display.height()) {
        icons[f][XPOS] = random(display.width());
        icons[f][YPOS] = 0;
        icons[f][DELTAY] = random(5) + 1;
      }
    }
   }
}

void testdrawchar(void) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);

  for (uint8_t i=0; i < 168; i++) {
    if (i == '\n') continue;
    display.write(i);
    if ((i > 0) && (i % 21 == 0))
      display.println();
  }    
  display.display();
}

void testdrawcircle(void) {
  for (int16_t i=0; i<display.height(); i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
    display.display();
  }
}

void testfillrect(void) {
  uint8_t color = 1;
  for (int16_t i=0; i<display.height()/2; i+=3) {
    // alternate colors
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
    display.display();
    color++;
  }
}

void testdrawtriangle(void) {
  for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(display.width()/2, display.height()/2-i,
                     display.width()/2-i, display.height()/2+i,
                     display.width()/2+i, display.height()/2+i, WHITE);
    display.display();
  }
}

void testfilltriangle(void) {
  uint8_t color = WHITE;
  for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
    display.fillTriangle(display.width()/2, display.height()/2-i,
                     display.width()/2-i, display.height()/2+i,
                     display.width()/2+i, display.height()/2+i, WHITE);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}

void testdrawroundrect(void) {
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE);
    display.display();
  }
}

void testfillroundrect(void) {
  uint8_t color = WHITE;
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}
   
void testdrawrect(void) {
  for (int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
    display.display();
  }
}

void testdrawline() {  
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, WHITE);
    display.display();
  }
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, WHITE);
    display.display();
  }
  delay(250);
  
  display.clearDisplay();
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, WHITE);
    display.display();
  }
  for (int16_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
    display.display();
  }
  delay(250);
  
  display.clearDisplay();
  for (int16_t i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
    display.display();
  }
  for (int16_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
    display.display();
  }
  delay(250);

  display.clearDisplay();
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, WHITE);
    display.display();
  }
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE); 
    display.display();
  }
  delay(250);
}

void testscrolltext(void) {
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  display.println("scroll");
  display.display();
 
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);    
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
}

Video: 

Comments (2)

  • Pratik's picture
    Pratik

    Hello,
    As I have gone through the example which you gave in your blog and it found really helpful to me.
    but I am using SSD1331 OLED display and its work on SPI Protocol.
    Some of the function may be not supported to SSD1331 OLED.
    Please give me a suggestion which modification needed?

    Regards,
    Pratik

    Sep 21, 2017
  • B.Aswinth Raj's picture
    B.Aswinth Raj

    Sorry patik, I haven't tried a SDD1331 OLED module yet. So can help you with this for now. But I sure the basics will remain the same.

     

    Sep 21, 2017

Leave a comment