I think that this project came out very nicely and the people I gifted clocks to seem to genuinely appreciate them, but the technical part that most interested me is the web-based GUI interface. I first implemented this for my Tiny1C tCamMini thermal imaging camera and adapting it for this project was pretty quick and easy.
I am in no way a web developer. Learning HTML, CSS and javascript and all the other technologies employed in a modern web page seems overwhelming to me - and typically not what I have to worry about as an embedded systems engineer. But I do know C, and LVGL, and networking pretty well. I have done a lot of commercial and personal projects using LVGL and I find it to be a very useful embedded systems GUI library. Some years ago I wrote an experimental project that used a web browser canvas as the display buffer for LVGL and sent the pixmap updates to the web browser over a web socket. It worked surprisingly well but didn't scale well to larger displays, 32 bit pixels or highly dynamic graphics because of the amount of pixel data that had to be shoved through the web socket.
When I started the Tiny1C camera, I wanted a responsive web based GUI served from an ESP32 but the idea of spending weeks or months learning how to create a traditional web page felt unachievable. However, the LVGL folks have long been using emscripten to encapsulate demos in web pages. Emscripten compiles traditional code (like C) to Web Assembly that can run in a web browser. It can use other libraries like SDL to render 2D images in a canvas. The LVGL developers simply wrote a LVGL driver on top of SDL which allows a LVGL C program to be compiled and run in a web page. Really cool.
I thought well what if I send commands instead of pixel data over the web socket and let the entire GUI portion of the program be compiled for and run in the web browser. The benefits would be much, much less data sent over the socket and the incredible performance of modern computers running the Web Assembly would offload the ESP32 of all graphics requirements. So I implemented a simple SET/GET/RESPONSE command protocol with helpers that are registered on both sides implementing the commands. It works really well. And was easy to port because I only had to rewrite the command handlers and specific LVGL GUI functionality the clock would need.
How it works in practice is that the program is now split into two parts. One built by Emscripten that includes the GUI code, and one built by the Espressif IDF that includes the clock code. A neat thing is that they share some code (e.g. the command code). The Emscripten project includes a very simple HTML page that calls the Web Assembly program when it's loaded. The Web Assembly program then initiates a web socket with the ESP32 and they both start processing commands. In reality the compiled Web Assembly program is pretty big. So I ended up compressing the built file which is stored in the ESP32 binary and sent by the ESP32's web server to the web browser initially which uncompresses and runs it.

To see how it works, consider the LCD Backlight Brightness slider in the GUI control panel (each control is its own module) When the control panel starts running the Brightness slider loads a GET Brightness command which is sent to the ESP32. The ESP32 then gets the brightness from persistent storage and sends it back with a RESPONSE command. The RESPONSE command references the original command so the command processor knows to execute the handler associated with brightness which updates the LVGL slider object. When the user drags the slider then a LVGL callback is called periodically and it loads a SET Brightness command which is received by the ESP32 which then updates both the LCD backlight brightness and persistent storage.
User navigation around the GUI, for example moving between the main control page and a sub-page like the Wi-Fi / Network sub-page, is completely invisible to the ESP32, except for handling the GET commands which the newly displayed page sends the ESP32 to get the current state to display.
In fact the Faux Nixie Clock actually has LVGL running in both the web browser and the ESP32. But on the ESP32 it's pretty simple. It displays the bitmap nixie "digits", a "nixie" colon, the date and an optional status message. Not particularly taxing but LVGL made the job easy and with anti-aliased fonts, the entire display looks good.
I suspect a seasoned web developer might roll their eyes at this approach but it let me build a pretty good and responsive web interface in a fraction of the time which is important when you have a couple weeks until Christmas.
Dan Julio
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.