ESP8266 NodeMCU – Controling Adafruit SSD1306 OLED Display

In this tutorial, we will learn how to control an Adafruit SSD1306 OLED Display (Organic Light-Emitting Diode). Understanding the basic working principles of the SSD1306 and its usefulness, we can now begin to apply them in our projects.

Parts Required

To build the global setup you must have the following parts:

Note: You do not need to have a NodeMCU board nor an ESP8266 to follow this tutorial. I am using this board because it is very famous and also because I will post future tutorials using wifi communications. In order to use other boards, you just have to change the pin number.

SSD1306 OLED Display

Figure 1

The SSD1306 is a popular option when it comes to picking an OLED I2C display to use alongside a microcontroller.

At the heart of the module is a powerful single-chip CMOS OLED driver controller – SSD1306. It can communicate with the microcontroller in multiple ways including I2C and SPI.

SPI is generally faster than I2C but requires more I/O pins. While I2C requires only two pins and can be shared with other I2C peripherals. It is a trade-off between pins and speed. For now, we will use SPI communication. It also has, embedded colour contrast and brightness control, display RAM and oscillator. In the end, is a chip that not only consumes minimal power but requires not many external components for functionality!

Circuit

Figure 2

The required connections are very simple, but first, it is recommended to take a look at the pins of our OLED, in order for it to work as properly. Therefore, we started by the power pins, connecting the VCC pin to the 3.3V output on the NodeMCU and connect GND to the ground. Next, we connect the SCL and SDA pins to the I2C clock (D1) and to the I2C data (D2) pins on the NodeMCU, respectively. Figure 2 diagram shows the result of the described connections.

Instaling Library For OLED Display

Before developing our code and in order to use the SSD1306 controller of the OLED, it is required to install Adafruit’s SSD1306 library, which was developed to hide away the complexities of the controller so that we can perform simple commands to control the display.

To install the library, navigate to the Sketch > Include Library > Manage Libraries… and then search for “adafruit ssd1306”. Look for Adafruit SSD1306 by Adafruit, click on that entry and then select Install, as shown in figure 3.

Figure 3

This Adafruit SSD1306 library needs to be paired with the Adafruit GFX Library to display graphics primitives like points, lines, circles, rectangles and many other characters. Type “adafruit gfx” in the search filter and install this library as well, as shown in figure 4.

Figure 4

Modifying Adafruit SSD1306 Library

Initially, Adafruit’s SSD1306 Library is not set up for the 128×64 OLED displays, which is the one we are using in this tutorial. To make this library work for our case, the display size must be changed in the Adafruit_SSD1306.h file, otherwise, an error message saying #error (“Height incorrect, please fix Adafruit_SSD1306.h!”); may appear when compiling the sketch in the Arduino IDE. This file is generally located under My Documents > Arduino > libraries > Adafruit_SSD1306, like in figure 5.

Figure 5

Now, open the Adafruit_SSD1306.h file in a text editor and scroll down until the section with the SSD1306 Displays’ sizes. Afterwards, comment out #define SSD1306_128_32 and uncomment #define SSD1306_128_64, just like presented in Figure 6.

Figure 6

Finally, save the file and open Arduino IDE. If you had it open while you were changing the Adafruit_SSD1306.h file, restart it. That’s it. It is now possible to upload the code to get the display printing!

Image Bitmap Array Generation

There are many ways to obtain a bitmap of the images you want to see in your OLED display. In this tutorial, we will use the LCD assistant program, which is one of the simplest bitmap array generation programs. But, before putting our image in the program, we’ll need to resize it into a 128x64px image, which is the dimensions of the OLED display we are using. As an example, we have used our awesome GEEKERING image.

To start with, open your image file in MS Paint and resize it to 128×64px by selecting Home > Resize > Pixels, as shown in figure 7. You may need to crop the image vertically or horizontally so that the image’s dimension is proportional to desired size (for instance 256x128px, 384x192px, etc.)

