Maker.io main logo

Adafruit 1.54 eInk Display Breakouts

31

2023-01-17 | By Adafruit Industries

License: See Original Project Displays

Courtesy of Adafruit

Guide by M. LeBlanc-Williams

Overview

Easy e-paper finally comes to microcontrollers, with these breakouts, ‎shields, and friends that are designed to make it a breeze to add a ‎tricolor eInk display. Chances are you've seen one of those new-‎fangled 'e-readers' like the Kindle or Nook. They have gigantic ‎electronic paper 'static' displays - that means the image stays on the ‎display even when power is completely disconnected. The image is also ‎high contrast and very daylight readable. It really does look just like ‎printed paper!‎

paper_1

We've liked these displays for a long time, but they were never ‎designed for makers to use. Finally, we decided to make our own!‎

display_2

We have multiple 1.54" EPD displays:‎

tricolor_3

Using our Arduino library, you can create a 'frame buffer' with what ‎pixels you want to have activated and then write that out to the display. ‎Most simple breakouts leave it at that. But if you do the math, using ‎even the smallest 1.54" display: 152 x 152 pixels x 2 colors = 5.7 ‎KBytes. Which won't fit into many microcontroller memories. Heck, ‎even if you do have 32KB of RAM, why waste 6KB?‎

So, we did you a favor and tossed a small SRAM chip on the ‎back. This chip shares the SPI port the eInk display uses, so you only ‎need one extra pin. And no more frame-buffering! You can use the ‎SRAM to set up whatever you want to display, then shuffle data ‎from SRAM to eInk when you're ready. The library we wrote does all ‎the work for you, you can just interface with it as if it were an Adafruit_GFX ‎compatible display.‎

chip_4

 

For ultra-low power usages, the onboard 3.3V regulator has the Enable ‎pin brought out so you can shut down the power to the SRAM, MicroSD ‎and display.‎

We even added on a MicroSD socket so you can store images, text files, ‎whatever you like to display. Everything is 3 or 5V logic safe so you can ‎use it with any and all microcontrollers.‎

Pinouts

Even though we have multiple 1.54" EPD displays, the pinouts, and ‎dimensions are the same for all of them!‎

This e-Paper display uses SPI to receive image data. Since the display is ‎SPI, it was easy to add two more SPI devices to share the bus - an SPI ‎SRAM chip and SPI-driven SD card holder. There's quite a few pins and ‎a variety of possible combinations for control depending on your needs.‎

eink_5

Power Pins

