Updated guides have been published for the different sizes of eInk Breakouts, Shields, and FeatherWings:
Wiring
It's easy to use eInk breakouts with Python and the Adafruit CircuitPython EPD library. This library allows you to easily write Python code to control the display.
We'll cover how to wire the display to your Raspberry Pi. First assemble your display.
Since there's dozens of Linux computers/boards you can use we will show wiring for Raspberry Pi. For other platforms, please visit the guide for CircuitPython on Linux to see whether your platform is supported.
Connect the display as shown below to your Raspberry Pi.
- Raspberry Pi 3.3 to display VIN
- Raspberry Pi GND to display GND
- Raspberry Pi SCLK to display SCK
- Raspberry Pi MOSI to display MOSI
- Raspberry Pi GPIO CE0 to display ECS
- Raspberry Pi GPIO 22 to display D/C
- Raspberry Pi GPIO 27 to display RST
- Raspberry Pi GPIO 17 to display BUSY
Setup
You'll need to install the Adafruit_Blinka library that provides the CircuitPython support in Python. This may also require enabling SPI on your platform and verifying you are running Python 3. Since each platform is a little different, and Linux changes often, please visit the CircuitPython on Linux guide to get your computer ready!
Python Installation of EPD Library
Once that's done, from your command line run the following command:
sudo pip3 install adafruit-circuitpython-epd
If your default Python is version 3 you may need to run 'pip' instead. Just make sure you aren't trying to use CircuitPython on Python 2.x, it isn't supported!
If that complains about pip3 not being installed, then run this first to install it:
sudo apt-get install python3-pip
Download font5x8.bin
This library also requires a font file to run! You can download it below. Before continuing, make sure the folder you are running scripts from contains the font5x8.bin file.
DejaVu TTF Font
Raspberry Pi usually comes with the DejaVu font already installed, but in case it didn't, you can run the following to install it:
sudo apt-get install fonts-dejavu
This package was previously calls ttf-dejavu, so if you are running an older version of Raspberry Pi OS, it may be called that.
Pillow Library
Some of the examples also use PIL, the Python Imaging Library, to allow graphics and using text with custom fonts. There are several system libraries that PIL relies on, so installing via a package manager is the easiest way to bring in everything:
sudo apt-get install python3-pil
That's it. You should be ready to go.
Usage
To demonstrate the usage of the display we'll initialize it and draw some lines from the Python REPL.
Run the following code to import the necessary modules and set up the pin assignments:
import digitalio import busio import board from adafruit_epd.epd import Adafruit_EPD spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) ecs = digitalio.DigitalInOut(board.CE0) dc = digitalio.DigitalInOut(board.D22) rst = digitalio.DigitalInOut(board.D27) busy = digitalio.DigitalInOut(board.D17) srcs = None
If you're using the 1.54" Tri-Color display, run the following code to initialize the display:
from adafruit_epd.il0373 import Adafruit_IL0373
display = Adafruit_IL0373(152, 152, spi, cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
rst_pin=rst, busy_pin=busy)
If you're using the 2.13" Tri-Color display, run the following code to initialize the display:
from adafruit_epd.il0373 import Adafruit_IL0373
display = Adafruit_IL0373(104, 212, spi, cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
rst_pin=rst, busy_pin=busy)
If you're using the 2.9" Tri-Color display, run the following code to initialize the display:
from adafruit_epd.il0373 import Adafruit_IL0373
display = Adafruit_IL0373(128, 296, spi, cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
rst_pin=rst, busy_pin=busy)
If you're using the 2.7" Tri-Color display, run the following code to initialize the display:
from adafruit_epd.il91874 import Adafruit_IL91874
display = Adafruit_IL91874(176, 264, spi, cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
rst_pin=rst, busy_pin=busy)
If you're using the 4.2" Tri-Color display, run the following code to initialize the display:
from adafruit_epd.il0398 import Adafruit_IL0398
display = Adafruit_IL0398(400, 300, spi, cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
rst_pin=rst, busy_pin=busy)
If you're using the 1.54" HD Monochrome display, run the following code to initialize the display:
from adafruit_epd.ssd1608 import Adafruit_SSD1608
display = Adafruit_SSD1608(200, 200, spi, cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
rst_pin=rst, busy_pin=busy)
Tri-Color Example
Now we can clear the screens buffer and draw some shapes. Once we're done drawing, we need to tell the screen to update using the display() method.
display.fill(Adafruit_EPD.WHITE) display.fill_rect(20, 20, 50, 60, Adafruit_EPD.RED) display.hline(80, 30, 60, Adafruit_EPD.BLACK) display.vline(80, 30, 60, Adafruit_EPD.BLACK) display.display()
Your display will look something like this:
Monochrome Example
Now we can clear the screens buffer and draw some shapes. Once we're done drawing, we need to tell the screen to update using the display() method.
display.fill(Adafruit_EPD.WHITE) display.fill_rect(0, 0, 50, 60, Adafruit_EPD.BLACK) display.hline(80, 30, 60, Adafruit_EPD.BLACK) display.vline(80, 30, 60, Adafruit_EPD.BLACK) display.display()
Your eInk display should look similar to the image above, with a black rectangle instead of a red one.
That's all there is to drawing simple shapes with eInk displays and CircuitPython!
Tri-Color Bitmap Example
Here's a complete example of how to display a bitmap image on your display. Note that any .bmp image you want to display must be exactly the size of your display. We will be using the image below on the 1.54" display. Click the button below to download the image and save it as blinka.bmp on your Raspberry Pi.
Save the following code to your Raspberry Pi as epd_bitmap.py.
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
import busio
import digitalio
from adafruit_epd.ek79686 import Adafruit_EK79686
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il0398 import Adafruit_IL0398
from adafruit_epd.il91874 import Adafruit_IL91874
from adafruit_epd.ssd1608 import Adafruit_SSD1608
from adafruit_epd.ssd1675 import Adafruit_SSD1675
from adafruit_epd.ssd1680 import Adafruit_SSD1680
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
from adafruit_epd.ssd1681 import Adafruit_SSD1681
from adafruit_epd.ssd1683 import Adafruit_SSD1683
from adafruit_epd.uc8151d import Adafruit_UC8151D
from adafruit_epd.uc8179 import Adafruit_UC8179
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.D10)
dc = digitalio.DigitalInOut(board.D9)
srcs = digitalio.DigitalInOut(board.D7) # can be None to use internal memory
rst = digitalio.DigitalInOut(board.D11) # can be None to not use this pin
busy = digitalio.DigitalInOut(board.D12) # can be None to not use this pin
# give them all to our driver
print("Creating display")
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display
# display = Adafruit_SSD1680B(122, 250 # Newer 2.13" HD (Tri-color or mono) with GDEY0213B74
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
# display = Adafruit_EK79686(176, 264, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display
# display = Adafruit_UC8151D(128, 296, # 2.9" mono flexible display
# display = Adafruit_UC8179(648, 480, # 5.83" mono 648x480 display
# display = Adafruit_UC8179(800, 480, # 7.5" mono 800x480 display
# display = Adafruit_IL0373(128, 296, # 2.9" Tri-color display IL0373
# display = Adafruit_SSD1680(128, 296, # 2.9" Tri-color display SSD1680
# display = Adafruit_SSD1683(400, 300, # 4.2" 300x400 Tri-Color display
# display = Adafruit_IL0398(400, 300, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
""" display = Adafruit_UC8179(800, 480, # 7.5" tricolor 800x480 display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
tri_color = True
)"""
# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY OR!
# UC8179 5.83" or 7.5" displays
# uncomment these lines!
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
# IF YOU HAVE A 2.9" FLEXIBLE DISPLAY uncomment these lines!
# display.set_black_buffer(1, True)
# display.set_color_buffer(1, True)
display.rotation = 0
FILENAME = "blinka.bmp"
def read_le(s):
# as of this writting, int.from_bytes does not have LE support, DIY!
result = 0
shift = 0
for byte in bytearray(s):
result += byte << shift
shift += 8
return result
class BMPError(Exception):
pass
def display_bitmap(epd, filename):
try:
f = open(filename, "rb")
except OSError:
print("Couldn't open file")
return
print("File opened")
try:
if f.read(2) != b"BM": # check signature
raise BMPError("Not BitMap file")
bmpFileSize = read_le(f.read(4))
f.read(4) # Read & ignore creator bytes
bmpImageoffset = read_le(f.read(4)) # Start of image data
headerSize = read_le(f.read(4))
bmpWidth = read_le(f.read(4))
bmpHeight = read_le(f.read(4))
flip = True
print(
"Size: %d\nImage offset: %d\nHeader size: %d"
% (bmpFileSize, bmpImageoffset, headerSize)
)
print("Width: %d\nHeight: %d" % (bmpWidth, bmpHeight))
if read_le(f.read(2)) != 1:
raise BMPError("Not singleplane")
bmpDepth = read_le(f.read(2)) # bits per pixel
print("Bit depth: %d" % (bmpDepth))
if bmpDepth != 24:
raise BMPError("Not 24-bit")
if read_le(f.read(2)) != 0:
raise BMPError("Compressed file")
print("Image OK! Drawing...")
rowSize = (bmpWidth * 3 + 3) & ~3 # 32-bit line boundary
for row in range(bmpHeight): # For each scanline...
if flip: # Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize
else: # Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize
# print ("seek to %d" % pos)
f.seek(pos)
rowdata = f.read(3 * bmpWidth)
for col in range(bmpWidth):
b, g, r = rowdata[3 * col : 3 * col + 3] # BMP files store RGB in BGR
if r < 0x80 and g < 0x80 and b < 0x80:
epd.pixel(col, row, Adafruit_EPD.BLACK)
elif r >= 0x80 and g >= 0x80 and b >= 0x80:
pass # epd.pixel(row, col, Adafruit_EPD.WHITE)
elif r >= 0x80:
epd.pixel(col, row, Adafruit_EPD.RED)
except OSError:
print("Couldn't read file")
except BMPError as e:
print("Failed to parse BMP: " + e.args[0])
finally:
f.close()
print("Finished drawing")
# clear the buffer
display.fill(Adafruit_EPD.WHITE)
display_bitmap(display, FILENAME)
display.display()
Before running it, we need to change a few pin definitions though. Find the section of code that looks like this:
ecs = digitalio.DigitalInOut(board.D10) dc = digitalio.DigitalInOut(board.D9) srcs = digitalio.DigitalInOut(board.D7) # can be None to use internal memory rst = digitalio.DigitalInOut(board.D11) # can be None to not use this pin busy = digitalio.DigitalInOut(board.D12) # can be None to not use this pin
Change the pins to the following to match the wiring on the Raspberry Pi:
ecs = digitalio.DigitalInOut(board.CE0) dc = digitalio.DigitalInOut(board.D22) srcs = None rst = digitalio.DigitalInOut(board.D27) busy = digitalio.DigitalInOut(board.D17)
Now go to the command prompt on your Raspberry Pi and run the script with the following command:
python3 epd_bitmap.py
After a few seconds, your display should show this image:
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
import busio
import digitalio
from adafruit_epd.ek79686 import Adafruit_EK79686
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.il0373 import Adafruit_IL0373, Adafruit_IL0373_213_Flex_Mono
from adafruit_epd.il0398 import Adafruit_IL0398
from adafruit_epd.il91874 import Adafruit_IL91874
from adafruit_epd.jd79661 import Adafruit_JD79661
from adafruit_epd.ssd1608 import Adafruit_SSD1608
from adafruit_epd.ssd1675 import Adafruit_SSD1675
from adafruit_epd.ssd1680 import Adafruit_SSD1680
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
from adafruit_epd.ssd1681 import Adafruit_SSD1681
from adafruit_epd.ssd1683 import Adafruit_SSD1683
from adafruit_epd.uc8151d import Adafruit_UC8151D
from adafruit_epd.uc8179 import Adafruit_UC8179
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.D12)
dc = digitalio.DigitalInOut(board.D11)
srcs = digitalio.DigitalInOut(board.D10) # can be None to use internal memory
rst = digitalio.DigitalInOut(board.D9) # can be None to not use this pin
busy = digitalio.DigitalInOut(board.D5) # can be None to not use this pin
# give them all to our drivers
print("Creating display")
# display = Adafruit_JD79661(122, 150, # 2.13" Quad-color display
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display
# display = Adafruit_SSD1680B(122, 250 # 2.13" HD (Tri-color or mono) with GDEY0213B74
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
# display = Adafruit_EK79686(176, 264, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display
# display = Adafruit_UC8151D(128, 296, # 2.9" mono flexible display
# display = Adafruit_UC8179(648, 480, # 5.83" mono 648x480 display
# display = Adafruit_UC8179(800, 480, # 7.5" mono 800x480 display
# display = Adafruit_IL0373(128, 296, # 2.9" Tri-color display IL0373
# display = Adafruit_IL0373_213_Flex_Mono(104, 212,# 2.13" mono flex display
# display = Adafruit_SSD1680(128, 296, # 2.9" Tri-color display SSD1680
# display = Adafruit_SSD1683(400, 300, # 4.2" 300x400 Tri-Color display
# display = Adafruit_IL0398(400, 300, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
""" display = Adafruit_UC8179(800, 480, # 7.5" tricolor 800x480 display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
tri_color = True
)"""
# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY OR!
# UC8179 5.83" or 7.5" monochrome displays
# uncomment these lines!
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
# IF YOU HAVE A 2.9" FLEXIBLE DISPLAY uncomment these lines!
# display.set_black_buffer(1, True)
# display.set_color_buffer(1, True)
display.rotation = 1
if type(display) == Adafruit_JD79661:
WHITE = Adafruit_JD79661.WHITE
BLACK = Adafruit_JD79661.BLACK
RED = Adafruit_JD79661.RED
YELLOW = Adafruit_JD79661.YELLOW
else:
WHITE = Adafruit_EPD.WHITE
BLACK = Adafruit_EPD.BLACK
RED = Adafruit_EPD.RED
# clear the buffer
print("Clear buffer")
display.fill(WHITE)
display.pixel(10, 100, BLACK)
print("Draw Rectangles")
display.fill_rect(5, 5, 10, 10, RED)
display.rect(0, 0, 20, 30, BLACK)
print("Draw lines")
if type(display) == Adafruit_JD79661:
display.line(0, 0, display.width - 1, display.height - 1, YELLOW)
display.line(0, display.height - 1, display.width - 1, 0, YELLOW)
else:
display.line(0, 0, display.width - 1, display.height - 1, BLACK)
display.line(0, display.height - 1, display.width - 1, 0, RED)
print("Draw text")
display.text("hello world", 25, 10, BLACK)
display.display()
Image Drawing with Pillow
In this image, we will use Pillow to resize and crop the image automatically and draw it the the ePaper Display. Pillow is really powerful and with it you can open and render additional file formats such as PNG or JPG. Let's start with downloading a PNG of blinka that has been adjusted down to 3 colors so it prints nicely on an ePaper Display. We are using PNG for this because it is a lossless format and won't introduce unexpected colors in.
Make sure you save it as blinka.png and place it in the same folder as your script. Here's the code we'll be loading onto the Raspberry Pi. Go ahead and copy it onto your Raspberry Pi and save it as epd_pillow_image.py. We'll go over the interesting parts.
# SPDX-FileCopyrightText: 2019 Melissa LeBlanc-Williams for Adafruit Industries
# SPDX-License-Identifier: MIT
"""
Image resizing and drawing using the Pillow Library. For the image, check out the
associated Adafruit Learn guide at:
https://learn.adafruit.com/adafruit-eink-display-breakouts/python-code
"""
import board
import busio
import digitalio
from PIL import Image
from adafruit_epd.ek79686 import Adafruit_EK79686
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il0398 import Adafruit_IL0398
from adafruit_epd.il91874 import Adafruit_IL91874
from adafruit_epd.jd79661 import Adafruit_JD79661
from adafruit_epd.ssd1608 import Adafruit_SSD1608
from adafruit_epd.ssd1675 import Adafruit_SSD1675
from adafruit_epd.ssd1680 import Adafruit_SSD1680
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
from adafruit_epd.ssd1681 import Adafruit_SSD1681
from adafruit_epd.ssd1683 import Adafruit_SSD1683
from adafruit_epd.uc8151d import Adafruit_UC8151D
from adafruit_epd.uc8179 import Adafruit_UC8179
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.CE0)
dc = digitalio.DigitalInOut(board.D22)
srcs = None
rst = digitalio.DigitalInOut(board.D27)
busy = digitalio.DigitalInOut(board.D17)
# give them all to our driver
# display = Adafruit_JD79661(122, 150, # 2.13" Quad-color display
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color or mono display
# display = Adafruit_SSD1680B(122, 250 # Newer 2.13" HD (Tri-color or mono) with GDEY0213B74
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
# display = Adafruit_EK79686(176, 264, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display
# display = Adafruit_UC8151D(128, 296, # 2.9" mono flexible display
# display = Adafruit_UC8179(648, 480, # 5.83" mono 648x480 display
# display = Adafruit_UC8179(800, 480, # 7.5" mono 800x480 display
# display = Adafruit_IL0373(128, 296, # 2.9" Tri-color display IL0373
# display = Adafruit_SSD1680(128, 296, # 2.9" Tri-color display SSD1680
# display = Adafruit_SSD1683(400, 300, # 4.2" 300x400 Tri-Color display
# display = Adafruit_IL0398(400, 300, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
""" display = Adafruit_UC8179(800, 480, # 7.5" tricolor 800x480 display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
tri_color = True
)"""
# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY OR!
# UC8179 5.83" or 7.5" displays
# uncomment these lines!
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
# IF YOU HAVE A 2.9" FLEXIBLE DISPLAY uncomment these lines!
# display.set_black_buffer(1, True)
# display.set_color_buffer(1, True)
display.rotation = 1
image = Image.open("blinka.png")
# Scale the image to the smaller screen dimension
image_ratio = image.width / image.height
screen_ratio = display.width / display.height
if screen_ratio < image_ratio:
scaled_width = image.width * display.height // image.height
scaled_height = display.height
else:
scaled_width = display.width
scaled_height = image.height * display.width // image.width
image = image.resize((scaled_width, scaled_height), Image.BICUBIC)
# Crop and center the image
x = scaled_width // 2 - display.width // 2
y = scaled_height // 2 - display.height // 2
image = image.crop((x, y, x + display.width, y + display.height)).convert("RGB")
# Convert to Monochrome and Add dithering
# image = image.convert("1").convert("L")
if type(display) == Adafruit_JD79661:
# Create a palette with the 4 colors: Black, White, Red, Yellow
# The palette needs 768 values (256 colors × 3 channels)
palette = []
# We'll map the 256 palette indices to our 4 colors
# 0-63: Black, 64-127: Red, 128-191: Yellow, 192-255: White
for i in range(256):
if i < 64:
palette.extend([0, 0, 0]) # Black
elif i < 128:
palette.extend([255, 0, 0]) # Red
elif i < 192:
palette.extend([255, 255, 0]) # Yellow
else:
palette.extend([255, 255, 255]) # White
# Create a palette image
palette_img = Image.new("P", (1, 1))
palette_img.putpalette(palette)
# Optional: Enhance colors before dithering for better results
# from PIL import ImageEnhance
# enhancer = ImageEnhance.Color(image)
# image = enhancer.enhance(1.5) # Increase color saturation
# Quantize the image using Floyd-Steinberg dithering
image = image.quantize(palette=palette_img, dither=Image.FLOYDSTEINBERG)
# Convert back to RGB for the display driver
image = image.convert("RGB")
# Display image.
display.image(image)
display.display()
So we start with our usual imports including a couple of Pillow modules and the ePaper display drivers.
import digitalio import busio import board from PIL import Image, ImageDraw from adafruit_epd.il0373 import Adafruit_IL0373 from adafruit_epd.il91874 import Adafruit_IL91874 from adafruit_epd.il0398 import Adafruit_IL0398 from adafruit_epd.ssd1608 import Adafruit_SSD1608 from adafruit_epd.ssd1675 import Adafruit_SSD1675
That is followed by initializing the SPI bus and defining a few pins here. The reason we chose these is because they allow you to use the same code with the EPD bonnets if you chose to do so.
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) ecs = digitalio.DigitalInOut(board.CE0) dc = digitalio.DigitalInOut(board.D22) srcs = None rst = digitalio.DigitalInOut(board.D27) busy = digitalio.DigitalInOut(board.D17)
We wanted to make these examples work on as many displays as possible with very few changes. The 2.13" Tri-color display is selected by default. For other displays, go ahead and comment out the following lines:
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
and uncomment the line appropriate for your display.
#display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
#display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
#display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
#display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display
#display = Adafruit_IL0373(128, 296, # 2.9" Tri-color display
#display = Adafruit_IL0398(400, 300, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy
)
Uncomment the next two lines if you have a flexible display. This tells the library to change a couple of settings so that it is writing the correct colors to the correct places.
# IF YOU HAVE A FLEXIBLE DISPLAY (2.13" or 2.9") uncomment these lines! #display.set_black_buffer(1, False) #display.set_color_buffer(1, False)
Next we tall the display the rotation setting we want to use. This can be a value between 0-3.
display.rotation = 1
Next we open the Blinka image, which we've named blinka.png, which assumes it is in the same directory that you are running the script from. Feel free to change it if it doesn't match your configuration.
image = Image.open("blinka.png")
Here's where it starts to get interesting. We want to scale the image so that it matches either the width or height of the display, depending on which is smaller, so that we have some of the image to chop off when we crop it. So we start by calculating the width to height ration of both the display and the image. If the height is the closer of the dimensions, we want to match the image height to the display height and let it be a bit wider than the display. Otherwise, we want to do the opposite.
Once we've figured out how we're going to scale it, we pass in the new dimensions and using a Bicubic rescaling method, we reassign the newly rescaled image back to image. Pillow has quite a few different methods to choose from, but Bicubic does a great job and is reasonably fast.
Nearest actually gives a little better result with the Tri-color eInks, but loses detail with displaying a color image on the monochrome display, so we decided to go with the best balance.
image_ratio = image.width / image.height
screen_ratio = display.width / display.height
if screen_ratio < image_ratio:
scaled_width = image.width * display.height // image.height
scaled_height = display.height
else:
scaled_width = display.width
scaled_height = image.height * display.width // image.width
image = image.resize((scaled_width, scaled_height), Image.BICUBIC)
Next we want to figure the starting x and y points of the image where we want to begin cropping it so that it ends up centered. We do that by using a standard centering function, which is basically requesting the difference of the center of the display and the center of the image. Just like with scaling, we replace the image variable with the newly cropped image.
x = scaled_width // 2 - display.width // 2 y = scaled_height // 2 - display.height // 2 image = image.crop((x, y, x + display.width, y + display.height))
Finally, we take our image, draw it to the frame buffer and display it. At this point, the image should have the exact same dimensions at the display and fill it completely.
display.image(image) display.display()
Now go to the command prompt on your Raspberry Pi and run the script with the following command:
python3 epd_pillow_image.py
After a few seconds, your display should show this image:
Here's what it looks like on a monochrome display:
Drawing Shapes and Text with Pillow
In the next example, we'll take a look at drawing shapes and text. This is very similar to the displayio example, but it uses Pillow instead. Go ahead and copy it onto your Raspberry Pi and save it as epd_pillow_demo.py. Here's the code for that.
# SPDX-FileCopyrightText: 2019 Melissa LeBlanc-Williams for Adafruit Industries
# SPDX-License-Identifier: MIT
"""
ePaper Display Shapes and Text demo using the Pillow Library.
"""
import board
import busio
import digitalio
from PIL import Image, ImageDraw, ImageFont
from adafruit_epd.ek79686 import Adafruit_EK79686
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il0398 import Adafruit_IL0398
from adafruit_epd.il91874 import Adafruit_IL91874
from adafruit_epd.jd79661 import Adafruit_JD79661
from adafruit_epd.ssd1608 import Adafruit_SSD1608
from adafruit_epd.ssd1675 import Adafruit_SSD1675
from adafruit_epd.ssd1680 import Adafruit_SSD1680
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
from adafruit_epd.ssd1681 import Adafruit_SSD1681
from adafruit_epd.ssd1683 import Adafruit_SSD1683
from adafruit_epd.uc8151d import Adafruit_UC8151D
from adafruit_epd.uc8179 import Adafruit_UC8179
# First define some color constants
WHITE = (0xFF, 0xFF, 0xFF)
BLACK = (0x00, 0x00, 0x00)
RED = (0xFF, 0x00, 0x00)
# Next define some constants to allow easy resizing of shapes and colors
BORDER = 20
FONTSIZE = 24
BACKGROUND_COLOR = BLACK
FOREGROUND_COLOR = WHITE
TEXT_COLOR = RED
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.CE0)
dc = digitalio.DigitalInOut(board.D22)
srcs = None
rst = digitalio.DigitalInOut(board.D27)
busy = digitalio.DigitalInOut(board.D17)
# give them all to our driver
# display = Adafruit_JD79661(122, 150, # 2.13" Quad-color display
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color or mono display
# display = Adafruit_SSD1680B(122, 250 # Newer 2.13" HD (Tri-color or mono) with GDEY0213B74
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
# display = Adafruit_EK79686(176, 264, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display
# display = Adafruit_UC8151D(128, 296, # 2.9" mono flexible display
# display = Adafruit_UC8179(648, 480, # 5.83" mono 648x480 display
# display = Adafruit_UC8179(800, 480, # 7.5" mono 800x480 display
# display = Adafruit_IL0373(128, 296, # 2.9" Tri-color display IL0373
# display = Adafruit_SSD1680(128, 296, # 2.9" Tri-color display SSD1680
# display = Adafruit_SSD1683(400, 300, # 4.2" 300x400 Tri-Color display
# display = Adafruit_IL0398(400, 300, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
""" display = Adafruit_UC8179(800, 480, # 7.5" tricolor 800x480 display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
tri_color = True
)"""
# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY OR!
# UC8179 5.83" or 7.5" displays
# uncomment these lines!
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
# IF YOU HAVE A 2.9" FLEXIBLE DISPLAY uncomment these lines!
# display.set_black_buffer(1, True)
# display.set_color_buffer(1, True)
display.rotation = 1
image = Image.new("RGB", (display.width, display.height))
# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)
# Draw a filled box as the background
draw.rectangle((0, 0, display.width - 1, display.height - 1), fill=BACKGROUND_COLOR)
# Draw a smaller inner foreground rectangle
draw.rectangle(
(BORDER, BORDER, display.width - BORDER - 1, display.height - BORDER - 1),
fill=FOREGROUND_COLOR,
)
# Load a TTF Font
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", FONTSIZE)
# Draw Some Text
text = "Hello World!"
(font_width, font_height) = font.getsize(text)
draw.text(
(display.width // 2 - font_width // 2, display.height // 2 - font_height // 2),
text,
font=font,
fill=TEXT_COLOR,
)
# Display image.
display.image(image)
display.display()
Just like in the last example, we'll do our imports, but this time we're including the ImageDraw and ImageFont Pillow modules because we'll be drawing some text this time.
import digitalio import busio import board from PIL import Image, ImageDraw, ImageFont from adafruit_epd.il0373 import Adafruit_IL0373 from adafruit_epd.il91874 import Adafruit_IL91874 from adafruit_epd.il0398 import Adafruit_IL0398 from adafruit_epd.ssd1608 import Adafruit_SSD1608 from adafruit_epd.ssd1675 import Adafruit_SSD1675
Next we define some colors that can be used with Pillow.
WHITE = (0xFF, 0xFF, 0xFF) BLACK = (0x00, 0x00, 0x00) RED = (0xFF, 0x00, 0x00)
After that, we create some parameters that are easy to change. If you had a smaller display for instance, you could reduce the FONTSIZE and BORDER parameters. The BORDER will be the size in pixels of the green border between the edge of the display and the inner purple rectangle. The FONTSIZE will be the size of the font in points so that we can adjust it easily for different displays. You could play around with the colors as well. One thing to note is that on monochrome displays, the RED will show up as BLACK.
BORDER = 20 FONTSIZE = 24 BACKGROUND_COLOR = BLACK FOREGROUND_COLOR = WHITE TEXT_COLOR = RED
After that, the initializer and rotation sections are exactly the same as in the previous example. If you have are using a different display than the 2.13" Tri-color, go ahead and adjust your initializer as explained in the previous example. After that, we will create an image with our dimensions and use that to create a draw object. The draw object will have all of our drawing functions.
image = Image.new('RGB', (display.width, display.height))
draw = ImageDraw.Draw(image)
Next we clear whatever is on the screen by drawing a rectangle using the BACKGROUND_COLOR that takes up the full screen.
draw.rectangle((0, 0, display.width, display.height), fill=BACKGROUND_COLOR)
Next we will draw an inner rectangle using the FOREGROUND_COLOR. We use the BORDER parameter to calculate the size and position that we want to draw the rectangle.
draw.rectangle((BORDER, BORDER, display.width - BORDER - 1, display.height - BORDER - 1),
fill=FOREGROUND_COLOR)
Next we'll load a TTF font. The DejaVuSans.ttf font should come preloaded on your Pi in the location in the code. We also make use of the FONTSIZE parameter that we discussed earlier.
font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', FONTSIZE)
Now we draw the text Hello World onto the center of the display. You may recognize the centering calculation was the same one we used to center crop the image in the previous example. In this example though, we get the font size values using the getsize() function of the font object.
text = "Hello World!"
(font_width, font_height) = font.getsize(text)
draw.text((display.width//2 - font_width//2, display.height//2 - font_height//2),
text, font=font, fill=TEXT_COLOR)
Finally, just like before, we display the image.
display.image(image) display.display()
Now go to the command prompt on your Raspberry Pi and run the script with the following command:
python3 epd_pillow_demo.py
After a few seconds, your display should show this image:
Page last edited January 22, 2025
Text editor powered by tinymce.