After almost 10 months of (slow) development, I’m almost at the end of my first “big” project. With three ESP32 microcontrollers, connected via Bluetooth LE (GATT protocol), I built a simple “tractor board computer” for a friend, who is renovating an old Deutz D 8006.
Interface (see video in shared album)
The main board has a non-touch 320x480 colour LCD with a two (soon to be three) page layout. It has a simple encoder and button-based navigation system, with standardized top/bottom bars. It is built upon a “view” concept: from the start, this project has been thought to be expandable (even if it won’t, I can reuse much code for future ones). Views are structs that define a “builder” function for the main content of each screen, a top bar configuration struct and a bottom bar configuration struct for buttons and contextualized menus (a long-press can show a context menu similar to the ones used in old Nokia phones, but this feature is unused in the current firmware).
View changes are stored in a stack in order to implement a common navigation pattern (same as Android/iOS).
Since this should never distract the driver, it has an automatic backlight regulation system, which automatically triggers a dark theme when brightness goes below a certain limit. The light theme is automatically enabled otherwise, for optimal visibility. Manual brightness can be set from a menu, and it will be saved in the NVM.
A few lvgl “tricks” were done to let the encoder action highlight a menu row containing a label and a control such as a button and a slider, and even more (not great) tricks were also made for automatically focusing the inner control of the menu row.
All the dynamic data received from the BLE devices (via notifications triggered from the sensors) is stored in a big but very tidy struct, divided by data source (engine and GPS). A timer periodically tells lvgl to refresh the widget tree by reading the latest values of these readings, but in an asynchronous manner, not related to the sensor update speed.
There are two secondary boards for this projects, one (called EngineSense) is a multipurpose acquisition board. It is currently used to read engine RPM from a Hall sensor that reads the cooling fan RPM. A coefficient for getting the engine RPM can be set via Bluetooth LE and will be stored in the ESP32 non-volatile memory. By doing a few other calculations, you can also get the driveshaft RPM (which is quite easy to display since there are only two speed shifts for it). It also reads the external engine temperature and the cooling air temperature (yes, it’s an air-cooled engine) from an I2C IR thermometer.
The other board, called Navis, supports standard NMEA GPS modules and it’s used for reading speed and heading and setting the correct time when it gets the first fix.
The two peripheral boards use the exact same codebase. This is done because most of the OTA, BLE and general management code is common to both boards. A build script selects the correct sdkconfig file and builds both BIN images in two separate runs, by changing GPIO configuration and adding/removing device drivers for each one. These images can be transferred to an iOS device for a wireless firmware upgrade. You can also change the settings in order to build a customized device with different GPIO numbers and device drivers/BLE services.
You’ll find everything from the PCB designs to the firmwares (and even a few failed firmware tests with other programming languages/libraries). The only thing that is missing is a small utility I wrote for my iPhone (using SwiftUI) to update the three firmwares wirelessly (BLE and WiFi combined together) because the two sensor boards are not accessible after being installed.
iCloud public album (no login required): https://www.icloud.com/sharedalbum/#B0jG4Tcsmu9Jt9U
There are no videos of the tractor running with the device installed because some engine parts are not ready. If you need more pictures/videos or information, I’ll be glad to share them. I will notify you with a comment when new photos or videos will be available.
I don’t plan to further expand this project due to a wrong choice… I used 256kB RAM ESP32 modules and the display one is quite tight on it (for example I had to use NimBLE instead of Bluedroid for BLE). Then, after almost a year working on it, I’d like to start something new, but I will continue to fix issues on this project as they will inevitably come up.
Specifically, I recently bought a 1993 HP 48G+ calculator and, well, I’d like to at least try to build something similar with an unused STM32F7 Nucleo board and an e-ink screen, but by programming it in… Swift. And lvgl obviously. Exams permitting.
There could be many, many more things to say about this project, but it’s getting late.
Thanks for this great library!