Today we will see how to interface the OLED display with Orange Pi zero. The display we are going to use is based on a SSD1306 monochrome display. The following hardware is required for this
The below links are my affiliate links
Before starting with the OLED, you need to setup the Orange pi zero and Install Armbian distro and get it ready for the next step.
The OLED Display:
The OLED display that we are using has a SSD1306 as its display controller. The controller can be controlled using I2C Interface to display pixels and can address 128X60 unique pixels. Since it is a mono chrome you have only one bright color .
The pin placement order is shown the same way the board is place in the below picture. The Orange Pi zero has two I2C interfaces , here the pin no 3 and 5 i.e PA 12 and PA11 are I2C Data and I2C Clock pins.
In order to access the I2C device the I2C driver needs to be enabled in the Linux kernel and rightly configure to used the hardware. We are using the Armbian Distro for the Orange Pi zero and it supports the I2C out of the box.
In Linux when the I2C is configured properly it will appear as devices /dev/i2c-X where X can be 0, 1 so on. In my Armbian installed Orange Pi Zero it appears as shown below.
root@orangepizero:~# ls /dev/i2c-* /dev/i2c-0 /dev/i2c-1
These are character devices which are created by I2C driver. To access the devices that are connected to the bus you can either use I2C utilities or programs that are specifically written using I2C libraries.
Now that we know about the I2C devices nodes let us install the utilities that can be used for scanning and debugging the I2C bus .
root@orangepizero:~# apt-get install i2c-utils
We have connected the OLED display to the /dev/i2c-0 of the orange pi zero. In order to know what is the I2C Address of the device (Though I know it already, it might help some where).
root@orangepizero:~# i2cdetect -r 0 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-0 using read byte commands. I will probe address range 0x03-0x77. Continue? [Y/n] y 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- 40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
"--". The address was probed but no chip answered. "UU". Probing was skipped, because this address is currently in use by a driver. This strongly suggests that there is a chip at this address. An address number in hexadecimal, e.g. "2d" or "4e". A chip was found at this address.
Now we know that the i2c address of the device is 0x3C . The I2C bus allows devices to be plugged and unplugged without rebooting Pi. It’ll mess up some accesses, but I2C will recover.
OLED python Library
With the emergence of Pi board and the Linux distros along with it there are always more than one library available for each interface. Likewise for OLED display there are many libraries and many variants of libraries . For the OLED with SSD1306 I choose this library https://github.com/codelectron/ssd1306 which are my modification over https://github.com/nukem/ssd1306 which is again a modification over https://github.com/rm-hull/luma.oled.
If you are looking for library for Raspberry pi then I would suggest you the https://github.com/rm-hull/luma.oled .
Library installation over virtualenv:
It is always a safe to use virtualenv for experimental things and I will be installing the library in virtual environment,
#virtualenv oledenv #source oledenv/bin/activate (oledenv)# (oledenv)# git clone https://github.com/codelectron/ssd1306/ (oledenv)# cd ssd1306 (oledenv)# python setup.py install (oledenv)# pip install Pillow –no-cache-dir (oledenv)# pip install smbus2 --no-cache-dir
Hurray, with this we are done with the installation process, the final part of the process is to test it with some demo code. if they work then there is nothing needed to be tweaked.
you are already in the folder ssd1306/ and now go examples folder and you will find quite some. (If you go to the more mature and the parent repo rm-hull/luma.oled you will find plenty of examples )
python sys_info.py Traceback (most recent call last): File "sys_info.py", line 13, in <module> import psutil ImportError: No module named psutil
You see this demo depends on another module psutil, so you need to install it using pip
# pip install psutil python sys_info.py
You will get an output like shown below.
For more information you check the source at https://github.com/codelectron/ssd1306/blob/master/examples/sys_info.py
Moving forward I would like to show another demo
I also ran a maze demo you can see the output here
Now lets get to the understanding of the library. I will explain you some fundamental stuffs which you can do with the library and all other things are built on top of it.
The first part of graphics is plotting a single pixel in a graph.
The output will look like a horizontal line as shown below
from oled.device import ssd1306, sh1106 from oled.render import canvas from PIL import ImageFont, ImageDraw device = ssd1306(port=0, address=0x3C) # rev.1 users set port=0 with canvas(device) as draw: draw.point((5,9),fill=255) draw.point((6,9),fill=255) draw.point((7,9),fill=255) draw.point((8,9),fill=255) draw.point((9,9),fill=255)
from oled.device import ssd1306, sh1106
Here I import thedisplay hardware related module which can speak with ssd1306 controller.
from oled.render import canvas
Assume the canvas to the the buffer which will be used to transfer the content to display controller.
from PIL import ImageFont, ImageDraw
There are from the Python Imaging Library to perform varius operation on a Image.
device = ssd1306(port=0, address=0x3C) # rev.1 users set port=0
We specifiy which I2C bus and the Device address to the display controller object and get a device handler as return.
with canvas(device) as draw:
We pass this device handler to the canvas and it returns a canvas handler which can be used like an Image and apply ImageFont and ImageDraw functions.
Plot a point or pixel at X axis 5 and Y axis 9 and fill with 255. In Monochrome oled there are only two color so if you set fill=1 or fill=255 they mean the same.
You can check out the latest source at https://github.com/codelectron/ssd1306/blob/master/examples/pixeloled.py
Now lets see the next example
This will create a rectangle box.
from oled.device import ssd1306, sh1106 from oled.render import canvas from PIL import ImageFont, ImageDraw device = ssd1306(port=0, address=0x3C) # rev.1 users set port=0 with canvas(device) as draw: draw.rectangle((0, 0, 40, 40), outline=255, fill=255)
draw.rectangle((0, 0, 40, 40), outline=255, fill=255)
This will create a rectane with top left coordinate as 0,0 and bottom right as 40,40 and outlike can be 0 or 1 and fill can be 0 or 1.
For more information about the ImageDraw refer to http://pillow.readthedocs.io/en/3.1.x/reference/ImageDraw.html
Now that we plotted a pixel, drew a shape, lets try to place some text.
from oled.device import ssd1306, sh1106 from oled.render import canvas from PIL import ImageFont, ImageDraw device = ssd1306(port=0, address=0x3C) # rev.1 users set port=0 with canvas(device) as draw: font = ImageFont.load_default() draw.text((0, 0), "Hello World", font=font, fill=255)
Here we go , we have printed Hellow world. Now lets see the code
font = ImageFont.load_default()
A default font of the system is loaded to the font object.
draw.text((0, 0), “Hello World”, font=font, fill=255)
The text method takes the co-ordinate where to start and the text “Hello world” in this case and the font.
font = ImageFont.truetype(‘./ssd1306/fonts/Volter__28Goldfish_29.ttf’,8)
This will load the given font at the size 8 and you can see the output here.
font = ImageFont.truetype(‘./ssd1306/fonts/Volter__28Goldfish_29.ttf’,20)
This line does the same with the font size of 20 and the output is shown below.
You can see the increase in the size in the last two outputs. For more example refer to https://github.com/codelectron/ssd1306/tree/master/examples
The advanced version of example is at https://github.com/rm-hull/luma.examples and it supported many other hardwares as compared to the one I forked.
If you have any comment/correction/feedback or just want to say hi, drop a comment below, I will be happy to respond back. If you want any other tutorials contact me.