SPI Interface between Raspberry Pi and SSD1306 OLED Display Tutorial

When aiming to implement graphic and text display functionality on a Raspberry Pi, connecting an OLED display is a common choice. In this regard, utilizing the SSD1306 OLED display with the SPI interface proves to be a straightforward and effective method. The core objective of this tutorial is to delve into the SPI communication principles between the Raspberry Pi and the SSD1306 OLED display. By configuring the Raspberry Pi’s SPI interface, establishing the connection with the SSD1306 OLED module, and utilizing the Adafruit_Python_SSD1306 library, we will systematically achieve the capability to display graphics on the OLED display.

SSD1306 OLED module

Table of Contents

Concepts and Principles Explanation

SPI

The SPI (Serial Peripheral Interface) is a serial communication protocol employed for communication between digital devices. The SPI bus typically operates in a master-slave configuration, involving one master device and one or more slave devices. Communication requires the use of four lines:

  • SCLK (Serial Clock): A clock signal line provided by the master device.
  • MOSI (Master Output Slave Input): An output line from the master device to send data to the slave device.
  • MISO (Master Input Slave Output): An output line from the slave device to send data to the master device.
  • CS/SS (Chip Select/Slave Select): A line used by the master device to select a specific slave device for communication.

Most devices utilizing SPI come equipped with built-in SPI modules, allowing easy communication by writing commands to registers. Even in the absence of a hardware SPI interface, software implementation is possible by manually manipulating GPIO for communication, adhering to the corresponding data transfer timing diagram.

Concerning the Raspberry Pi, it comes with a built-in SPI interface, but it is typically disabled by default. To utilize the SPI protocol for communication with other devices, you usually need to follow these steps:

  1. Run the command sudo raspi-config to access the configuration page.
  2. Locate the SPI interface in the configuration page and enable it.

Raspberry Pi SPI interface settings

SSD1306

The SSD1306 is a chip commonly used to drive OLED displays, designed and manufactured by Solomon Systech. It utilizes organic compounds as luminescent materials, achieving higher contrast and a broader viewing angle. What are the advantages of SSD1306 OLED displays?

  • High-Quality Display: The SSD1306 OLED display features high contrast and brightness, ensuring clear visibility of content even in low-light conditions. Additionally, OLED technology enables the screen to deliver excellent performance at various viewing angles without color shifts or distortions typical of LCD displays.
  • Highly Flexible: The SSD1306 supports multiple communication interfaces, including I2C, SPI, and others, allowing easy integration into various microcontroller and microcontroller systems. The versatility of SSD1306-compatible OLED displays provides enhanced design flexibility.
  • Fast Response: Despite being a low-power display, the SSD1306 OLED display offers rapid pixel response times, facilitating smooth graphics and text display.

Raspberry Pi and SSD1306 OLED Display Wiring

Careful consideration must be given to connecting the SSD1306 OLED module to the GPIO pins of the Raspberry Pi, ensuring alignment with both BCM numbering and the physical pin numbering system. Here is a simplified description of the connection steps:

  • GND Pin: Connect the module’s GND pin to the Raspberry Pi’s GND pin.
  • VCC Pin: Ensure compatibility between the OLED module’s voltage requirements and the 3.3V output of the Raspberry Pi.
  • D0 Pin (SCLK): Connect OLED’s D0 to the Raspberry Pi’s SCLK pin (BCM GPIO 11, Physical Pin 23).
  • D1 Pin (MOSI): Connect OLED’s D1 to the Raspberry Pi’s MOSI pin (BCM GPIO 10, Physical Pin 19).
  • RES Pin: Connect OLED’s RES to the Raspberry Pi’s BCM GPIO 17 (Physical Pin 11).
  • DC Pin: Connect OLED’s DC to the Raspberry Pi’s BCM GPIO 22 (Physical Pin 15).
  • CS Pin (CE0): Connect OLED’s CS to the Raspberry Pi’s CE0 pin (BCM GPIO 8, Physical Pin 24).

Raspberry Pi and SSD1306 OLED Display Wiring

Installing Relevant Libraries

Now we need to ensure that the system has the dependencies required to build and run the Adafruit_Python_SSD1306 library and install the library into the system for future projects involving communication between the Raspberry Pi and SSD1306 OLED.

  1. Update the environment and essential tools:
				
					sudo apt-get update
