Electronics Software Development

Interfacing An SSD1306 Display Module To A Raspberry Pi

Raspberry Pi SSD1306 Graphic
Written by John Woolsey

Introduction

This tutorial teaches how to connect an SSD1306 based OLED display module to a Raspberry Pi using the I2C bus interface and display text and graphics on the module’s screen. A basic understanding of electronics and programming is expected along with some familiarity with the Raspberry Pi platform. If you are new to the Raspberry Pi platform or would just like to refresh your knowledge, please see our Blink: Making An LED Blink On A Raspberry Pi tutorial before proceeding with this one. Detailed versions of all source code used in this tutorial are available on GitHub for your reference.

What Is Needed

Background Information

Organic light emitting diode (OLED) displays typically are thinner, more efficient, and provide a better viewing experience in comparison to other types of displays. They are increasingly being used for TVs, mobile phones, and other consumer electronics.

An SSD1306 display module consists of a 128×64 OLED display connected to the SSD1306 OLED Display Driver IC by Solomon Systech. The SSD1306 driver is capable of communicating with microcontrollers through I2C, SPI, and 6800/8000 parallel bus interfaces.

My development board is a Raspberry Pi 3 Model B running the Raspbian OS and my display module is the SunFounder 0.96″ Inch Blue I2C IIC Serial 128×64 OLED LCD LED SSD1306 Module (which includes the I2C based 4 pin wiring connector). If you are using a different model of the Raspberry Pi, a different Linux based OS that is similar to Raspbian, or a different SSD1306 based display model, the vast majority of this tutorial should still apply, however, some minor changes may be necessary.

Building The Circuit

Before connecting the display module to your Raspberry Pi, shutdown and disconnect the Raspberry Pi from power. This avoids accidental damage during wiring.

Some displays have their VCC and GND pin placements reversed, so make sure you connect them properly. In addition, the 4 pin I2C connector that came with my display has GND and VCC connected to the brown and white wires, not black and red as expected.

Connect the VCC and GND pins of the display module to the 3v3 (physical pin 1) and GND (physical pin 9) power pins respectively on the Raspberry Pi.

For the I2C serial bus connection, connect the SDA and SCL pins of the display module to the SDA (physical pin 3) and SCL (physical pin 5) pins respectively on the Raspberry Pi. Your particular display may require additional connections as well. See your display’s documentation for further information.

You can now connect power to your Raspberry Pi and boot it up.

To communicate with the display, we need to verify the I2C serial bus is enabled on the Raspberry Pi. This is accomplished by running the Raspberry Pi Software Configuration Tool from the command line.

% sudo raspi-config

Use your cursor keys to move around and select Interfacing Options, then I2C, then Yes, then Ok to enable the I2C serial bus. Reboot if prompted. When done, select Finish to exit the program.

We also need to determine the I2C bus address that is being used for the display. Many displays have a default I2C hexadecimal address of 0x3C. To determine the address being used for your display, run the following command and jot down the address shown as we will need it later.

% sudo i2cdetect -y 1

3c (row 30, column c) is displayed for me.

Writing The Software

I researched various libraries that can be used with SSD1306 display modules and settled on the Adafruit_Python_SSD1306 library due to its popularity. This library works well with the standard Python Imaging Library (PIL) that provides extensive graphics and drawing capabilities and comes preinstalled on Raspbian.

Run the following commands to install the Adafruit_Python_SSD1306 library.

% git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
% cd Adafruit_Python_SSD1306
% sudo python setup.py install

Interestingly, documentation for this library does not seem to exist. However, the example programs that come with the library are quite useful in understanding how to use the library. Peruse and run some of the example programs to ensure your display is functioning as expected.

% cd examples
% sudo python shapes.py
% sudo python stats.py

You may need to CTRL-C to exit some of the programs.

We will first create a Python program using the Adafruit_Python_SSD1306 and PIL libraries to display text on the screen. Create and save a new program named displayText.py with the code shown below.

