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
- Raspberry Pi Running Raspbian Or Similar Linux Based OS (available on Raspberry Pi Foundation and Adafruit)
- SSD1306 OLED Display Module With I2C Interface (available on Amazon and Adafruit)
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
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.
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 on this journey and I hope you enjoyed the experience. Please feel free to share your thoughts in the comments section below.
Greetings, John —
Thanks for a very useful and informative tutorial on using the SSD1306. It was the fourth tutorial I tried after being unable to muddle through three others. One note: I did have to obtain and install the Adafruit_BBIO package in order for line 21/line 34 in the first and second example respectively to run without error.
Respectfully,
Frank
I’m glad you liked the tutorial and found it helpful. That is strange that it would require the Beaglebone library to compile.
I noticed that the Adafruit_Python_SSD1306 library used in this tutorial is now deprecated. I should probably research and rewrite the tutorial using the newer adafruit-circuitpython-displayio-ssd1306 and displayio libraries with CircuitPython.