sudo apt-get install build-essential python-dev python-pip
sudo pip install RPi.GPIO
				
			
  1. Install Python libraries:
				
					sudo apt-get install python-imaging python-smbus
				
			
  1. Install the Adafruit_Python_SSD1306 library:
				
					sudo apt-get install git
git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
cd Adafruit_Python_SSD1306
sudo python setup.py install
				
			

Writing Python Programs

At this stage, we will thoroughly test the SSD1306 OLED module through a Python program, achieving vivid graphics and text displays:

  1. Create and Initialize:

Firstly, we need to create a display object representing the OLED module and initialize it. This serves as the foundation for the entire testing process:

				
					import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
from PIL import Image, ImageDraw, ImageFont
# Pin configuration
RST = 17        # Reset pin
DC = 22         # Data/Command pin
SPI_PORT = 0    # SPI port
SPI_DEVICE = 0  # SPI device
# Initialize the OLED module
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))
disp.begin()
disp.clear()
disp.display()  # Clear the screen
				
			
  1. Draw Graphics, Load Images, and Display Text

Next, we use the Image and ImageDraw modules of the PIL library to create three image objects. We then draw graphics and text on these images using methods from the ImageDraw module:

				
					# Image 1: Draw graphics
width = disp.width
height = disp.height
image1 = Image.new('1', (width, height))
draw1 = ImageDraw.Draw(image1)
padding = 1
shape_width = 50
left = padding
top = padding
right = width - padding
bottom = height - padding
# Draw a rectangle
draw1.rectangle((left, top, right, bottom), outline=1, fill=0)
# Draw an ellipse
draw1.ellipse((left + 10, top + 10, left + 10 + shape_width, top + 10 + shape_width), outline=1, fill=0)
# Draw a triangle
draw1.polygon([(right - 20, top + 10), (width / 2 + 5, bottom - 10), (right - 5, bottom - 10)], outline=1, fill=0)
# Image 2: Load an image
image2 = Image.open('testImage.jpg').resize((128, 64)).convert('1')
# Image 3: Display text
image3 = Image.new('1', (width, height))
draw3 = ImageDraw.Draw(image3)
font1 = ImageFont.load_default()
font2 = ImageFont.truetype('04B_30__.TTF', 15)
font3 = ImageFont.truetype('baby blocks.ttf', 18)
# Display text on image3
draw3.text((0, 0), 'Hello', font=font1, fill=1)
draw3.text((0, 15), 'World!', font=font2, fill=1)
draw3.text((0, 35), 'Enjoy it!', font=font3, fill=1)

				
			
  1. Loop for Display

Finally, through a loop, we cyclically display these three images on the OLED module:

				
					try:
    index = 1
    while True:
        if index == 1:
            disp.image(image1)  # Display image1
            index += 1
        elif index == 2:
            disp.image(image2)  # Display image2
            index += 1
        else:
            disp.image(image3)  # Display image3
            index = 1
        disp.display()  # Update the display
        time.sleep(2)  # Pause for 2 seconds
except:
    disp.clear()  # Clear the display in case of an exception
    disp.display()  # Update the display to reflect the clearing
				
			

In the above program, we create three Image objects—image1, image2, and image3—for cyclic display on the OLED screen. Let’s understand the characteristics of each object:

  • About image1:

image1 is generated by calling the Draw object of the ImageDraw module and using its rectangle method to draw a rectangle. Considering that the SSD1306 monochrome OLED graphics display supports only two colors (on and off), we define color values as 1 and 0. Typically, 1 represents on, and 0 represents off. It’s crucial to note that values greater than 1 will be interpreted as the “on” state.

  • About image2:

image2 is a loaded image of a dolphin. In our project, we don’t need to concern ourselves with the format of the image because we can use the resize() method to adjust it to the 128×64 size of the OLED screen. Subsequently, we convert the image to a binary image using the convert(‘1’) method, passing the parameter “1.” It’s important to choose an image that doesn’t contain excessive color gradients and details, as these details will be simplified into pixels with two states on the OLED—making it impossible to fully represent.

  • About image3:

image3 contains the display of some text. Using the text method, we added some text to the image.

Ending

Finally, the following results are displayed on the SSD1306 OLED display:

Final Results

You Might Be Interested

raspberry pi autostart
How to Auto Start Programs on Raspberry Pi

Automating program startup on the Raspberry Pi can be achieved through various methods. Editing the “/etc/rc.local” file or using desktop applications, while simpler, may not

Scroll to Top