Skip to content

Instantly share code, notes, and snippets.

@invisiblek
Last active April 18, 2026 14:12
Show Gist options
  • Select an option

  • Save invisiblek/08fc71de9ffc7af3575036102f5b7c76 to your computer and use it in GitHub Desktop.

Select an option

Save invisiblek/08fc71de9ffc7af3575036102f5b7c76 to your computer and use it in GitHub Desktop.

Revisions

  1. invisiblek revised this gist Feb 6, 2025. No changes.
  2. invisiblek created this gist Feb 6, 2025.
    58 changes: 58 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    # LVGL Micropython on the Waveshare ESP32-C6-LCD-1.47
    This is some notes/scripts/etc that I've put together with the hopes of saving someone else a bunch of time if they ever want to get this thing running. I'm sure there's a better way to do this with custom board files and stuff but for the time being, this will at least serve as a starting point.

    With the esp32c6 only somewhat recently getting [official micropython support](https://github.com/micropython/micropython/pull/11869) and the forked [lv_micropython](https://github.com/lvgl/lv_micropython) seemingly not rebasing anytime soon, kdschlosser has created a [spinoff project](https://github.com/lvgl-micropython/lvgl_micropython) to get things working with mainline micropython. It works great for this!

    ## Helpful Links
    - [Waveshare Wiki for ESP32-C6-LCD-1.74](https://www.waveshare.com/wiki/ESP32-C6-LCD-1.47) - a useful reference. I was able to utilize the demos and documentation to determine which pins to fiddle with to get the screen working
    - [kdschlosser's lvgl_micropython repo](https://github.com/lvgl-micropython/lvgl_micropython) - the meat and potatoes of the whole thing
    - [ampy](https://github.com/scientifichackers/ampy) - used to transfer files to the device

    ## Todo/test (they may already work)
    - ~~Wifi~~ this works
    - SD card
    - Bluetooth
    - ~~LEDs~~ work with neopixel (led is pin 8)
    - Screen rotation

    ## Instructions
    Follow the directions to get kdschlosser's lvgl_micropython cloned.
    The build script for this particular board looks like this:
    ```
    python3 make.py esp32 clean \
    --flash-size=4 \
    --enable-jtag-repl=y \
    BOARD=ESP32_GENERIC_C6 \
    DISPLAY=st7789
    ```
    Once it's done, you'll have a bin that needs flashing. You may need to hold the `boot` button while plugging in the to put it in bootloader mode for flashing.
    Here's the command to do the flash. This assumes a few things:
    - The lvgl_micropython repo was cloned in your home directory
    - The build happened with idf 5.2 and python 3.12. Depending on your distro, and the point in time that you build this, those may need updating.
    - The device shows up as /dev/ttyACM0

    You may need to adjust accordingly, but here's the command as of today:
    ```
    ~/.espressif/python_env/idf5.2_py3.12_env/bin/python \
    -m esptool \
    --chip esp32c6 \
    -p /dev/ttyACM0 \
    -b 460800 \
    --before default_reset \
    --after hard_reset write_flash \
    --flash_mode dio \
    --flash_size 4MB \
    --flash_freq 80m \
    --erase-all 0x0 \
    ~/lvgl_micropython/build/lvgl_micropy_ESP32_GENERIC_C6-4.bin
    ```
    Once it's flashed, make sure micropython is running on the device by connecting a terminal emulator (I've been using gtkterm) to it:
    - Port: `/dev/ttyACM0`
    - Baud Rate: `115200`

    And running: `import sys; sys.version`
    It should return something like `'3.4.0; LVGL (9.2.2) MicroPython (1.24.1) Binding compiled on 2025-02-05'`

    Finally, upload the included `main.py` file to the device and hit the `reset` button to restart it and hopefully get a `HELLO WORLD!`

    Enjoy!
    74 changes: 74 additions & 0 deletions main.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    import lcd_bus
    from micropython import const
    import machine


    # display settings
    _WIDTH = const(172)
    _HEIGHT = const(320)
    _BL = const(22)
    _RST = const(21)
    _DC = const(15)

    _MOSI = const(6)
    _MISO = const(5)
    _SCK = const(7)
    _HOST = const(1) # SPI2

    _LCD_CS = const(14)
    _LCD_FREQ = const(80000000)

    _OFFSET_X = const(34)
    _OFFSET_Y = const(0)

    spi_bus = machine.SPI.Bus(
    host=_HOST,
    mosi=_MOSI,
    miso=_MISO,
    sck=_SCK
    )

    display_bus = lcd_bus.SPIBus(
    spi_bus=spi_bus,
    freq=_LCD_FREQ,
    dc=_DC,
    cs=_LCD_CS,
    )

    # we are going to let the display driver sort out the best freame buffer size and where to allocate it to.
    # fb1 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA)
    # fb2 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA)

    import st7789 # NOQA
    import lvgl as lv # NOQA


    display = st7789.ST7789(
    data_bus=display_bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    backlight_pin=_BL,
    reset_pin=_RST,
    reset_state=st7789.STATE_LOW,
    backlight_on_state=st7789.STATE_PWM,
    color_space=lv.COLOR_FORMAT.RGB565,
    color_byte_order=st7789.BYTE_ORDER_RGB,
    rgb565_byte_swap=True,
    offset_x=_OFFSET_X,
    offset_y=_OFFSET_Y,
    )

    import task_handler # NOQA

    display.set_power(True)
    display.init()
    display.set_backlight(100)

    th = task_handler.TaskHandler()

    scrn = lv.screen_active()
    scrn.set_style_bg_color(lv.color_hex(0x000000), 0)

    label = lv.label(scrn)
    label.set_text('HELLO WORLD!')
    label.align(lv.ALIGN.CENTER, 0, 0)