pins_6

  • 3-5V / Vin - this is the power pin, connect to 3-5VDC - it has ‎reverse polarity protection but try to wire it right!‎

  • ‎3.3V out - this is the 3.3V output from the onboard regulator, ‎you can 'borrow' about 100mA if you need to power some other ‎‎3.3V logic devices

  • GND - this is the power and signal ground pin

  • ENAble - this pin is all the way on the right. It is connected to ‎the enable pin on the onboard regulator that powers everything. ‎If you want to really have the lowest possible power draw, pull ‎this pin low! Note that if you do so you will cut power to the eInk ‎display but also the SPI RAM (thus erasing it) and the SD card ‎‎(which means you'll have to re-initialize it when you re-power.)‎

Data Control Pins

data_7

  • SCK - this is the SPI clock input pin, required for e-Ink, SRAM ‎and SD card

  • MISO - this is the SPI Microcontroller In Serial Out pin, its used ‎for the SD card and SRAM. It isn't used for the e-Ink display ‎which is write-only, however you'll likely be using the SRAM to ‎buffer the display so connect this one too!‎

  • MOSI - this is the SPI Microcontroller Out Serial In pin, it is used ‎to send data from the microcontroller to the SD card, SRAM, and ‎e-Ink display

  • ECS - this is the E-Ink Chip Select, required for controlling the ‎display

  • D/C - this is the e-Ink Data/Command pin, required for ‎controlling the display

  • SRCS - this is the SRAM Chip Select, required for communicating ‎with the onboard RAM chip

  • SDCS - this is the SD card Chip Select, required for ‎communicating with the onboard SD card holder. You can leave ‎this disconnected if you aren't going to access SD cards

  • RST - this is the E-Ink ReSeT pin, you may be able to share this ‎with your microcontroller reset pin but if you can, connect it to a ‎digital pin

  • BUSY - this is the e-Ink busy detect pin, and is optional if you ‎don't want to connect the pin (in which case the code will just ‎wait an approximate number of seconds)‎

Assembly

Assembly_8

Assembly

Cut the header down to length if necessary. It will be easier to solder if ‎you insert it into a breadboard - long pins down.

Assembly

Add the E-Ink Display‎ ‎

Place the board over the pins so that the short pins poke through the ‎top of the breakout pads.‎

Assembly

And Solder!‎‎ ‎

Be sure to solder all pins for reliable electrical contact. ‎ ‎

(For tips on soldering, be sure to check out the Guide to Excellent ‎Soldering).

Assembly

Assembly

Assembly

OK, you're done!‎

OK you are done

Wiring

Breakout Wiring

Though it looks like a lot of connections, wiring up an eInk breakout is ‎pretty straightforward! Below shows using hardware SPI to connect it to ‎an Adafruit Metro M4.‎

  • Vin connects to the microcontroller board's 5V or 3.3V power ‎supply pin

  • GND connects to ground

  • CLK connects to SPI clock. It's easiest to connect it to pin 3 of ‎the ICSP header

  • MOSI connects to SPI MOSI. It's easiest to connect it to pin 4 of ‎the ICSP header

  • MISO connects to SPI MISO. It's easiest to connect it to pin 1 of ‎the ICSP header

  • ECS connects to our e-Ink Chip Select pin. We'll be using Digital ‎‎9

  • D/C connects to our e-Ink data/command select pin. We'll be ‎using Digital 10

  • SRCS connects to our SRAM Chip Select pin. We'll be ‎using Digital 6

  • RST connects to our e-Ink reset pin. We'll be using Digital 8‎

  • BUSY connects to our e-Ink busy pin. We'll be using Digital 7‎

  • SDCS connects to our SD Card Chip Select pin. We'll be ‎using Digital 5‎

fritzing_15

Python Wiring

  • 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

fritzing2_16

Usage & Expectations

usage_17

One thing to remember with these small e-Ink screens is that it’s very ‎slow compared to OLEDs, TFTs, or even 'memory displays'. It will take ‎may seconds to fully erase and replace an image.‎

There's also a recommended limit on refreshing - you shouldn't ‎refresh or change the display more than every 3 minutes (180 ‎seconds).

You don't have to refresh often, but with tricolor displays, the larger ‎red ink dots will slowly rise, turning the display pinkish instead of ‎white background. To keep the background color clear and pale, ‎refresh once a day.‎

Do not update more than once every 180 seconds or you may ‎permanently damage the display.

Arduino Setup

To use the display, you will need to install the Adafruit_EPD library (code ‎on our github repository). It is available from the Arduino library manager, ‎so we recommend using that.‎

From the IDE open up the library manager...‎

setup_18

And type in adafruit EPD to locate the library. Click Install.‎

library_19

If you would like to draw bitmaps, do the same with adafruit ‎ImageReader, click Install.‎

bitmaps_20

Do the same to install the latest adafruit GFX library, click Install.

install_21

If using an earlier version of the Arduino IDE (pre-1.8.10), locate and ‎install Adafruit_BusIO (newer versions handle this prerequisite ‎automatically.)

Arduino Usage

Here is where the differences in the tricolor/monochrome and ‎chipset/dimensions start mattering. Check carefully to make sure you ‎are running the right example and creating the matching ThinkInk type ‎for your display or you won’t see anything happen on the EPD (or the ‎image may be really weird looking.)‎

1.54" Monochrome 200x200 Pixel Display‎

For the 200 x 200 monochrome display we will run a monochrome demo.‎

Adafruit 1.54" Monochrome eInk / ePaper Display with SRAM

Open up File→Examples→Adafruit_EPD→ThinkInk_mono

open_22

1.54" Tricolor 152x152 OR 200x200 Pixel ‎Display

For the 152x152 OR 200x200 Tricolor display, we will run the tricolor ‎demo.‎

Adafruit 1.54" 152x152 Tricolor eInk / ePaper Display with SRAM

Adafruit 1.54" Tricolor eInk / ePaper 200x200 Display with SRAM

Open up File→Examples→Adafruit_EPD→ThinkInk_tricolor

file_23

Configure Pins

No matter what display you have, you will need to verify that your pins ‎match your wiring. At the top of the sketch find the lines that look like:‎

Download File

Copy Code
#define EPD_DC      10
#define EPD_CS      9
#define SRAM_CS     6
#define EPD_RESET   8 // can set to -1 and share with microcontroller Reset!
#define EPD_BUSY    7 // can set to -1 to not use a pin (will wait a fixed delay)

If you wired the display differently than on the wiring page, adjust the ‎pin numbers accordingly.‎

Configure Display Type & Size

Find the part of the script where you can pick which display is going to ‎be used. The eInk displays are made up a combination of a Chipset and ‎a Film in different sizes. We have narrowed it down to just a few ‎choices between the size of the display, chipset, and film based on ‎available combinations. In the sketch, we have sorted it by size, so it's ‎easy to find your display.‎

You will need to uncomment the appropriate initializer and leave any ‎other type commented.‎

For the 1.54" 200x200 Monochrome breakout you will ‎use ThinkInk_154_Mono_D27 display initializer.

‎For the 1.54" 152x152 Tricolor breakout, you will use ‎the ThinkInk_154_Tricolor_Z17 display initializer.‎

For the 1.54" 200x200 Tricolor breakout, you will use ‎the ThinkInk_154_Tricolor_Z90 display initializer.‎

For example, for the monochrome 200x200, uncomment this line, and ‎comment any other line that is creating a ThinkInk display object.‎

Download File

Copy Code
// 1.54" Monochrome displays with 200x200 pixels and SSD1608 chipset
ThinkInk_154_Mono_D27 display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY);

