Repository navigation
Read the sensors and the pack on their own threads - #6
Merged
Merged
Conversation
taciturnaxolotl
force-pushed
the
feat/threaded-sources
branch
from
September 26, 2026 18:01
8681f05 to
195e04a
Compare
The three inputs have incompatible shapes. The Arduino pushes frames at 20 Hz. The BMS is request/response and a reply can take most of a second. The strategizer computes for tens of milliseconds. None of that fits in a render loop that must not stall for longer than a frame. So each source blocks freely on its own thread and publishes into its own slot behind its own mutex, and the UI takes a snapshot per frame. Separate locks on purpose: a slow BMS reply must not hold up the sensor feed, and neither can stall the display. This needed no change to BmsHub. Its blocking read with a timeout is exactly right on a dedicated thread and was only wrong in a render loop, so threading deleted that work rather than moving it. LVGL 9.3 ships a pthread OS layer, so LV_USE_OS goes from LV_OS_NONE to LV_OS_PTHREAD and every call into LVGL is wrapped, lv_timer_handler included. Missing that one is the classic mistake: the corruption looks random and only appears under load. Checked by hammering a widget from a second thread at about 5 kHz while rendering. race_telemetry_t moves out of the dashboard header into include/telemetry.h. A source producing telemetry should not include a UI header to learn its shape. It grows pack voltage, current, state of charge and both energy estimates, plus a burn window for the strategizer to fill in. Freshness is a field rather than an inference. With threads, an idle BMS and a dead BMS thread look identical, so each group carries the time it was last updated and anything older than two seconds reads invalid. telemetry_source.c is replaced by sources.c. BmsHub is optional at build time exactly as SensorHub is, so all four combinations still build and a laptop with no hardware still gets the demo. The warnings job also gains -Iinclude, and slot_stopping is guarded: it is only called by the source threads, so it was unused in the demo-only build.
taciturnaxolotl
force-pushed
the
feat/threaded-sources
branch
from
September 26, 2026 18:02
195e04a to
cf8b51d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Currently we have a bunch of different data sources which all have different timing requirements
If we move the blocking work to threads then we can keep the renderer running at a decent speed
LVGL threading
We can use LVGL's pthread layer to manage the different threads in an os agnostic way.
lv_lock()must wraplv_timer_handler()on every call since LVGL walks its object tree and redraws requiring that nothing touches any of the widget data.BMS
this also adds the bms data layer from https://github.com/HEEV/BmsHub