Getting MicroPython Working on the ESP32-C6-LCD-1.47
Run micropython on ESP32-C6-LCD-1.47 was not easy, but it worked in the end.
I recently got my hands on an ESP32-C6 board and was immediately drawn to its compact form factor. In particular, the Waveshare ESP32-C6-LCD-1.47 model comes with a 1.47” display, Wi‑Fi, and a few other handy features. You can check out the full specs on the Waveshare Wiki.
My initial goal is to use this board as the core of a MIDI controller. Getting it working, however, wasn’t straightforward. After some trial and error, I managed to flash MicroPython, configure the display, and run a simple demo app that shows random quotes. The MIDI controller is still a work in progress, but here’s how I got the board up and running.
Finding the Right Display Library
After trying a few approaches, the repo that finally worked for me was:
- https://github.com/russhughes/st7789py_mpy
The examples I had at first didn’t work out of the box, but the code from this repo did the trick — with a few caveats. I had to tweak some helper scripts to run properly on macOS, as they assumed Linux-specific commands. The changes were minor, though.
Here’s the full process I followed.
Required Toolchain
First, install the required tools:
pipx install mpremote esptool mpy-cross
Flashing MicroPython
Download the latest ESP32-C6 firmware from micropython.org, then flash it to the board:
# Erase the flash memory
PORT=/dev/cu.usbmodemXXXX # Replace with your actual port
esptool.py --port $PORT --baud 921600 erase_flash
# Flash the firmware
esptool.py --port $PORT --baud 921600 write_flash -z 0x0 firmware-esp32-generic-c6.bin
After flashing, reset the board.
The Random Quotes App
The sample app displays a random quote every 10 seconds on the screen.
boot.py
import esp
try:
esp.osdebug(None)
except Exception:
pass
main.py
import time
import random
import st7789py as st7789
import tft_config
import vga1_8x8 as font
tft = tft_config.config(tft_config.WIDE)
QUOTES = [
"Cafe listo, bugs listos.",
"Compilo, luego existo.",
"Mi otro microcontrolador es un 6502.",
"Funciona en mi placa™.",
"Wi-Fi es mi superpoder.",
"El LED parpadea, luego hay vida.",
"RTFM: Realmente Tremendo Firmware Manual.",
"El bug era un feature... hasta que no.",
"GPIO: Grandes Ideas, Pocas Opciones.",
"Dormir? Prefiero flashear.",
]
def center(text, fg=st7789.WHITE, bg=st7789.BLACK):
"""Centers the given text on the display."""
length = len(text)
tft.text(
font,
text,
tft.width // 2 - length // 2 * font.WIDTH,
tft.height // 2 - font.HEIGHT,
fg,
bg,
)
def main():
"""The big show!"""
while True:
for color in [
st7789.BLACK,
st7789.color565(100, 100, 100),
st7789.color565(0, 0, 100),
]:
tft.fill(color)
tft.rect(0, 0, tft.width, tft.height, st7789.WHITE)
center(QUOTES[random.randint(0, len(QUOTES) - 1)], st7789.WHITE, color)
time.sleep(10)
main()
Custom Display Configuration
The tricky part was getting the display configuration right. None of the tft_config.py
files included with the library worked for the Waveshare board, so I created my own:
tft_config.py
"""Waveshare ESP32-C6-LCD-1.47
https://www.waveshare.com/wiki/ESP32-C6-LCD-1.47
172x320 ST7789 display with ESP32-C6
Note: Using 240x320 mode with offset for 172x320 display
"""
from machine import Pin, SPI
import st7789py as st7789
TFA = 0
BFA = 0
WIDE = 1
TALL = 0
SCROLL = 0 # orientation for scroll.py
FEATHERS = 1 # orientation for feathers.py
def config(rotation=0):
"""
Configures and returns an instance of the ST7789 display driver.
Args:
rotation (int): The rotation of the display (default: 0).
Returns:
ST7789: An instance of the ST7789 display driver.
"""
return st7789.ST7789(
SPI(1, baudrate=80000000, sck=Pin(7), mosi=Pin(6), miso=Pin(5)),
240,
320,
reset=Pin(21, Pin.OUT),
cs=Pin(14, Pin.OUT),
dc=Pin(15, Pin.OUT),
backlight=Pin(22, Pin.OUT),
rotation=rotation)
Deployment Script
Finally, here’s the script I used to deploy everything to the board. This was the “magic trick” that made the process smooth. I adapted it from upload_all.sh
in the example folder of the st7789py_mpy
repo and added font compilation.
deploy.sh
#!/usr/bin/env bash
set -euo pipefail
PORT="${PORT:-/dev/cu.usbmodem83101}"
if ! command -v mpremote >/dev/null 2>&1; then
echo "This script requires the mpremote command. You can install it with:"
echo "pip3 install --user mpremote"
exit 1
fi
if ! command -v mpy-cross >/dev/null 2>&1; then
echo "This script requires the mpy-cross command. You can install it with:"
echo "pip3 install --user mpy-cross"
exit 1
fi
upload_fonts () {
cd romfonts
rm -f *.mpy
for font in *.py
do
mpy-cross $font
done
cd ..
mpremote cp romfonts/*.mpy :
}
mpremote connect "$PORT" mip install "github:russhughes/st7789py_mpy/lib/st7789py.py" || true
upload_fonts
mpremote connect "$PORT" fs cp tft_config.py :
mpremote connect "$PORT" fs cp boot.py :
mpremote connect "$PORT" fs cp main.py :
echo "==> Resetting board"
mpremote connect "$PORT" reset
echo "Done."
Wrapping Up
Once I figured out the display configuration, everything else fell into place. The ESP32-C6 is a surprisingly capable board, and with MicroPython it’s easy to iterate quickly. The random quotes app is just a fun example, but the same setup will serve as the foundation for my upcoming MIDI controller project.