Upload Sketch

Go ahead and upload the sketch to your board. Once it is done ‎uploading, open the Serial Monitor.‎

The display should start running a series of monochrome tests.‎

display_24

einkepaper_25

Arduino Bitmaps

bitmaps_26

Not only can you draw shapes, but you can also load images from the ‎SD card, perfect for static images!‎

The 1.54" Monochrome display can show a max. of 200x200 pixels, ‎and the Standard 1.54" Tri-Color display can show a max. of 152x152 ‎pixels, and the HD Tri-Color version can show a max. of 200x200 ‎pixels. Let's use this Blinka bitmap for our demo. Select the one that is ‎the correct size:‎

Download Monochrome blinka.bmp

Download Tricolor blinka.bmp

Download HD Tricolor blinka.bmp

Download the blinka.bmp file and place it into the base directory of a ‎microSD card and insert it into the microSD socket in the breakout.‎

Plug the MicroSD card into the display. You may want to try the SD ‎library examples before continuing, especially one that lists all the ‎files on the SD card

Open ‎the file→examples→Adafruit_ImageReader→ThinkInkDisplays example.

imagereader_27

Upload to your board and you should see an image of Blinka appear.‎

upload_28

If you want to later use your own image, use an image editing tool and ‎crop your image to no larger than 152 pixels wide and 152 pixels high ‎on the standard display and no larger than 200 pixels wide and 200 ‎pixels high on the HD display. Save it as a 24-bit color BMP file - it ‎must be 24-bit color format to work, even if it was originally a 16-bit ‎color image - because of the way BMPs are stored and displayed!‎

CircuitPython Usage

Here is where the differences in the tricolor/monochrome and ‎chipset/dimensions start mattering. Check carefully to make sure you ‎are running the right example and creating the matching library type ‎for your display or you won’t see anything happen on the EPD (or the ‎image may be really weird looking.)‎

CircuitPython eInk displayio Library Installation

To use displayio, you will need to install the appropriate library for your ‎display. ‎

First make sure you are running the latest version of Adafruit ‎CircuitPython for your board. You will need the latest version of ‎CircuitPython.‎

Next, you'll need to install the necessary libraries to use the hardware-‎‎-carefully follow the steps to find and install these libraries ‎from Adafruit's CircuitPython library bundle. Our introduction guide has a ‎great page on how to install the library bundle for both express and non-‎express boards.‎

You will need to copy the appropriate displayio driver from the ‎bundle lib folder to a lib folder on your CIRCUITPY drive. The displayio ‎driver contains the initialization codes specific to your display that are ‎needed to for it to work. Since there is more than one driver, you will ‎need to copy the correct file over. Here is a list of each of the displays ‎and the correct driver for that display.‎

