Raspberry Pi SH1106

Neil HaddleyJuly 24, 2023

OLED display

IOTraspberry-pioledsh1106display

I used Python to output text and simple graphics to an OLED display connected to a Raspberry Pi.

OLED wiring

OLED wiring

i2cdetect -y 1

i2cdetect -y 1

Luma-OLED Driver

I installed the Luma-OLED driver by following these instructions:

https://luma-oled.readthedocs.io/en/latest/install.html

I installed the driver with this command

$ sudo -H pip3 install --upgrade luma.oled

I enabled I2C communications using the raspi-config application

$ sudo raspi-config

Interface Options | I2C | enable ARM I2C

i2c permissions

I followed the steps described by Alexander Rüedlinger to allow non-root users to access i2c devices (specifically the OLED display).

1) Create new user group called i2c:

$ sudo groupadd i2c

2) Change the group ownership of /dev/i2c-1 to i2c:

$ sudo chown :i2c /dev/i2c-1

3) Change the file permissions of the device /dev/i2c-1 so users of the i2c group can read and write to the device:

$ sudo chmod g+rw /dev/i2c-1

4) Add your user to the group i2c:

$ sudo usermod -aG i2c <username>

Python code

Python code

The hello.py code running on configured hardware

The hello.py code running on configured hardware

Displaying an image on the OLED display

I downloaded a stop sign image and updated the hello.py code to display the image on the OLED display.

Stop sign

Stop sign

Using OpenCV and luma.oled to display video on the OLED display

I used the cv2 library (OpenCV) to read frames from a dog video I downloaded from:

https://pixabay.com/videos/puppy-dog-playful-beach-sand-play-4740/

I then updated the code to send images captured by the webcam to the OLED display.

Dog video

Dog video

Webcam

Webcam

hello.py

PYTHON
1from luma.core.interface.serial import i2c, spi, pcf8574
2from luma.core.interface.parallel import bitbang_6800
3from luma.core.render import canvas
4from luma.oled.device import ssd1306, ssd1309, ssd1325, ssd1331, sh1106, sh1107, ws0010
5from time import sleep
6
7# rev.1 users set port=0
8# substitute spi(device=0, port=0) below if using that interface
9# substitute bitbang_6800(RS=7, E=8, PINS=[25,24,23,27]) below if using that interface
10serial = i2c(port=1, address=0x3C)
11
12# substitute ssd1331(...) or sh1106(...) below if using that device
13device = sh1106(serial)
14
15with canvas(device) as draw:
16    draw.rectangle(device.bounding_box, outline="white", fill="black")
17    draw.text((30, 40), "Hello World", fill="white")
18
19sleep(10)

stop_sign_display.py

PYTHON
1from luma.core.interface.serial import i2c, spi, pcf8574
2from luma.core.interface.parallel import bitbang_6800
3from luma.core.render import canvas
4from luma.oled.device import ssd1306, ssd1309, ssd1325, ssd1331, sh1106, sh1107
5from time import sleep
6
7from PIL import Image
8
9serial = i2c(port=1, address=0x3C)
10device = sh1106(serial)
11
12width =  device.width
13height = device.height
14
15image = Image.open("stop.png")
16
17image_r = image.resize((width,height), Image.LANCZOS)
18# Image.BICUBIC is another option
19image_bw = image_r.convert("1")
20
21device.display(image_bw)
22
23sleep(10)

dog_display_window_and_oled.py

PYTHON
1from luma.core.interface.serial import i2c, spi, pcf8574
2from luma.core.interface.parallel import bitbang_6800
3from luma.core.render import canvas
4from luma.oled.device import ssd1306, ssd1309, ssd1325, ssd1331, sh1106, sh1107
5
6from time import sleep
7
8import cv2
9
10# OpenCV follows BGR color convention and PIL follows RGB color convention
11
12# Python Imaging Library
13from PIL import Image
14
15serial = i2c(port=1, address=0x3C)
16device = sh1106(serial)
17
18width =  device.width
19height = device.height
20
21cap = cv2.VideoCapture("dog.mp4")
22while True:
23    ret, frame = cap.read()
24    if not ret:
25        break
26    cv2.imshow("Img", frame)
27    
28    color_coverted = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
29    pil_image = Image.fromarray(color_coverted)
30    image_r = pil_image.resize((width,height), Image.LANCZOS) 
31    # Image.BICUBIC is another option
32    image_bw = image_r.convert("1")
33
34    device.display(image_bw)
35
36    key = cv2.waitKey(1)
37    if key == 27:
38        break
39        
40cap.release()
41cv2.destroyAllWindows()

webcam_display_window_and_oled.py

PYTHON
1...
2cap = cv2.VideoCapture(0)
3...