It's easy to use display breakouts with Python and the Adafruit Blinka Displayio module. This module allows you to easily write Python code to control the display.

Below covers how to wire the display to a Raspberry Pi. 

Since there's dozens of Linux computers/boards you can use, below shows 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.

Note this is not a kernel driver that will let you have the console appear on the TFT. However, this is handy when you can't install an fbtft driver, and want to use the TFT 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

Wiring

  • Vin connects to the Raspberry Pi's 3V pin
  • GND connects to the Raspberry Pi's ground
  • CLK connects to SPI clock. On the Raspberry Pi, that's SLCK
  • MOSI connects to SPI MOSI. On the Raspberry Pi, that's also MOSI
  • CS connects to our SPI Chip Select pin. This uses CE0
  • RST connects to our Reset pin. This uses GPIO 24, but it can be changed later.
  • D/C connects to our SPI Chip Select pin. This uses GPIO 25, but it can be changed later as well.

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!

If you have previously installed the Kernel Driver with the PiTFT Easy Setup, you will need to remove it first in order to run this example.

Python Installation of ST7789 Library

Once that's done, from your command line run the following command:

sudo pip3 install adafruit-circuitpython-st7789 adafruit-circuitpython-display-text

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

Pillow Library

PIL, the Python Imaging Library, will also be needed to display 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

NumPy Library

You can install NumPy which allows for additional speed. This can be installed with the following command:

sudo apt-get install python3-numpy

Running the Code

Next to run the code, you will need to do a simple modification so the CircuitPython code runs on Python.

Script Download and Modifications

Download the script using the wget command:

cd ~
wget https://github.com/adafruit/Adafruit_CircuitPython_ST7789/raw/main/examples/st7789_172x320_1.47_simpletest.py

Next, edit the script and make the following changes to use the correct pins:

tft_cs = board.CE0
tft_dc = board.D25
tft_rst = board.D24

Now go ahead and run the script, the output should look like this:

Full Example

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

"""
This test will initialize the display using displayio and draw a solid green
background, a smaller purple rectangle, and some yellow text.
"""
import board
import terminalio
import displayio
from adafruit_display_text import label
from adafruit_st7789 import ST7789


BORDER_WIDTH = 28
TEXT_SCALE = 3

# Release any resources currently in use for the displays
displayio.release_displays()

# built-in, silkscreen labelled SPI bus
spi = board.SPI()
tft_cs = board.D5
tft_dc = board.D6
tft_rst = board.D9

# If using a Raspberry Pi Pico or Pico-w
# Uncomment the below code to use GP (General Purpose) pins
# instead of D (Digital)

# import busio
# spi = busio.SPI(board.GP2, board.GP3, board.GP4)
# tft_cs = board.GP5
# tft_dc = board.GP6
# tft_rst = board.GP7

display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_rst)

display = ST7789(display_bus, width=320, height=172, colstart=34, rotation=270)

# Make the display context
splash = displayio.Group()
display.show(splash)

color_bitmap = displayio.Bitmap(display.width, display.height, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x00FF00  # Bright Green
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)

# Draw a smaller inner rectangle
inner_bitmap = displayio.Bitmap(
    display.width - (BORDER_WIDTH * 2), display.height - (BORDER_WIDTH * 2), 1
)

inner_palette = displayio.Palette(1)
inner_palette[0] = 0xAA0088  # Purple
inner_sprite = displayio.TileGrid(
    inner_bitmap, pixel_shader=inner_palette, x=BORDER_WIDTH, y=BORDER_WIDTH
)
splash.append(inner_sprite)

# Draw a label
text_area = label.Label(
    terminalio.FONT,
    text="Hello World!",
    color=0xFFFF00,
    scale=TEXT_SCALE,
    anchor_point=(0.5, 0.5),
    anchored_position=(display.width // 2, display.height // 2),
)
splash.append(text_area)

while True:
    pass

Python Installation of RGB Display Library

The other library that you can use to draw to displays in Python is the RGB Display library. This library allows you to more directly use PIL so if you wanted to draw a JPG image, for instance, or other advanced graphics, then you can easily do so. To install the library, run this command:

sudo pip3 install adafruit-circuitpython-rgb-display

Displaying a JPG Image

To display an image other than a Bitmap such as a JPG, you just need to load it in with Pillow. To demonstrate this, download this image of blinka:

You can download it straight onto you Pi with this command:

wget https://cdn-learn.adafruit.com/assets/assets/000/110/219/original/adafruit_products_blinka.jpg
mv adafruit_products_blinka.jpg blinka.jpg

You can download the script to your Pi with this command:

wget https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display/raw/main/examples/rgb_display_pillow_image.py

Run the Script

You will need to modify the script by commenting out a few lines of the ILI9341 display initializer. Leave everything else that including the line that contains cs=cs_pin, alone. The code with the commented out part should look like this:

#disp = ili9341.ILI9341(
#    spi,
#    rotation=90,  # 2.2", 2.4", 2.8", 3.2" ILI9341
    cs=cs_pin,
    dc=dc_pin,

Then you will need to uncomment the line that for this display:

disp = st7789.ST7789(spi, rotation=90, width=172, height=320, x_offset=34, # 1.47" ST7789

Now you can run the script with this command:

sudo python3 rgb_display_pillow_image.py

Your display should look like this:

Full Example

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

"""
Be sure to check the learn guides for more usage information.

This example is for use on (Linux) computers that are using CPython with
Adafruit Blinka to support CircuitPython libraries. CircuitPython does
not support PIL/pillow (python imaging library)!

Author(s): Melissa LeBlanc-Williams for Adafruit Industries
"""

import digitalio
import board
from PIL import Image, ImageDraw
from adafruit_rgb_display import ili9341
from adafruit_rgb_display import st7789  # pylint: disable=unused-import
from adafruit_rgb_display import hx8357  # pylint: disable=unused-import
from adafruit_rgb_display import st7735  # pylint: disable=unused-import
from adafruit_rgb_display import ssd1351  # pylint: disable=unused-import
from adafruit_rgb_display import ssd1331  # pylint: disable=unused-import

# Configuration for CS and DC pins (these are PiTFT defaults):
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = digitalio.DigitalInOut(board.D24)

# Config for display baudrate (default max is 24mhz):
BAUDRATE = 24000000

# Setup SPI bus using hardware SPI:
spi = board.SPI()

# pylint: disable=line-too-long
# Create the display:
# disp = st7789.ST7789(spi, rotation=90,                            # 2.0" ST7789
# disp = st7789.ST7789(spi, height=240, y_offset=80, rotation=180,  # 1.3", 1.54" ST7789
# disp = st7789.ST7789(spi, rotation=90, width=135, height=240, x_offset=53, y_offset=40, # 1.14" ST7789
# disp = st7789.ST7789(spi, rotation=90, width=172, height=320, x_offset=34, # 1.47" ST7789
# disp = st7789.ST7789(spi, rotation=270, width=170, height=320, x_offset=35, # 1.9" ST7789
# disp = hx8357.HX8357(spi, rotation=180,                           # 3.5" HX8357
# disp = st7735.ST7735R(spi, rotation=90,                           # 1.8" ST7735R
# disp = st7735.ST7735R(spi, rotation=270, height=128, x_offset=2, y_offset=3,   # 1.44" ST7735R
# disp = st7735.ST7735R(spi, rotation=90, bgr=True, width=80,       # 0.96" MiniTFT Rev A ST7735R
# disp = st7735.ST7735R(spi, rotation=90, invert=True, width=80,    # 0.96" MiniTFT Rev B ST7735R
# x_offset=26, y_offset=1,
# disp = ssd1351.SSD1351(spi, rotation=180,                         # 1.5" SSD1351
# disp = ssd1351.SSD1351(spi, height=96, y_offset=32, rotation=180, # 1.27" SSD1351
# disp = ssd1331.SSD1331(spi, rotation=180,                         # 0.96" SSD1331
disp = ili9341.ILI9341(
    spi,
    rotation=90,  # 2.2", 2.4", 2.8", 3.2" ILI9341
    cs=cs_pin,
    dc=dc_pin,
    rst=reset_pin,
    baudrate=BAUDRATE,
)
# pylint: enable=line-too-long

# Create blank image for drawing.
# Make sure to create image with mode 'RGB' for full color.
if disp.rotation % 180 == 90:
    height = disp.width  # we swap height/width to rotate it to landscape!
    width = disp.height
else:
    width = disp.width  # we swap height/width to rotate it to landscape!
    height = disp.height
image = Image.new("RGB", (width, height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a black filled box to clear the image.
draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
disp.image(image)

image = Image.open("blinka.jpg")

# Scale the image to the smaller screen dimension
image_ratio = image.width / image.height
screen_ratio = width / height
if screen_ratio < image_ratio:
    scaled_width = image.width * height // image.height
    scaled_height = height
else:
    scaled_width = width
    scaled_height = image.height * width // image.width
image = image.resize((scaled_width, scaled_height), Image.Resampling.BICUBIC)

# Crop and center the image
x = scaled_width // 2 - width // 2
y = scaled_height // 2 - height // 2
image = image.crop((x, y, x + width, y + height))

# Display image.
disp.image(image)

This guide was first published on Mar 29, 2022. It was last updated on Mar 29, 2022.

This page (Python Usage) was last updated on Jun 09, 2023.

Text editor powered by tinymce.