To use the eInk displays with displayio, you will need to use the latest ‎version of CircuitPython and a board that can fit `displayio`. See the ‎Support Matrix to determine if `displayio` is available on a given board: ‎https://circuitpython.readthedocs.io/en/latest/shared-‎bindings/support_matrix.html

Adafruit_CircuitPython_SSD1608‎

The 200x200 monochrome display with SSD1608 driver uses ‎the Adafruit_CircuitPython_SSD1608 library. Copy ‎the adafruit_ssd1608.mpy file from the bundle to the lib folder on ‎your CIRCUITPY drive.‎

Adafruit 1.54" Monochrome eInk / ePaper Display with SRAM

Adafruit_CircuitPython_IL0373‎

The 152x152 Tricolor display with IL0373 uses ‎the Adafruit_CircuitPython_ILI0373 library. Copy ‎the adafruit_il0373.mpy file from the bundle to the lib folder on ‎your CIRCUITPY drive.‎

Adafruit 1.54" 152x152 Tricolor eInk / ePaper Display with SRAM

Adafruit_CircuitPython_SSD1681

The 200x200 Tricolor display with SSD1681 driver uses ‎the Adafruit_CircuitPython_SSD1681 library. Copy ‎the adafruit_ssd1681.mpy file from the bundle to the lib folder on ‎your CIRCUITPY drive.‎

Adafruit 1.54" Tricolor eInk / ePaper 200x200 Display with SRAM

Image File

To show you how to use the eInk with displayio, we'll show you how to ‎draw a bitmap onto it. First start by downloading display-ruler.bmp.‎

Download display-ruler.bmp

Copy display-ruler.bmp into the root directory of ‎your CIRCUITPY drive.‎

Monochrome Display Usage

In the examples folder for your SSD1608 displayio driver, there should ‎be a test for your display which we have listed here:‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

"""Simple test script for 1.54" 200x200 monochrome display.

Supported products:
  * Adafruit 1.54" Monochrome ePaper Display Breakout
    * https://www.adafruit.com/product/4196
  """

import time
import board
import displayio
import adafruit_ssd1608

displayio.release_displays()

# This pinout works on a Feather M4 and may need to be altered for other boards.
spi = board.SPI()  # Uses SCK and MOSI
epd_cs = board.D9
epd_dc = board.D10
epd_reset = board.D5
epd_busy = board.D6

display_bus = displayio.FourWire(
    spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000
)
time.sleep(1)

display = adafruit_ssd1608.SSD1608(
    display_bus, width=200, height=200, busy_pin=epd_busy, rotation=180
)

g = displayio.Group()

with open("/display-ruler.bmp", "rb") as f:
    pic = displayio.OnDiskBitmap(f)
    # CircuitPython 6 & 7 compatible
    t = displayio.TileGrid(
        pic, pixel_shader=getattr(pic, "pixel_shader", displayio.ColorConverter())
    )
    # CircuitPython 7 compatible only
    # t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
    g.append(t)

    display.show(g)

    display.refresh()

    print("refreshed")

    time.sleep(120)

View on GitHub

Configure and Upload

You will want to change the epd_reset and epd_busy to the correct values. ‎If you wired it up as shown on the Wiring page, you will want to change ‎it to these values:‎

Download File

Copy Code
epd_reset = board.D8
epd_busy = board.D7

‎Save it to your CIRCUITPY drive as code.py and it should ‎automatically run. Your display will look something like this:‎

drive_29

Tricolor Display Usage

HD Tricolor Display

In the examples folder for your SSD1681 displayio driver, there should ‎be a test for your display which we have listed here:‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

"""Simple test script for 1.54" 200x200 tri-color display.
Supported products:
  * Adafruit 1.54" Tri-Color Display Breakout
    * https://www.adafruit.com/product/4868
  """

import time
import board
import displayio
import adafruit_ssd1681

displayio.release_displays()

# This pinout works on a Feather M4 and may need to be altered for other boards.
spi = board.SPI()  # Uses SCK and MOSI
epd_cs = board.D9
epd_dc = board.D10
epd_reset = board.D5
epd_busy = board.D6

display_bus = displayio.FourWire(
    spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000
)
time.sleep(1)