Figure 7

Then, save your file as bitmap, choosing File > Save as > Save as type > Monochrome Bitmap(*.bmp;*.dib) (figure 8). This will generate a binary bitmap image that has only two possible values for each pixel i.e. 0 (black) or 1 (white). One disadvantage in this procedure is the impossibility of threshold level setting since it is set to 50% by default and cannot be changed.

Figure 8

Now, you need to download the LCD assistant program by clicking in the following link: http://en.radzio.dxp.pl/bitmap_converter/. Open the executable and load your bitmap from File > Load image.

Figure 9

When I said previously that this is one of the simplest bitmap array generation programs, it’s because there’s nothing much you can do with this tool. So, just select File > Save output and then save it as a text file. It is expected that your file looks something like the one shown in figure 10.

Figure 10

That’s it. You have successfully created your array. All you have to do now is to paste the bitmap array into your code.

Alternatively, there’s an online application called image2cpp which can convert your image into an array (http://javl.github.io/image2cpp/). Image2cpp is newer and much more powerful than LCD assistant. It includes some extra features which allow us to, for example, converts multiple images simultaneously, adjusts the brightness threshold between black and white and even re-centre the image vertically and/or horizontally. If you want to go beyond what is described in this tutorial, we suggest you give this application a try.

Coding

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

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET LED_BUILTIN // Reset pin #
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const unsigned char geekering [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x08, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x1d, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x80, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x1f, 0x80, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x0f, 0xc0, 0x0f, 0xe0, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x01, 0xfc, 0x3f, 0xf0, 0x7f, 0xf8, 0x3f, 0xf8, 0x7c, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x01, 0xf8, 0x3f, 0xf0, 0x3f, 0xf0, 0x1f, 0xf8, 0x7c, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x01, 0xf0, 0x3f, 0xf0, 0x3f, 0xf0, 0x1f, 0xf8, 0x3c, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xf0, 0x38, 0x00, 0x1f, 0xe0, 0x1c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x1f, 0xe0, 0x3c, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x1c, 0xe0, 0x3c, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x00, 0x18, 0x60, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x30, 0x3f, 0xe0, 0x18, 0x20, 0x3f, 0xe0, 0x30, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x30, 0x3f, 0xe0, 0x30, 0x30, 0x3f, 0xe0, 0x30, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x38, 0x3f, 0xe0, 0x30, 0x30, 0x3f, 0xe0, 0x30, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x00, 0x30, 0x30, 0x3c, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x00, 0x70, 0x18, 0x3c, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x00, 0x60, 0x18, 0x3c, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0c, 0x38, 0x00, 0xe0, 0x0c, 0x1c, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0c, 0x3f, 0xf0, 0xc0, 0x0c, 0x1f, 0xf8, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x0c, 0x3f, 0xf1, 0xc4, 0x06, 0x1f, 0xf8, 0xc0, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x06, 0x3f, 0xf3, 0x84, 0x07, 0x3f, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0x3f, 0xf7, 0x0c, 0x03, 0x9f, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x0e, 0x0c, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xfc, 0x0e, 0x00, 0xfe, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x07, 0x80, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup()   
{                
  // initialize with the I2C addr 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

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

  // Display "GEEKERING"
  display.setTextColor(WHITE);
  display.setCursor(12,24);
  display.setTextSize(2);
  display.println("GEEKERING");
  display.display();
  delay(3000);
  display.clearDisplay();
  
  // Display logo
  display.drawBitmap(0, 0,  geekering, 128, 64, WHITE);
  display.display();
  delay(3000);
  display.clearDisplay();

  // Display "#youcandoit" scroling to the right
  display.setCursor(32,24);
  display.setTextSize(1);
  display.println("#youcandoit");
  display.display();
  display.startscrollright(0x00, 0x07);
  delay(9000);
  display.stopscroll();
}

void loop() {}

Leave a Reply

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