Getting Thermostat demo working with Elecrow ESP32 Terminal and Micropython

Hi, I’m currently trying out LVGL and SquareLine Studio for fun and profit.

For fun the Arduino platform, with the ESP32 devices, seems to “just work”, as long as you are OK with the app size limitations.

For profit projects will need to use the full Espressif development environment. However, installing the Espressif esp-idf is a descent down the rabbit hole of Python and OS systems versioning and compatibility woe and torment. And possibly forever breaking other software on your previously working laptop.

The only safe way is to install a fresh OS and ESP-idf tools on a clean VM. Possibility using Gitpod or Github workflows to create pristine disposable environments on the fly.

For the short term I decided to do something else. I purchases a ESP32s3 display module that already has a working binary of Micropython. What, with LVGL builtin, as well as SquareLine tested examples, what could be better; being able to quickly and easily test LVGL along with SquareLine studio with the ease of just loading python files into the device. No development environment setup nightmare. Just joy and bliss.

Several weeks into this ten minute project I’ve finally made some progress and would like to share how I finally got a SquareLine example to (mostly) run under Micropython for those that would like to try this themselves.

Additionally, maybe, those that have more Micropython/LVGL/SquareLine experience under their belt might be able to offer additional suggestions and improvements.

So here goes:

I built the SquareLine Studio example for the thermostat. I exported the UI and added a display driver setup wrapper around it. Using Thonny, uploaded the exported UI files and my wrapper python file. Pressed run to be dazzled by the thermostat UI on the display.

Well no.

Got an “AttributeError: ‘module’ object has no attribute 'SIZE’”. Well that’s nice, what on earth do I do to fix that. SquareLine studio is new to me, LVGL is new, as well as Micropython. Were do you even start. And “SIZE.CONTENT” seems to be some kind of magical thing. Is is a constant, an object? But is seems to have some kind of mystical workings that may or may not follow what seems to be python syntax rules.

After days of digging through LVGL source code it seems to be a getter, part of the lv object, that just returns a magic number to inform other layout objects to ignore the expected behavior and do something auto-magical behind the scenes.

Breaking this down and testing this in isolation produces this result.

Traceback (most recent call last):

 File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'SIZE'

As this is all new to me, more culling through source code along with a few plausible guesses revealed the error to likely be a bug in the SquareLine emitted code.

The fix is change this to:


Additionally I found a similar error with “ lv.ANIM_REPEAT.INFINITE”.
It should be “ lv.ANIM_REPEAT_INFINITE”.
There are likely more examples.

So here is what I did to fix the code in

  1. Replace all instances of “lv.SIZE.CONTENT” with “lv.SIZE_CONTENT”
  2. Replaced all instances of “lv.font_montserrat_20” with “lv.font_montserrat_16”. Because “lv.font_montserrat_16” is a builtin font and a quick way around the font error.
  3. Comment out:
def Fan_Speed_Control_eventhandler(event_struct):

##Comment out for debugging, because I don’t want to bother trying to fix this for now.

##   event = event_struct.code
##   if event == lv.EVENT.VALUE_CHANGED and True:
##      fan_speed_value( event_struct ) 


  1. Add a wrapper to initialize the drivers and code and then include the UI code.

———— Wrapper Code: ——

import time
from espidf import VSPI_HOST
from ili9XXX import ili9488
from ft6x36 import ft6x36 
from machine import Pin, I2C
import lvgl as lv

# Light up the screen
p16 = Pin(16, Pin.OUT)

# Creating the display object
## Should this be  (as I’ve seen in other examples) disp = 
## I’ve run it both ways. Either seems to work.
dispp = ili9488(miso=14, mosi=13, clk=12, cs=3, dc=42, rst=18,backlight=46, backlight_on=1, power_on=1,
               spihost=VSPI_HOST, mhz=20,power=-1,
               factor=16, hybrid=True, width=320, height=480,
               invert=False, double_buffer=True, half_duplex=False)

# Create a touch screen object
touch = ft6x36(sda=2, scl=1)

import ui

——— End wrapper code ————

That’s it.

There are still some issues I have not fixed yet in the demo. The temperature did not display in my test.

The big issue that will affect nearly all UIs you may want to create is the “lv.SIZE.CONTENT” —> “lv.SIZE_CONTENT” and related issues. The rest are more related to the demo and not necessarily an issue when you create a UI from scratch.

Now some questions.
Does “lv.SIZE.CONTENT” work in any version of Micropython/LVGL? I tested with a couple of versions. Seems the this would be an issue for any version, and therefor a bug.

I found the UI was very slow to respond to touch input. Is that because I need to fix more code issues. Or, is Micropython possibly not a truly viable platform for LVGL, except for maybe, simple relatively static dashboards.

I can see where compiling a whole new Micropython binary with the created UI embedded may improve performance, but that defeats the whole idea of the “ease” of using Micropython. Once I have a proper ESP32 complier toolchain setup, I’ll likely just use C++.

Finally, I used an Elecrow ESP32 Terminal, with SPI display interface, for this testing. I think the ESP32 Terminal is a really nice display module and I don’t hold these Micropython struggles (“learning opportunities”) against it.


Thanks for the feedback, we’ll review the micropython code exporter in SLS.
About the 2nd part: You’re right, writing complex GUIs in MicroPython can be slower than C.

1 Like

Thanks for info.

The ‘lv.SIZE.CONTENT’ should be available as such in release/v8 branch of lv_micropython. If you build micropython for yourself you should build the release/v8 branch now because SquareLine Studio currently (v1) exports LVGL/lv_micropython v8 compatible MicroPython code. The ‘lv.SIZE_CONTENT’ is currently seen in the master (v9) branch of lv_micropython. In LVGL major versions you can see API changes like this one.