display = adafruit_ssd1681.SSD1681(
    display_bus,
    width=200,
    height=200,
    busy_pin=epd_busy,
    highlight_color=0xFF0000,
    rotation=180,
)

g = displayio.Group()

with open("/display-ruler.bmp", "rb") as f:
    pic = displayio.OnDiskBitmap(f)
    # CircuitPython 6 & 7 compatible
    t = displayio.TileGrid(
        pic, pixel_shader=getattr(pic, "pixel_shader", displayio.ColorConverter())
    )
    # CircuitPython 7 compatible only
    # t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
    g.append(t)

    display.show(g)

    display.refresh()

    print("refreshed")

    time.sleep(120)

View on GitHub

Standard Tricolor Display

In the examples folder for your ILI0373 displayio driver, there should ‎be a test for your display which we have listed here:‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

"""Simple test script for 1.54" 152x152 tri-color display.

Supported products:
  * Adafruit 1.54" Tri-Color Display Breakout
    * https://www.adafruit.com/product/3625
  """

import time
import board
import displayio
import adafruit_il0373

displayio.release_displays()

# This pinout works on a Feather M4 and may need to be altered for other boards.
spi = board.SPI()  # Uses SCK and MOSI
epd_cs = board.D9
epd_dc = board.D10
epd_reset = board.D5
epd_busy = board.D6

display_bus = displayio.FourWire(
    spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000
)
time.sleep(1)

display = adafruit_il0373.IL0373(
    display_bus,
    width=152,
    height=152,
    busy_pin=epd_busy,
    highlight_color=0xFF0000,
    rotation=180,
)

g = displayio.Group()

with open("/display-ruler.bmp", "rb") as f:
    pic = displayio.OnDiskBitmap(f)
    # CircuitPython 6 & 7 compatible
    t = displayio.TileGrid(
        pic, pixel_shader=getattr(pic, "pixel_shader", displayio.ColorConverter())
    )
    # CircuitPython 7 compatible only
    # t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
    g.append(t)

    display.show(g)

    display.refresh()

    print("refreshed")

    time.sleep(120)

‎‎View on GitHub

Configure and Upload

For either display, you will want to change ‎the epd_reset and epd_busy to the correct values. If you wired it up as ‎shown on the Wiring page, you will want to change it to these values:‎

Download File

Copy Code
epd_reset = board.D8
epd_busy = board.D7

Save it to your CIRCUITPY drive as code.py and it should ‎automatically run. Your display will look something like this:‎

save_30

Python Setup

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.‎

Since there are 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. ‎

Note this is not a kernel driver that will let you have the console appear ‎on the eInk. However, this is handy when you want to use the eInk ‎display purely from 'user Python' code!‎

You can only use this technique with Linux/computer devices that have ‎hardware SPI support, and not all single board computers have an SPI ‎device, so check before continuing.

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:‎

Copy Code
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:‎

Copy Code
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.‎

Download font5x8.bin

Alternatively, you can use wget to directly download the file to your pi:‎

Copy Code
wget https://github.com/adafruit/Adafruit_CircuitPython_framebuf/raw/main/examples/font5x8.bin

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:‎

Copy Code
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:‎

Copy Code
sudo apt-get install python3-pil

That's it. You should be ready to go.‎

Python Usage

Note this is not a kernel driver that will let you have the console appear ‎on the eInk. However, this is handy when you want to use the eInk ‎display purely from 'user Python' code!‎

You can only use this technique with Linux/computer devices that have ‎hardware SPI support, and not all single board computers have an SPI ‎device, so check before continuing.‎

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. We set the SRAM CS pin to None because the Raspberry ‎Pi has lots of RAM, so we don't really need it.‎

Download File

Copy Code
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

Depending on the exact E-Ink display you're using, the driver and ‎object initialization will differ a bit because we have to tell Python what ‎the chip driver is, and what the size of the display is!‎

Run the following code to initialize the Monochrome display:‎

Adafruit 1.54" Monochrome eInk / ePaper Display with SRAM

Download File

Copy Code
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)

Run the following code to initialize the lower-res Tricolor display:‎

Adafruit 1.54" 152x152 Tricolor eInk / ePaper Display with SRAM

Copy Code
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)

Run the following code to initialize the newer high-res Tricolor ‎display:‎

Adafruit 1.54" Tricolor eInk / ePaper 200x200 Display with SRAM

