Skip to content

Instantly share code, notes, and snippets.

@blakev
Created May 2, 2021 00:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save blakev/9af1b0a4534d5544ea57313d632bfa41 to your computer and use it in GitHub Desktop.
Save blakev/9af1b0a4534d5544ea57313d632bfa41 to your computer and use it in GitHub Desktop.
Simple Python3 "driver" for the WaveShare PoE Pi HAT with LCD display.
import time
from typing import Optional, List
from PIL import Image
from PIL import ImageDraw
from PIL import ImageOps
from PIL import ImageFont
from smbus import SMBus
class LcdSSD1306:
FONT = ImageFont.truetype("fonts/type_writer.ttf", 7)
# https://www.dafont.com/type-writer.font
def __init__(self, width: int = 128, height: int = 32):
self._w = width
self._h = height
self._pages = int(self._h / 8)
self._addr = 0x3c # 60
self._bus = SMBus(1)
self.__setup()
def __setup(self):
"""Bootstrap the display."""
# yapf: disable
sequence = [
0xAE, 0x40, 0xB0, 0xC8, 0x81,
0xFF, 0xA1, 0xA6, 0xA8, 0x1F,
0xD3, 0x00, 0xD5, 0xF0, 0xD9,
0x22, 0xDA, 0x02, 0xDB, 0x49,
0x8D, 0x14, 0xAF
]
# yapf: enable
for cmd in sequence:
self.write_cmd(cmd)
self.clear_black()
def write_cmd(self, cmd: int):
self._bus.write_byte_data(self._addr, 0x00, cmd)
def write_ram(self, cmd: int):
self._bus.write_byte_data(self._addr, 0x40, cmd)
def _put_buffer(self, *, color: Optional[int] = None, buffer: Optional[List[int]] = None,):
"""Writes pixels to the screen."""
if color is None and buffer is None:
# no options
return
if color is not None and buffer:
# both options
return
if color is not None:
buffer = [color] * (self._h * self._w)
for p in range(self._pages):
self.write_cmd(0xB0 + p)
self.write_cmd(0x00)
self.write_cmd(0x10)
for c in range(self._w):
idx = c + self._w * p
new = buffer[idx]
self.write_ram(new)
def flash_image(self, image: Image, for_: float = 2.0, flip: bool = False):
"""Flashes a black and white image on the display for ``for_`` seconds."""
image_a = image.convert('L')
image_b = ImageOps.invert(image_a)
start = time.monotonic()
self.clear_white()
while time.monotonic() < start + for_:
self.put_image(image_a, flip=flip)
self.put_image(image_b, flip=flip)
self.put_image(image_a, flip=flip)
self.clear_black()
def write_lines(self, *lines, flip: bool = False, invert: bool = False):
"""Write lines of text to the display."""
if len(lines) == 1 and '\n' in lines[0]:
lines = lines[0].split('\n')
image = Image.new('L', (self._w, self._h), 'BLACK')
draw = ImageDraw.Draw(image)
for idx, line in enumerate(lines):
draw.text((0, (8 * idx)), str(line), font=self.FONT, fill='WHITE')
if invert:
image = ImageOps.invert(image)
self.put_image(image, flip=flip)
writelines = write_lines
def put_image(self, image: Image, flip: bool = False):
"""Puts a Pillow.Image buffer on the screen.
``flip`` will re-orient the image 180 degrees.
"""
# create a buffer for the contents that go on the screen
buffer = [0xff] * (self._pages * self._w)
# orient the image
if image.size == (self._h, self._w):
image = image.rotate(90, expand=True)
if flip:
image = image.rotate(180)
# convert image to monochromatic
mono = image.convert('1')
i_w, i_h = mono.size
pixels = mono.load()
# write the pixels to a horizontal screen
for y in range(i_h):
for x in range(i_w):
if pixels[x, y] == 0x00:
buffer[x + int(y / 8) * self._w] &= ~(1 << (y % 8))
self._put_buffer(buffer=buffer)
def clear_white(self):
"""Fill the screen with white pixels."""
self._put_buffer(color=0xFF)
def clear_black(self):
"""Fill the screen with black pixels."""
self._put_buffer(color=0x00)
def close(self):
"""Safely close the I2C bus instance."""
self._bus.close()
@blakev
Copy link
Author

blakev commented May 2, 2021

Link to the WaveShare Wiki.

Needs:

wget https://project-downloads.drogon.net/wiringpi-latest.deb
sudo dpkg -i wiringpi-latest.deb
gpio -v

wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.60.tar.gz
tar zxvf bcm2835-1.60.tar.gz 
cd bcm2835-1.60/
sudo ./configure
sudo make && sudo make check && sudo make install
sudo apt install libopenjp2-7-dev libtiff-dev
pip3 install --user  smbus pillow

Also need to install this font, https://www.dafont.com/type-writer.font

Usage:

screen = LcdSSD1306()
screen.flash_image(Image.open('extra/sale.png'), 3.0)
screen.writelines('one', 'two', 'three', 'four')
screen.close()

IMG_20210501_185256-small

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment