Let's draw to a display!
Here we'll use SPI to talk to a TFT display. And since we are on a powerful desktop PC, we can even use Pillow (PIL) to do the graphical heavy lifting.
Connect the Display
Here is the wiring diagram for connecting a 2.4" TFT LCD display via SPI. We aren't using touch, so don't need to worry about those pins.
Install Pillow/PIL
We'll just point you to the official Pillow/PIL page so you can follow the install instruction there.
You should be able to just use pip though.
Install CircuitPython RGB Display Library
This library provides support for the TFT display. To install, run:
sudo pip3 install adafruit-circuitpython-rgb-display
Example Image
In this example, we'll load and display an image. Download the image below and save it to the same directory where the Python code will be stored. Make sure it is named blinka.bmp.
import board import digitalio import adafruit_rgb_display.ili9341 as ili9341 from PIL import Image # Setup display cs_pin = digitalio.DigitalInOut(board.C0) dc_pin = digitalio.DigitalInOut(board.C1) disp = ili9341.ILI9341(board.SPI(), cs=cs_pin, dc=dc_pin, baudrate=64000000) # Load image and convert to RGB image = Image.open('blinka.bmp').convert('RGB') # Display it (rotated by 90 deg) disp.image(image, 90)
Save the above with a filename like tft_image.py and then run it with:
python3 tft_image.py
and boom! you should get a happy little Blinka showing up on your display.
Fancier Demo for Linux
There's a lot of power in Pillow/PIL. It can do more than just load and display images. Here's another example that creates a Draw object, uses a TTF font, and then grabs some stats from the PC and displays them.
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT """ This will show some Linux Statistics on the attached display. Be sure to adjust to the display you have connected. 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)! """ import time import subprocess import digitalio import board from PIL import Image, ImageDraw, ImageFont 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) # First define some constants to allow easy positioning of text. padding = -2 x = 0 # Load a TTF font. Make sure the .ttf font file is in the # same directory as the python script! # Some other nice fonts to try: http://www.dafont.com/bitmap.php font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 24) while True: # Draw a black filled box to clear the image. draw.rectangle((0, 0, width, height), outline=0, fill=0) # Shell scripts for system monitoring from here: # https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load cmd = "hostname -I | cut -d' ' -f1" IP = "IP: " + subprocess.check_output(cmd, shell=True).decode("utf-8") cmd = "top -bn1 | grep load | awk '{printf \"CPU Load: %.2f\", $(NF-2)}'" CPU = subprocess.check_output(cmd, shell=True).decode("utf-8") cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%s MB %.2f%%\", $3,$2,$3*100/$2 }'" MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8") cmd = 'df -h | awk \'$NF=="/"{printf "Disk: %d/%d GB %s", $3,$2,$5}\'' Disk = subprocess.check_output(cmd, shell=True).decode("utf-8") cmd = "cat /sys/class/thermal/thermal_zone0/temp | awk '{printf \"CPU Temp: %.1f C\", $(NF-0) / 1000}'" # pylint: disable=line-too-long Temp = subprocess.check_output(cmd, shell=True).decode("utf-8") # Write four lines of text. y = padding draw.text((x, y), IP, font=font, fill="#FFFFFF") y += font.getsize(IP)[1] draw.text((x, y), CPU, font=font, fill="#FFFF00") y += font.getsize(CPU)[1] draw.text((x, y), MemUsage, font=font, fill="#00FF00") y += font.getsize(MemUsage)[1] draw.text((x, y), Disk, font=font, fill="#0000FF") y += font.getsize(Disk)[1] draw.text((x, y), Temp, font=font, fill="#FF00FF") # Display image. disp.image(image) time.sleep(0.1)
The example has import and code initialization for multiple displays. Uncomment the one for the display you are using, and comment out all others. If you are using the same 2.4" TFT (ILI9341) from above, then you don't need to change anything. The example uses that as default.
You will need to change the pins being used to match those on the FT232H. Find these lines of code and make things changes:
# Configuration for CS and DC pins (these are PiTFT defaults): cs_pin = digitalio.DigitalInOut(board.C0) dc_pin = digitalio.DigitalInOut(board.C1) reset_pin = None
With those changes in place, you should be able to run it and get some system stats showing up.
And it will update in near real-time.