Download File

Copy Code
from adafruit_epd.ssd1681 import Adafruit_SSD1681

display = Adafruit_SSD1681(200, 200, spi, cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs, rst_pin=rst, busy_pin=busy)

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.‎

Download File

Copy Code
display.rotation = 2
display.fill(Adafruit_EPD.WHITE)

display.fill_rect(20, 20, 50, 60, Adafruit_EPD.BLACK)
display.hline(80, 30, 60, Adafruit_EPD.BLACK)
display.vline(80, 30, 60, Adafruit_EPD.BLACK)

display.display()

Tricolor Example

The Tricolor example is almost the same as the monochrome ‎example, except we added another color in. Once we're done drawing, ‎we need to tell the screen to update using the display() method.‎

Download File

Copy Code
display.rotation = 2
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:‎

shapes_31

That's all there is to drawing simple shapes with eInk displays and ‎CircuitPython!‎

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. We will be using a ‎Tricolor bitmap, but it should still work on a monochrome display.

Click here to download blinka for the 1.54" Low Res Tricolor display

Click here to download blinka for the 1.54" High Res Tricolor and Mono ‎displays

Save the following code to your Raspberry Pi as epd_bitmap.py.‎

Download Project Bundle‎

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

import digitalio
import busio
import board
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il91874 import Adafruit_IL91874  # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398  # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608  # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675  # pylint: disable=unused-import
from adafruit_epd.ssd1680 import Adafruit_SSD1680  # pylint: disable=unused-import
from adafruit_epd.ssd1681 import Adafruit_SSD1681  # pylint: disable=unused-import
from adafruit_epd.uc8151d import Adafruit_UC8151D  # pylint: disable=unused-import


# 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_SSD1681(200, 200,        # 1.54" HD Tri-color display
# display = Adafruit_IL91874(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_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,
)

# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY 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):  # pylint: disable=too-many-locals, too-many-branches
    try:
        f = open(filename, "rb")  # pylint: disable=consider-using-with
    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()

View on GitHub

Before running it, we need to change a few pin definitions though. Find ‎the section of code that looks like this:‎

Download File

Copy Code
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:‎

Download File

Copy Code
ecs = digitalio.DigitalInOut(board.CE0)
dc = digitalio.DigitalInOut(board.D22)
srcs = None
rst = digitalio.DigitalInOut(board.D27)
busy = digitalio.DigitalInOut(board.D17)

Next, find the section that looks like this:‎

Download File

Copy Code
# display = Adafruit_SSD1608(200, 200,        # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250,        # 2.13" HD mono display
# display = Adafruit_SSD1681(200, 200,        # 1.54" HD Tri-color 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,
    spi,  # 2.13" Tri-color display
    cs_pin=ecs,
    dc_pin=dc,
    sramcs_pin=srcs,
    rst_pin=rst,
    busy_pin=busy,
)

Comment out these lines:‎

Download File

Copy Code
display = Adafruit_IL0373(
    104,
    212,  # 2.13" Tri-color display

and uncomment the line that corresponds with your display. ‎

Next, we tell the display the rotation setting we want to use. This can ‎be a value between 0-3. For the 1.54" displays, a value of 2 seems to ‎work well.‎

Download File

Copy Code
display.rotation = 2

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 an image like this:‎

Bitmap Example

Full Example Code

Here is the full example code.‎

To run the code sample below, you will need to change the pins the ‎same way as you did in the Tricolor Bitmap Example.‎‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

import digitalio
import busio
import board
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il91874 import Adafruit_IL91874  # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398  # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608  # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675  # pylint: disable=unused-import
from adafruit_epd.ssd1680 import Adafruit_SSD1680  # pylint: disable=unused-import
from adafruit_epd.ssd1681 import Adafruit_SSD1681  # pylint: disable=unused-import
from adafruit_epd.uc8151d import Adafruit_UC8151D  # pylint: disable=unused-import

# 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_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_SSD1681(200, 200,        # 1.54" HD Tri-color display
# display = Adafruit_IL91874(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_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,
)

# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY 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

# clear the buffer
print("Clear buffer")
display.fill(Adafruit_EPD.WHITE)
display.pixel(10, 100, Adafruit_EPD.BLACK)

