A feature-rich MicroPython driver for ST7789 TFT LCD displays with enhanced functionality including bitmap rendering, text display, and rotation support.
- Text Rendering: Built-in 8x8 font with scalable text output
- Bitmap Support: Display images with memory-efficient streaming
- Rotation Control: Four orientation modes (0°, 90°, 180°, 270°)
- BMP File Loading: Stream BMP files directly from filesystem
- Graphics Primitives: Lines, rectangles, pixels, and fills
- Memory Efficient: Chunked rendering for large images
- High Performance: Optimized SPI communication
This driver is based on devbis/st7789py_mpy with significant enhancements including:
- Text rendering with built-in font
- Bitmap and BMP file display capabilities
- Display rotation support
- Improved memory efficiency for large images
- ESP32-C6 with 240x320 ST7789 display
- Should work with other MicroPython-compatible boards (ESP32, ESP8266, RP2040, etc.)
-
Install Thonny: Download from thonny.org
-
Connect Your Board:
- Connect your ESP32-C6 (or compatible board) via USB
- In Thonny, select your board from the bottom-right corner
- Choose "MicroPython (ESP32)" or your specific board type
-
Upload the Driver:
- Open
st7789py.pyin Thonny - Go to File → Save As
- Choose MicroPython device
- Save as
st7789py.py
- Open
-
Upload Your Test Script:
- Open
test_st7789.py - Save it to your MicroPython device
- Open
-
Run: Click the green "Run" button in Thonny
# Install ampy
pip install adafruit-ampy
# Upload driver (change port as needed)
ampy --port /dev/ttyUSB0 put st7789py.py
# Upload test script
ampy --port /dev/ttyUSB0 put test_st7789.py
| ST7789 Pin | ESP32-C6 Pin | Description |
|---|---|---|
| VCC | 3.3V | Power supply |
| GND | GND | Ground |
| SCK | GPIO6 | SPI Clock |
| MOSI | GPIO7 | SPI Data (MOSI) |
| DC | GPIO2 | Data/Command |
| RST | GPIO10 | Reset |
| CS | GPIO15 | Chip Select |
| BL | GPIO3 | Backlight (optional) |
Note: Pin numbers can be customized in your code. The above are just examples.
- 240x240: Square displays
- 240x320: Rectangular displays (common)
- 135x240: Smaller rectangular displays
import machine
import st7789py as st7789
# Initialize SPI
spi = machine.SPI(
1,
baudrate=80000000,
polarity=0,
phase=0,
sck=machine.Pin(6),
mosi=machine.Pin(7),
)
# Initialize display
display = st7789.ST7789(
spi,
240, # Width
320, # Height
reset=machine.Pin(10, machine.Pin.OUT),
dc=machine.Pin(2, machine.Pin.OUT),
cs=machine.Pin(15, machine.Pin.OUT),
backlight=machine.Pin(3, machine.Pin.OUT),
)
# Initialize with rotation (0=portrait, 1=landscape, 2=portrait flipped, 3=landscape flipped)
display.init(rotation=0)
# Turn on backlight
display.backlight.value(1)
# Draw something!
display.fill(st7789.BLACK)
display.text("Hello World!", 10, 10, st7789.WHITE, scale=3)
# Fill screen with color
display.fill(st7789.RED)
# Draw rectangles
display.rect(10, 10, 100, 50, st7789.WHITE)
display.fill_rect(20, 20, 80, 30, st7789.BLUE)
# Draw lines
display.line(0, 0, 239, 319, st7789.GREEN)
display.hline(0, 100, 240, st7789.YELLOW)
display.vline(120, 0, 320, st7789.CYAN)
# Draw individual pixels
display.pixel(120, 160, st7789.WHITE)
# Basic text
display.text("Hello!", 10, 10, st7789.WHITE)
# Scaled text (scale=1 is 8x8, scale=2 is 16x16, etc.)
display.text("BIG TEXT", 10, 50, st7789.YELLOW, scale=4)
# Text with background color
display.text("Info", 10, 100, st7789.BLACK, st7789.WHITE, scale=2)
# Multi-line text
display.text("Line 1\nLine 2\nLine 3", 10, 10, st7789.GREEN, scale=2)
# Portrait (0°)
display.set_rotation(0)
# Landscape (90°)
display.set_rotation(1)
# Portrait flipped (180°)
display.set_rotation(2)
# Landscape flipped (270°)
display.set_rotation(3)
# Create a small bitmap in RGB565 format
bitmap = bytearray()
for y in range(32):
for x in range(32):
r = x * 8
g = y * 8
b = 128
color = st7789.color565(r, g, b)
bitmap.extend(color.to_bytes(2, 'big'))
# Draw the bitmap
display.draw_bitmap(bitmap, 50, 50, 32, 32)
The draw_bmp_file_streaming() function is highly optimized for memory-constrained devices. It streams the BMP file line-by-line, making it possible to display full-screen images without running out of RAM.
# Load and display a BMP file (24-bit uncompressed BMP only)
# The file is streamed in chunks - very memory efficient!
display.draw_bmp_file_streaming('image.bmp', x=0, y=0)
# Or use the convenient alias
display.draw_bmp_file('image.bmp')
# Adjust chunk size for different memory constraints
# Smaller lines_per_chunk = less memory usage
display.draw_bmp_file_streaming('image.bmp', x=0, y=0, lines_per_chunk=2)
Important: Only 24-bit uncompressed BMP files are supported. Use the included utility/conv_240_320.py utility to prepare your images.
# Use predefined colors
colors = [st7789.BLACK, st7789.RED, st7789.GREEN, st7789.BLUE,
st7789.CYAN, st7789.MAGENTA, st7789.YELLOW, st7789.WHITE]
# Create custom colors (RGB 0-255)
custom_color = st7789.color565(128, 64, 200)
# You can also pass a tuple
color_tuple = (255, 128, 0)
orange = st7789.color565(color_tuple)
The included utility/conv_240_320.py script is a PC-side utility that converts any image format to a properly sized 24-bit BMP file for your display.
# Install PIL/Pillow
pip install Pillow
# Convert any image to 240x320 BMP
python conv_240_320.py input_image.jpg output_image.bmp
# Examples
python conv_240_320.py photo.jpg beach.bmp
python conv_240_320.py logo.png logo.bmp
python conv_240_320.py drawing.gif drawing.bmp
The script will:
- Resize the image to 240x320 pixels
- Convert it to 24-bit BMP format
- Save the output file ready for upload
Using Thonny:
- Open Thonny
- Right-click in the "Files" panel
- Select "Upload to /"
- Choose your BMP file
Using ampy:
ampy --port /dev/ttyUSB0 put beach.bmp
display = st7789.ST7789(spi, width, height, reset, dc, cs=None,
backlight=None, xstart=-1, ystart=-1)
display.init(rotation=0)
fill(color)- Fill entire screenfill_rect(x, y, width, height, color)- Draw filled rectanglerect(x, y, width, height, color)- Draw rectangle outlineline(x0, y0, x1, y1, color)- Draw linehline(x, y, length, color)- Draw horizontal linevline(x, y, length, color)- Draw vertical linepixel(x, y, color)- Draw single pixel
text(text, x, y, color, bg_color=None, scale=1)- Draw textchar(char, x, y, color, bg_color=None, scale=1)- Draw single character
draw_bitmap(bitmap_data, x, y, width, height)- Draw bitmap from memorydraw_bmp_file(filename, x, y)- Load and display BMP file (memory efficient)draw_bmp_file_streaming(filename, x, y, lines_per_chunk=4)- Stream BMP with custom chunk size
set_rotation(rotation)- Set rotation (0-3)inversion_mode(value)- Enable/disable color inversionsleep_mode(value)- Enable/disable sleep mode
- Small bitmaps (≤64x64): Can be loaded entirely into RAM
- Large images: Use
draw_bmp_file_streaming()for memory efficiency - Full screen (240x320): Requires ~2KB per chunk with default settings
- Text: Minimal memory usage with built-in font
- Check wiring connections
- Verify backlight is on:
display.backlight.value(1) - Try different rotation settings
- Check SPI pins match your hardware
- Try:
display.inversion_mode(True)ordisplay.inversion_mode(False)
- Adjust rotation:
display.set_rotation(0)throughdisplay.set_rotation(3)
- Ensure file is 24-bit uncompressed BMP
- Use
conv_240_320.pyto convert images - Check file is uploaded to device
- Verify filename is correct (case-sensitive on some systems)
- Use smaller
lines_per_chunkindraw_bmp_file_streaming() - Reduce bitmap sizes
- Close unused files and objects
MIT License
Copyright (c) 2025
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
- Based on devbis/st7789py_mpy
- Tested on ESP32-C6 hardware
- Font data adapted from standard 8x8 bitmap fonts
