I am using a generic ESP32-D0WD-V3. I have a generic GC9A01 240x240 display. I am using micropython. I have been working on this for 5 days now just trying for the life of me to figure out how to get LVGL onto my board. I have downloaded multiple files, I have downloaded multiple programs. I have esptools, idf, and a slew of other stuff I have installed using pip. I have tried cmd, I have tried powershell (ran as administrator), i have tried WSL. I have tried creating projects, building firmwares, flashing firmwares, using examplesā¦ lets just say Iām about tired of chasing my tail. I have tried to find any forum related to LVGL using micropython and my display. All I want to do is use EEZ Studio to make a guage to measure the RPM of an electric motor. How in the actual do you use LVGL? Is there a straight forward set of directions on how to add this. Iāll be honest, and hopefully at this point it is apparent, I have no idea what I am doing. I am teaching myself all of this as I go. None of the instructions in any of the readme files make any sense. All they say to do is run āidf.py buildāā¦ like, what? I have tried that and received nothing but errors in return. Does anyone have anything other than āGood Luck Kidā to help me?
Start with reply why for this you require micropython?
I am familiar with the python language and micropython is supposedly one of the better languages to use with MCUs. I already have the motor controller working with micropython. Iām just wanting to add gauges.
I feel your pain, I was there once it was literally insane trying to figure out where the starting point and end points were.
Some things Iām going to say are going to be obvious to you maybe not but I donāt know where youāre at so Iām just kind of take a leap here and tell you what the big picture is.
So you have micropython and lvgl, they need to be merged into a single binary (firmware.bin) to be uploaded to the ESP32.
LVGL is not a module that can be imported, itās baked into the micropython code !!!
Now to make the firmware.bin file that will have micropython and LVGL that will be flashed to your mcu.
I use WSL2 on windows.
In the āterminalā make a build folder ie:guage_firmware
mkdir guage_firmware
now go into that folder
cd guage_firmware
Using repo from GitHub - kdschlosser/lvgl_micropython: LVGL module for MicroPython lot of info there ā¦
now enterā¦
git clone "https://github.com/kdschlosser/lvgl_micropython.git"
you now will have a lvgl_micropython folder
Now letās install the tool chains
sudo apt-get install build-essential
sudo apt-get install cmake
sudo apt-get install ninja-build
sudo apt-get install python
Time to build the firmware
cd lvgl_micropython
This command line is specific for my needsā¦ this is where you create a custom build
For exampleā¦
mcuā¦ esp32
use only on 1st runā¦ submodules
remove last buildā¦ clean
use only on 1st runā¦ mpy_cross
version of esp32ā¦ BOARD=ESP32_GENERIC
esp32 memory typeā¦ BOARD_VARIANT=SPIRAM
my tft chipā¦ DISPLAY=ili9341
my touch chipā¦ INDEV=xpt2046
esp32 memory size in mbā¦ --flash-size=4
āoptimize-size
Lets buildā¦
python3 make.py esp32 submodules clean mpy_cross BOARD=ESP32_GENERIC BOARD_VARIANT=SPIRAM DISPLAY=ili9341 INDEV=xpt2046 --flash-size=4 --optimize-size
When the build is completed you should see something like thisā¦
To flash firmware:
Replace "(PORT)" with the serial port for your esp32
and run the commands.
/home/rich/.espressif/python_env/idf5.2_py3.8_env/bin/python -m esptool -p (PORT) -b 460800 erase_flash
/home/rich/.espressif/python_env/idf5.2_py3.8_env/bin/python -m esptool --chip esp32 -p (PORT) -b 921600 --before default_reset --after no_reset write_flash --flash_mode dio --flash_size 4MB --flash_freq 40m 0x0 "/home/rich/SL-Version-2/lvgl_micropython/build/lvgl_micropy_ESP32_GENERIC-SPIRAM-SPIRAM-4.bin"
NOW This is where Iām different than other people I like to work in windows so Iām going to grab my firmware file and copy it to a folder in my windows environmentā¦
make a project folder ie: guage
in the gauge folder make a folder bin for the firmware.bin file
In Windows Explorer go to Linux > Ubuntu
and get firmware.bin at.
\home\ -NAME- \guage_firmware\lvgl_micropython\lib\micropython\ports\esp32\build-ESP32_GENERIC-SPIRAM\firmware.bin
copy firmware.bin and paste in your guage/bin folder
Lets Flash the esp32ā¦
my esp32 is connected to port com4
Using PowerShellā¦
erase flash
python -m esptool --chip esp32 --port COM4 erase_flash
now flashā¦
python -m esptool --chip esp32 --port COM4 --baud 921600 write_flash -z --flash_mode dio --flash_freq 40m 0x1000 firmware.bin
now open your REPL and see if you have a promptā¦
>>
Here is a main.py test file with a button and labelā¦
from machine import SPI # NOQA
def btn_cb(event):
if event.get_code() == lv.EVENT.CLICKED:
print('clicked !!')
msg_txt.set_text('clicked !!') # change hello world to clicked !!
# Create the SPI bus
spi_bus = SPI(2, 1000, miso=19, mosi=23, sck=18, cs=5)
# SPI device for display
import lcd_bus
display_bus = lcd_bus.SPIBus(spi_bus=spi_bus, cs=15, freq=40_000_000, dc=13)
import lvgl as lv
# Start display driver
import ili9341
display = ili9341.ILI9341(
data_bus=display_bus,
display_width=240, # I'm using a portrait rotation
display_height=320,
# frame_buffer1=fb1,
# frame_buffer2=fb2,
reset_pin=None,
power_pin=None,
backlight_pin=27,
color_space=lv.COLOR_FORMAT.RGB565,
color_byte_order=ili9341.BYTE_ORDER_BGR,
rgb565_byte_swap=True
)
display.init()
# Start touch driver
import xpt2046
touch = xpt2046.XPT2046(spi_bus)
main = lv.screen_active()
msg_txt = lv.label(main)
msg_txt.align(lv.ALIGN.CENTER, 0, 80)
msg_txt.set_text('Hello World !!')
btn = lv.button(main)
btn.set_size(90,40)
btn.align(lv.ALIGN.CENTER, 0, 0)
btn.add_event_cb(btn_cb, lv.EVENT.CLICKED, None)
btn_lbl = lv.label(btn)
btn_lbl.set_text("Click Me !")
btn_lbl.align(lv.ALIGN.LEFT_MID, 0, 0)
display.set_backlight(100) # turns on tft backlight
import task_handler
th = task_handler.TaskHandler()
Hope this helps anyone!!!
This is amazing! Thank you so much for this. For me I found itās easier to flash using esptools in powershell (if thereās a better way, please let me know.) Iāve been using WSL in my all my failed attempts to follow the readme instructions of:
"
Build Instructions
First step is always to clone lv_micropython and update its submodules recursively:
git clone GitHub - lvgl/lv_micropython: Micropython bindings to LVGL for Embedded devices, Unix and JavaScript
cd lv_micropython
git submodule update --init --recursive lib/lv_bindings
Next you should build mpy-cross
make -C mpy-cross
make -C ports/esp32 LV_CFLAGS=ā-DLV_COLOR_DEPTH=16ā OARD=GENERIC_SPIRAM deploy
"
Before posting this topic, I compiled something that resembled a firmware.bin, but when I flashed it to my board the diag light on the board just flashed and the shell showed some kind of an awful loop.
Where I got lost in your reply was when you said:
āNOW This is where Iām different than other people I like to work in windows so Iām going to grab my firmware file and copy it to a folder in my windows environmentā¦
make a project folder ie: guage
in the gauge folder make a folder bin for the firmware.bin file
In Windows Explorer go to Linux > Ubuntu
and get firmware.bin at.
\home\ -NAME- \guage_firmware\lvgl_micropython\lib\micropython\ports\esp32\build-ESP32_GENERIC-SPIRAM\firmware.bin
copy firmware.bin and paste in your guage/bin folderā
Iāve never used Linux before, so in my WSL Iāve been using:
āamelvin@Melvin:/mnt/c/Users/andre/OneDrive/Desktop/lvgl-master/lv_micropython/ports/esp32$ idf.py set-target esp32ā
Iām assuming that when youāre messing with Linux, youāre doing it from in a virtual machine environment that is using a compartmented file system? I am also assuming that when Iām in WSL the /mnt/ is almost like mounting a virtual drive in a virtual machine? Quite frankly, Iām not sure what Iām doing, I just know I am referencing the directory located in the Windows environment.
That being said, if I never hear from you again, I want you to know I am extremely grateful for your response. I am going to try this now, Iāll post my results. Thanks again @GC-RmG.
Another question I have, what do I do about my tft chip? My display is a gc9a01. The drivers are not part of the standard LVGL download. I do have a GC9A01 driver that I used to test my pinout and see if I could get it to work, which it did. Iām just not sure what I should do with the driver folder to have it also ābaked into the micropython code.ā I can just upload it to the chip and initialize the driver using the specific file location like I did with the test code, but Iām sure thereās a better way of doing this.
This was how I referenced the driver in my code when I tested the display:
"
from lib import gc9a01py as gc9a01
"
The instructions I gave you were for a new and much better repo namedā¦
lvgl_micropython by Kevin Schlosser @ GitHub - kdschlosser/lvgl_micropython: LVGL module for MicroPython
This package will build a micropython v1.24 and LVGL v9
MicroPython v1.24.0-preview.39.g411d66586.dirty on 2024-06-24; Generic ESP32 module with SPIRAM with ESP32
The methods you are describing are from the originalā¦
lv_micropython by Gabor Kiss-Vamosi @ GitHub - lvgl/lv_micropython: Micropython bindings to LVGL for Embedded devices, Unix and JavaScript
Any questions or any help you need regarding drivers building anything Kevin is extremely responsive and very thorough !!!
Thanks to you, Iāve seen more progress than ever. Now, however, I am getting to a certain spot and getting a idf click error. Iām not near my computer but Iāll copy the error or take a screenshot later. I think itās and idf environment error
make: Entering directory ā/mnt/c/Users/andre/OneDrive/Documents/ESP32_to_ESC_Project/Gauge_Firmware/lvgl_micropython/lib/micropython/ports/esp32ā
idf.py -D MICROPY_BOARD=ESP32_GENERIC -D MICROPY_BOARD_DIR=ā/mnt/c/Users/andre/OneDrive/Documents/ESP32_to_ESC_Project/Gauge_Firmware/lvgl_micropython/lib/micropython/ports/esp32/boards/ESP32_GENERICā -DUSER_C_MODULES=ā¦/ā¦/ā¦/ā¦/ā¦/ext_mod/micropython.cmake -D MICROPY_FROZEN_MANIFEST=/mnt/c/Users/andre/OneDrive/Documents/ESP32_to_ESC_Project/Gauge_Firmware/lvgl_micropython/build/manifest.py -D MICROPY_BOARD_VARIANT=SPIRAM -B build-ESP32_GENERIC-SPIRAM build || (echo -e āSee \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0mā; false)
-e See Build Troubleshooting Ā· micropython/micropython Wiki Ā· GitHub
make: Leaving directory ā/mnt/c/Users/andre/OneDrive/Documents/ESP32_to_ESC_Project/Gauge_Firmware/lvgl_micropython/lib/micropython/ports/esp32ā
Cannot import module āclickā. This usually means that āidf.pyā was not spawned within an ESP-IDF shell environment or the python virtual environment used by āidf.pyā is corrupted.
Please use idf.py only in an ESP-IDF shell environment. If problem persists, please try to install ESP-IDF tools again as described in the Get Started guide.
make: *** [Makefile:66: all] Error 1
amelvin@Melvin:/mnt/c/Users/andre/OneDrive/Documents/ESP32_to_ESC_Project/Gauge_Firmware/lvgl_micropython$
First of all Thanks for your post you really helped me a lot!
I did everything you posted and it worked beatifully or so I thought. The REPL appears and I can even import ili9341, xpt2046 and lvgl. The only issue appears when I want to use the SPI() method in your test file:
.
.
.
spi_bus = SPI(2, 1000, miso=19, mosi=23, sck=18, cs=5)
.
.
.
Traceback (most recent call last):
File āā, line 9, in
TypeError: canāt create āSPIā instances
I tried building like in your reply:
" python3 make.py esp32 submodules clean mpy_cross BOARD=ESP32_GENERIC BOARD_VARIANT=SPIRAM DISPLAY=ili9341 INDEV=xpt2046 --flash-size=4 --optimize-size
"
but got the afore mentioned TypeError. I am using an ESP32-WROVER -DEV v1.6 so I thought maybe the problem is there. The microntroller Iām using uses 8MB of SPRAM so I tried adjusting the parameters like this:
python3 make.py esp32 submodules clean mpy_cross BOARD=ESP32_GENERIC BOARD_VARIANT=PSRAM DISPLAY=ili9341 INDEV=xpt2046 --flash-size=8 --optimize-size
but got the same result.
i would appreciate if someone could show me a direction.
Maybe try a simpler way - itās now possible to use LVGL in ESPHome which is configured in YAML, so no C or IDF skills required.
ESPHome supports the display chip youāre using, and has components to measure pulse rates etc. so should be easy enough to measure your RPM.
Start here: LVGL implementation for ESPHome by clydebarrow Ā· Pull Request #6363 Ā· esphome/esphome Ā· GitHub
Questions can go on ESPHome Discord in the #display-changes thread.
If you are open to using the Arduino IDE, consider this repo: GitHub - yashmulgaonkar/SquareLineStudio_boardpackages
If you pick up the LILYGO T-encoder s3 board package, you can change the graphics driver yo match what you have.
Hereās the cut and dry easy answer folks. Thank you so much to @GC-RmG and @Kdschlosser for all your help. This is the link to krschlosserās steps:
@GC-RmG Iām sure if I would have had all my WSL and Powershell apps configured right the first time, your steps would have got me there. I ended up having to start over on my computer at work.
Now I just have to figure out how to use the build folder from EEZ Studioā¦
I donāt know if EEZStudio has support for generating the coded needed to run on MicroPython. I can tell you with 100% certainty it is not going to support the binding I wrote. My whole driver design is completely different than the āofficialā binding.
I wrote the drivers for a display in 2 parts. one part is the bus which is the connection type used. The supported buses are SPI, I8080 and RGB. The bus drivers are not keyed to any specific display IC. A lot of display ICās actually support more than one type of bus depending on how it is connected. That is the reason why the bus drivers are their own thing. The bus drivers are written in C code and they expose the needed parts to the python side of things.
The second piece is the display driver. The display drivers are written in Python. This is done so a user has the ability to āmonkey patchā the driver should they have something that needs to be tweaked. It also allows the user to be able to change displays out very easily without needing to compile new firmware. I do however provide the ability to bake the drivers into the firmware if they want to. I wrote a framework that does the majority of the heavy lifting when it comes to the display drivers. This allows for a very minimum amount of code that needs to be written to add new drivers. The code that has to be added is typically just the display initialization sequence and sometimes providing different commands that have to be sent to the display to set memory addresses for where to write the frame buffer data toā¦
I also corrected issues in MicroPython itself. Things like not being able to use an SPI SDCard on a bus that has other devices attached to it. That problem no longer exists. The USB OTG occupying pins 19 and 20 even if you are not using that feature has also been solved. This allows those pins to be used for anything you want.
In order to correct the issues with the SPI SDCard I had to change the way the SPI drivers in MicroPython worked. Micropython was written in a manner where it treated the bus and a device on the bus as a single thing. They actually are 2 different things and they needed to be handled as 2 different things. While I kept the API for sending and receiving the same the API for creating an SPI bus/device has changed. I also wrote and I2C wrapper that mimics the new SPI Bus/Device organization. It also mirrors the send and receive APIās as well. This was done for touch drivers. Some touch ICās allow for using SPI or I2C connections depending on how the IC is connected so the touch drivers are written in the same manner manner where the ābusā is separated from the touch driver code.
Some of the really big features is the ability to test a GUI on the desktop and being able to use the same code on an MCU. The drivers are written in a manner that allow this to be done. Another big feature is real time changes in rotation of the display. Now you can attach a MEMS sensor so you can detect device orientation and based on that data you can change the display rotation which will automatically adjust the touch. You also have the ability to āhot plugā displays. Because of how the bus and driver code is written you can remove a display and plug in a different one without having to flash new firmware, you actually can do this without restarting the MCU.
I also coded in the ability to support DMA transfers. That coupled with double buffering gives a nice boost in performance. This is because the CPU doesnāt get tied up when transferring data to the display so it can go and do other things like writing new data to be display to a second frame bufferā¦
Currently the ESP32 is fully supported. I have started adding support for other MCUās as well but I need a developer that has knowledge of these MCUās to help get them to the same level that the ESP32ās are at. I am not seasoned enough with the other MCUās to be able to tackle this task.
Oh. I forgot to mention one thing. You only need to worry about installing the basics into your OS. things like python, cmake, ninja and a c compiler. All other requirements are handled by the build program. It will collect MicroPython 1.23.0, LVGL 9.1.0, and any SDKās that are used like the ESP-IDF 5.2.0. The build script sets up the entire build environment for you. One command does it all. In the case of the ESP32 it even takes care of generating a partition file that is size matched to the firmware to maximize the amount of space for user code. For the ESP32 it also packages the firmware, partition and boot loader into a single binary making it easier to flash from any PC or even OTA
One thing that I havenāt seen mentioned is how to find the chip ID and flash size of the ESP32. That was a vitally important step that I was missing. I was assuming the flash size was something else based off the āmanufacturerāsā data sheet. These things come from literally anywhere. Correct me if Iām wrong, but I feel, in my very, very, limited experience, that doing a chip_id and flash_size should be the first step. Once again, I know NOTHING about any of this, especially with this reply coming under @kdschlosser introduction (which, by the way, makes you sound like the smartest dude on the planet). If I am wrong, please put me in my place and show me the way.
The chip and the flash size is something that the user could select.
So if you provided a dialog to do a config for an LVGL MicroPython binding you would let them choose the MCU they are using. Currently the ESP32 is the most supported MCU. STM32 is but only SPI and no DMA transfers. Same thing for the RP2.
My point is when they select the MCU options will become available to them to select the series of chip they are using and things like the flash size. enabling USB OTG. the number of lanes the SPRAM and the flash use. They would be given the ability to select the display and touch they are using as well as the type of connection being used for both the display and the touch. Because of how generic the API is and how universal it is across all the display and touch drivers you only need to provide 1 group of config settings for the different bus types and then one group for all of the display driver settingsā¦
The cool thing is I provided the ability so code that would get generated from say EEZ Studio could get baked right into the firmware or optionally the user could upload the source files. either way it would work.
I can put together a JSON file that lays out the entire API if that would helpā¦
I am far from itā¦
I simply put a large amount of thought into how to handle the binding and making the drivers and things of that nature. I have spent the better part of 2 years collecting information and writing the code to makes the binding a lot easier to compile and I wrote frameworks that make it a lot easier to add drivers or to be able to patch drivers for specific use cases without needing to write a whole new driver.
I have the build folder from a simple gauge I made on EEZ Studio. It includes two string output sections and some text blocks. I donāt know if I can upload the folder here so you can take a look at it, but I can try if youād like. I opened up the screen.c file and it looks to be written in C. You said that some of the bus driver stuff you did was written in C code and they expose the needed parts to python, would it be possible to do the same with the EEZ Studio build?
The code that gets generated by your app would need to be python. The amount of additional code that would need to be added to make everything work from C code would be pretty extensive and actually self defeating. The purpose to the binding is rapid development which means the ability to change the source files without having to recompile and flash firmware.