print("Draw Rectangles")
display.fill_rect(5, 5, 10, 10, Adafruit_EPD.RED)
display.rect(0, 0, 20, 30, Adafruit_EPD.BLACK)

print("Draw lines")
display.line(0, 0, display.width - 1, display.height - 1, Adafruit_EPD.BLACK)
display.line(0, display.height - 1, display.width - 1, 0, Adafruit_EPD.RED)

print("Draw text")
display.text("hello world", 25, 10, Adafruit_EPD.BLACK)
display.display()

View on GitHub

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.‎

Image Drawing with Pillow

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.‎

Download Project Bundle

Copy Code
# 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 digitalio
import busio
import board
from PIL import Image
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il91874 import Adafruit_IL91874  # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398  # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608  # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675  # pylint: disable=unused-import
from adafruit_epd.ssd1680 import Adafruit_SSD1680  # pylint: disable=unused-import
from adafruit_epd.ssd1681 import Adafruit_SSD1681  # pylint: disable=unused-import
from adafruit_epd.uc8151d import Adafruit_UC8151D  # pylint: disable=unused-import


# 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_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_SSD1681(200, 200,        # 1.54" HD Tri-color display
# display = Adafruit_IL91874(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_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,
)

# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY 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")

# Display image.
display.image(image)
display.display()

View on GitHub

So, we start with our usual imports including a couple of Pillow ‎modules and the ePaper display drivers.‎

Download File

Copy Code
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
from adafruit_epd.ssd1681 import Adafruit_SSD1681

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.‎

Download File

Copy Code
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" Tricolor 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. ‎

Download File

Copy Code
#display = Adafruit_SSD1608(200, 200,        # 1.54" HD mono display
#display = Adafruit_SSD1675(122, 250,        # 2.13" HD mono display
#display = Adafruit_SSD1681(200, 200,        # 1.54" HD Tri-color 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
)

Next change the rotation setting to 2.‎

Download File

Copy Code
display.rotation = 2

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.‎

Download File

Copy Code
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 Tricolor eInks, but ‎loses detail with displaying a color image on the monochrome display, ‎so we decided to go with the best balance.‎

Download File

Copy Code
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.‎

Download File

Copy Code
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.‎

Download File

Copy Code
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:‎

command_34

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.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2019 Melissa LeBlanc-Williams for Adafruit Industries
# SPDX-License-Identifier: MIT

"""
ePaper Display Shapes and Text demo using the Pillow Library.

"""

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  # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398  # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608  # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675  # pylint: disable=unused-import
from adafruit_epd.ssd1680 import Adafruit_SSD1680  # pylint: disable=unused-import
from adafruit_epd.ssd1681 import Adafruit_SSD1681  # pylint: disable=unused-import
from adafruit_epd.uc8151d import Adafruit_UC8151D  # pylint: disable=unused-import

# 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_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_SSD1681(200, 200,        # 1.54" HD Tri-color display
# display = Adafruit_IL91874(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_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,
)

# IF YOU HAVE A 2.13" FLEXIBLE DISPLAY 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()

View on GitHub

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.‎

Download File

Copy Code
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
from adafruit_epd.ssd1681 import Adafruit_SSD1681

Next, we define some colors that can be used with Pillow.‎

Download File

Copy Code
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.‎

For the 1.54" display, a BORDER value of 10 and a FONTSIZE value ‎of 20 looks good.‎

Download File

Copy Code
BORDER = 10
FONTSIZE = 20
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" Tricolor, 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.‎

Download File

Copy Code
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.‎

Download File

Copy Code
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.‎

Download File

Copy Code
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.‎

Download File

Copy Code
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.‎

Download File

Copy Code
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.‎

Download File

Copy Code
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:‎

hello_35

Downloads

Files

Display shape/outline:‎

outline_36

Schematic

schematic_37

Fabrication Print

fabrication_38

 

Mfr Part # 3625
1.54" TRI-COLOR EINK / EPAPER DI
Adafruit Industries LLC
$184.75
View More Details
Mfr Part # 4868
ADAFRUIT 1.54 TRI-COLOR EINK / E
Adafruit Industries LLC
$163.81
View More Details
Mfr Part # 4196
BREAKOUT MONOCHROME 1.54" EPD
Adafruit Industries LLC
$204.86
View More Details
Add all DigiKey Parts to Cart
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.