# displayText.py
#
# Description:
# Prints text to an SSD1306 display module using the Adafruit_Python_SSD1306
# and Python Imaging Library (PIL) libraries.
#
# Created by John Woolsey on 07/05/2018.
# Copyright (c) 2018 Woolsey Workshop.  All rights reserved.


import Adafruit_SSD1306
from PIL import Image, ImageDraw, ImageFont
import RPi.GPIO as GPIO


# Adafruit_Python_SSD1306 graphics library configuration for
# SunFounder OLED SSD1306 Display Module.
# Use the configuration compatible with your display module.
# See library "examples" directory for configuration selection.
# 128x64 display with hardware I2C and no reset pin
display = Adafruit_SSD1306.SSD1306_128_64(rst=None)

# Setup
display.begin()  # initialize graphics library for selected display module
display.clear()  # clear display buffer
display.display()  # write display buffer to physical display
displayWidth = display.width  # get width of display
displayHeight = display.height  # get height of display
image = Image.new('1', (displayWidth, displayHeight))  # create graphics library image buffer
draw = ImageDraw.Draw(image)  # create drawing object
font = ImageFont.load_default()  # load and set default font

# Draw text
draw.text((0,0), "Hello,\nRaspberry Pi!", font=font, fill=255)  # print text to image buffer

# Display to screen
display.image(image)  # set display buffer with image buffer
display.display()  # write display buffer to physical display

# Cleanup
GPIO.cleanup()  # release all GPIO resources

Lines 11-13 load the libraries we will use in our program: Adafruit_SSD1306 for display communication, PIL for drawing, and RPi.GPIO for general GPIO access.

Line 21 configures the Adafruit_Python_SSD1306 library for use with our particular display. The display identifier is the name that we will use throughout our program when referring to the Adafruit_Python_SSD1306 library operations we are applying to our display. This can be a different name if you choose, but make sure to change all of the references to it throughout the rest of the code if you do. It is very important to use a configuration that is compatible with your particular display module. Look through the Adafruit_Python_SSD1306 library’s example code to determine the correct configuration for your display. The Adafruit_SSD1306.SSD1306_128_64(rst=None) library configuration I chose is for a generic SSD1306 display module with a size of 128×64 pixels using a hardware based I2C bus interface and no reset pin. If the I2C bus address for your display we determined previously is not the default value of 3c, you can specify the address to use by adding the optional i2c_address argument to the configuration, which becomes Adafruit_SSD1306.SSD1306_128_64(rst=None, i2c_address=0x3C), and specifying the address for your display.

Lines 24-31 initializes and sets up the display for use. This includes creating the PIL library’s image buffer and drawing object along with setting the default font. The image buffer is the place that the drawing object uses to draw shapes and text.

Line 34 draws the text to the screen beginning in column 0 and row 0 using the specified font and full opacity.

Lines 37 and 38 draw the text to the display screen. Line 37 loads the display buffer with the image buffer where we are drawing. Line 38 writes the display buffer to the actual display screen.

Line 41 sets all of the GPIO pins back to their default state. While technically I don’t think that running the GPIO.cleanup() function from the RPi.GPIO library is actually needed here since we are only interfacing to the I2C port, I believe it is a good habit to get into, so I have included it here.

Run the program. You should see Hello, Raspberry Pi! on your display as shown below.

% python displayText.py

Raspberry Pi Display Text

Play around with changing the text and its location on the screen.

Next, let’s add some graphics. This program will display text and graphics on the screen. Create and save a new program named displayGraphics.py with the code shown below.

# displayGraphics.py
#
# Description:
# Prints text and graphics to an SSD1306 display module using the
# Adafruit_Python_SSD1306 and Python Imaging Library (PIL) libraries.
#
# Created by John Woolsey on 07/03/2018.
# Copyright (c) 2018 Woolsey Workshop.  All rights reserved.


import Adafruit_SSD1306
from PIL import Image, ImageDraw, ImageFont
import RPi.GPIO as GPIO


