blog

Monochrome 2.7” and 2.42” 128x64 OLED displays on a Raspberry Pi Zero

by snm, November 10th, 2017

OLED (organic light-emitting diode) displays are renowned for their lack of backlight requirement, allowing for deeper blacks and higher contrast. Used from watches to television sets, but to experiment with using OLEDs, I purchased a few monochrome 128x64 OLED display modules from Adafruit:

Interfacing mode for SSD1325: SPI

2.7" module unboxing

Solder on the included header:

Soldering pins

and plug into a breadboard:

Breadboarded

From here we have a choice, the SSD1325 controller chip supports three different interfacing modes (and other OLED controllers support various other modes as well):

Pinout with interfacing modes

Decided to go with SPI due to the low pin count. The reverse side of the board shows the BS1 and BS2 jumpers were already configured as “00”, meaning SPI:

SSD1325 module reverse

Curiously, this board (labeled “TW28642270B03”) looks a lot different than Adafruit’s 2.7” pictures:

Adafruit website OLED module

newer/prototype version?

Now that the header is soldered, wire it up to match the documented pinout, I connected it to a Raspberry Pi Zero as follows (using pinout.xyz for reference):

OLED Module Pin Pi Zero Pin Remarks
1 GND P01-20 GND GND, ground
2 +3V P01-17 3V3 3.3V, power
4 DC P01-18 GPIO 24 data/command, the fourth wire of “4-wire SPI” (sic)
7 SCLK P01-23 GPIO 11 (SCLK) serial clock
8 DIN P01-19 GPIO 10 (MOSI) MOSI, master out slave in (MISO is not connected, no slave output)
15 /CS P01-24 GPIO 8 (CE0) Chip enable/select 0
16 /RES P01-22 GPIO 25 reset

2.7" connected

luma.oled on Pi Zero

Run sudo raspi-config then enable SPI in “4 Interfacing Options” then “P5 I2C”. The luma-oled guide said to enable in “> Advanced Options > A6 SPI”, I guess they moved it for some reason in Debian Stretch. After enabling there are character devices for SPI:

pi@pizero:~ $ ls -l /dev/spi*
crw-rw---- 1 root spi 153, 0 Nov  7 01:39 /dev/spidev0.0
crw-rw---- 1 root spi 153, 1 Nov  7 01:39 /dev/spidev0.1

then give the pi user access:

sudo usermod -a -G spi,gpio pi

and follow the luma.oled installation steps.

pi@pizero:~ $ sudo apt-get install python-dev python-pip libfreetype6-dev libjpeg-dev build-essential
...
pi@pizero:~ $ sudo -H pip install --upgrade pip
Requirement already up-to-date: pip in /usr/lib/python2.7/dist-packages
pi@pizero:~ $ sudo apt-get purge python-pip
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libpython-all-dev python-all python-all-dev python-keyring python-keyrings.alt python-secretstorage python-wheel
Use 'sudo apt autoremove' to remove them.
The following packages will be REMOVED:
  python-pip*
0 upgraded, 0 newly installed, 1 to remove and 1 not upgraded.
After this operation, 671 kB disk space will be freed.
Do you want to continue? [Y/n] 
(Reading database ... 122781 files and directories currently installed.)
Removing python-pip (9.0.1-2+rpt1) ...
Processing triggers for man-db (2.7.6.1-2) ...
pi@pizero:~ $ sudo -H pip install --upgrade luma.oled
sudo: pip: command not found

What was the point of removing pip, causing the last command to fail? This is a known issue in the luma.core documentation on Stretch: https://github.com/rm-hull/luma.core/issues/106 - fix is to reinstall with sudo apt-get install python-pip then install luma.oled as normal with sudo -H pip install --upgrade luma.oled. This succeeded. Now to try the examples, found in http://github.com/rm-hull/luma.examples - run an example:

pi@pizero:~/luma.examples/examples$ python clock.py --display ssd1325 --interface spi
Display: ssd1325
Interface: spi
Dimensions: 128 x 64
----------------------------------------

Clock example on 2.7

It works! The OLED module shows the clock example. A sigh of relief, since I actually first ordered this same module from Amazon, Adafruit’s Monochrome 2.7” 128x64 OLED Graphic Display Module Kit, but the device was defective. Adafruit tests each module before shipment so I had more confidence their product would operate correctly. Here’s another module:

2.42” display with SSD1305

2.42" module unboxing

The 2.42” display is also 128x64 but slightly smaller than the 2.7”. It also has a different controller chip: SSD1305 instead of SSD1325. The SSD1305 supports 8-bit and SPI, just like the SSD1325, but also I2C. Solder on the header and plug it into the breadboard; fortunately, it has the same pinout so and supports the same interfacing mode as the other module so no wiring changes are needed, it can be swapped it interchangeably.

This board came configured for 8-bit interfacing mode (R18=R20=1):

R18=R20=1

necessitating desoldering the jumpers and moving them to R19 and R21, selecting SPI:

R19 and R21 SPI

luma.oled doesn’t recognize “ssd1305” but it does support ssd1306 and selecting that display type works well:

pi@pizero:~/luma.examples/examples $ python clock.py --display ssd1306 --interface spi
Display: ssd1306
Interface: spi
Dimensions: 128 x 64
----------------------------------------

2.42" clock

Both modules

Two OLED modules at the same time

Here’s how the two modules (2.7” and 2.42”) compare:

2.7" vs 2.42"

Would be nice to connect both, but how? The SPI clock/data lines can be shared, and there are two chip enables (CE0 and CE1) so the CE1 can be used for a second SPI device. DC and /RES require two more GPIOs, arbitrarily selected:

OLED Module Pin Pi Zero Pin Remarks
1 GND P01-20 GND GND, ground
2 +3V P01-17 3V3 3.3V, power
4 DC P01-16 GPIO 23 data/command
7 SCLK P01-23 GPIO 11 (SCLK) (shared) serial clock
8 DIN P01-19 GPIO 10 (MOSI) (shared) MOSI, master out slave in
15 /CS P01-26 GPIO 7 (CE1) Chip enable/select 1
16 /RES **P01-36 GPIO 16 reset

Now to drive this second display with luma.oled, we need to specify SPI device 1, as well as the data/command and reset pins:

pi@pizero:~/luma.examples/examples $ python clock.py --display ssd1325 --interface spi --spi-device 1 --gpio-data-command 23 --gpio-reset 16 

running the other command simultaneously, driving both devices:

pi@pizero:~/luma.examples/examples $ python clock.py --display ssd1306 --interface spi

Both displays at the same time

The refresh rate of the 2.7” SSD1325 is slower, so my camera picks it up mid-frame, but it looks fine in person, albeit dimmer than the 2.42” SSD1305 (which doesn’t have grayscale). Now with two clocks, we can never tell what time it is, as the saying goes. Fortunately, they both update simultaneously, so they never disagree.

What good are two OLED displays on a Pi? luma.oled has some nifty examples, including game simulators, here is invaders.py and jetset_willy.py:

python invaders.py --display ssd1325 --interface spi --spi-device 1 --gpio-data-command 23 --gpio-reset 16 
python jetset_willy.py --display ssd1306 --interface spi

Invaders and jetset willy

but a practical use for these displays will have to wait for another time. This concludes this experiment, we have seen how to successfully setup two OLED display modules, a 2.7” SSD1325-based board and a 2.42” SSD1305-based board, via SPI, to a Raspberry Pi Zero.

sys_info and starfield