# Draws LED schematic symbol with size of 60x24
def drawLED(centerX, centerY):
   draw.polygon((centerX - 10, centerY + 12, centerX + 10, centerY + 2, centerX - 10, centerY - 8), fill=255)
   draw.line((centerX + 10, centerY - 8, centerX + 10, centerY + 12), fill=255)
   draw.line((centerX - 30, centerY + 2, centerX - 10, centerY + 2), fill=255)
   draw.line((centerX + 10, centerY + 2, centerX + 30, centerY + 2), fill=255)
   draw.line((centerX, centerY - 6, centerX + 3, centerY - 10), fill=255)
   draw.polygon((centerX + 6, centerY - 12, centerX + 6, centerY - 8, centerX + 2, centerY - 12), fill=255)
   draw.line((centerX - 22, centerY + 8, centerX - 18, centerY + 8), fill=255)
   draw.line((centerX - 20, centerY + 6, centerX - 20, centerY + 10), fill=255)
   draw.line((centerX + 18, centerY + 8, centerX + 22, centerY + 8), fill=255)


# Adafruit_Python_SSD1306 graphics library configuration for
# SunFounder OLED SSD1306 Display Module.
# Use the configuration compatible with your display module.
# See library "examples" directory for configuration selection.
# 128x64 display with hardware I2C and no reset pin
display = Adafruit_SSD1306.SSD1306_128_64(rst=None)

# Setup
display.begin()  # initialize graphics library for selected display module
display.clear()  # clear display buffer
display.display()  # write display buffer to physical display
displayWidth = display.width  # get width of display
displayHeight = display.height  # get height of display
image = Image.new('1', (displayWidth, displayHeight))  # create graphics library image buffer
draw = ImageDraw.Draw(image)  # create drawing object
font = ImageFont.load_default()  # load and set default font

# Draw text
draw.text(((displayWidth - font.getsize("Woolsey")[0]) / 2, 0), "Woolsey", font=font, fill=255)  # center text at top of screen
draw.text(((displayWidth - font.getsize("Workshop")[0]) / 2, 53), "Workshop", font=font, fill=255)  # center text at bottom of screen

# Draw LED symbol
drawLED(displayWidth / 2, displayHeight / 2)  # place symbol in middle of screen (between text)

# Display to screen
display.image(image)  # set display buffer with image buffer
display.display()  # write display buffer to physical display

# Cleanup
GPIO.cleanup()  # release all GPIO resources

This code is very similar to the displayText.py program we created earlier with only the differences being highlighted. The first difference is the addition of the drawLED() function that draws lines and polygons to assemble an LED schematic symbol graphic. The second difference changes the text and its location on the screen while also calling the drawLED() function to display the graphic symbol.

Run the program. You should see the new text along with an LED schematic symbol being displayed on your screen as shown below.

Raspberry Pi Display Graphics

Again, play around and draw some of your own shapes to the screen. The ImageDraw Module reference shows all of the drawing functions available with the PIL graphics library. You can also view the top level reference for the entire PIL library with all of its extensive modules and capabilities.

Summary

In this tutorial we learned how to connect an SSD1306 based OLED display module to a Raspberry Pi development board using the I2C bus interface and draw text and graphics on the display using the Adafruit_Python_SSD1306 (display) and Python Imaging Library (graphics) libraries.

The final source code for this tutorial is located on GitHub.

Thank you for joining me in this journey and I hope you enjoyed the experience. Please feel free to share your thoughts in the comments section below.

About the author

John Woolsey

John is an electrical engineer who loves science, math, and technology and teaching it to others even more.
 
He knew he wanted to work with technology from an early age, building his first robot when he was in 8th grade. His first computer was a Timex/Sinclair 2068 followed by the Tandy 1000 TL (aka really old stuff).
 
He put himself through college (University of Texas at Austin) by working at Motorola where he worked for many years after that in Research and Development.
 
John started developing mobile app software in 2010 for himself and for other companies. He has also taught programming to kids for summer school and enjoyed years of judging kids science projects at the Austin Energy Regional Science Festival.
 
Electronics, software, and teaching all culminate in his new venture to learn, make, and teach others via the Woolsey Workshop website.

Leave a Comment