Activate Electric Air Module (0x8E) for cell-level battery monitoring - #213
Activate Electric Air Module (0x8E) for cell-level battery monitoring#213DieterMayerOSS wants to merge 1 commit into
Conversation
57e6262 to
f536303
Compare
|
Thanks a lot for the contribution. The implementation is clean and I appreciate the detailed work on the EAM packet. At the moment I am not fully sure what EAM adds over the existing HoTT mapping:
There is also a possible compatibility concern because some HoTT receivers may already use Electric Air (0x8E) for their own telemetry, and HoTT only allows one sensor of each type on the bus. So I would like to better understand the specific benefit:
Also, since |
|
Thank you for the thoughtful review. You're right that for HW5/Kontronik the cell data is replication, not true per-cell — that's a fair call. But I'd like to offer a different framing for the EAM addition that I think addresses your concerns: The UniSens-E (a well-established HoTT sensor from SM Modellbau) lets the user pick one of GAM / EAM / ESC / Vario as the module role. That's how it coexists with other sensors on the bus — the HoTTv4 "one per type" rule means flexibility in which type you announce as is the actual feature. msrc currently auto-publishes as ESC (when an ESC is configured) and GAM (when So the use case is:
That said — your For this specific PR: would you accept it as-is (EAM as opt-in only), or would you prefer I close it and submit (a) a smaller PR that just routes HW5/Kontronik cells to |
|
Thank you for the careful review — your concerns are valid, and I want to step back and propose a broader direction rather than defending the EAM-specific PR. Looking at the established pattern in the HoTT ecosystem: UniSens-E (SM Modellbau) — probably the most widely used HoTT telemetry sensor in the community — lets the user pick one role for the sensor: GAM, EAM, ESC, or Vario. The HoTTv4 "one per type" rule isn't a limitation, it's the actual design contract: each smart sensor announces as one type, and several sensors can coexist on the bus by picking different types. msrc currently auto-publishes on multiple types simultaneously (ESC + GAM + Vario), which is convenient when msrc is alone on the bus but causes collisions when combined with other sensors (UniSens-E, JLog). Would you be open to a broader refactor where msrc adopts the same single-role pattern? Concretely:
If yes, I'd close this PR and open a new one for the broader change. If you'd rather keep the current multi-role auto behavior, I'll close this PR and submit a smaller alternative that just routes HW5/Kontronik Either direction is fine — what would you prefer? |
|
Thank you, this is a good and well-reasoned proposal. I need to analyze it more carefully before deciding the right direction. I agree that the current multi-module HoTT behavior can be convenient, but it can also create conflicts when other HoTT sensors are present on the bus. Your proposed broader approach may be better than adding EAM as a special case, but I want to review the implications for existing users, config compatibility, msrc_link, and the current ESC/GAM/Vario routing before making a decision. So please give me a bit of time to think about it. I will review the HoTT mapping and then decide whether a broader configurable HoTT role/output model makes sense, or whether it is better to keep the current behavior and make only a smaller change. |
|
No rush — take all the time you need. Architecture decisions are exactly the kind of thing worth thinking through carefully, especially when backwards-compatibility and the msrc_link binary protocol are involved. If it would help your evaluation, I'm happy to:
Otherwise I'll just wait for your decision and act accordingly. |
…E style) After review feedback on PR dgatf#213, this generalizes the EAM activation into a module-role selector that lets the user choose which HoTT module types msrc announces on the bus -- matching the pattern established by UniSens-E, oXs_on_RP2040, and openXsensor. Per HoTTv4 "one sensor per type per bus", smart sensors coexist by each announcing as a different type. msrc's previous behaviour (auto- enable on every type whose data source was present) caused collisions when other smart sensors were on the bus. This change gives the user explicit per-role control. Architecture changes: - shared.h: `spare7` repurposed as `hott_modules_enabled` (uint8 bitmask). Bit 0 = ESC (0x8C), bit 1 = GAM (0x8D), bit 2 = EAM (0x8E), bit 3 = Vario (0x89). Same byte position, no layout change. - config.c: default 0x0B (ESC + GAM + Vario, EAM off) preserves pre-bitmask behaviour for new flashed configs. - hott.c: existing auto-enable wiring kept intact; a final masking pass at the end of set_config() clears `is_enabled[HOTT_TYPE_*]` for roles the user disabled. Pre-bitmask configs (`hott_modules_enabled == 0`) fall back to the legacy default at runtime, so existing flashed units keep working without a reflash or config wipe. EAM (0x8E) frame implementation: - Replace stale internal `HOTT_ELECTRIC_*` enum (was marked "shouldnt be used") with one mirroring the wire-frame layout: 7 cell slots, battery 1/2, two temperatures, altitude, current, drive voltage, capacity, two climb rates, RPM, speed. - Add `electric_air[HOTT_ELECTRIC_COUNT]` to `hott_sensors_t`. - Grow `is_enabled[]` from 4 to 5 so `HOTT_TYPE_ELECTRIC` (=4) is addressable (was a latent OOB). - Add `electric_triggers_t` enum + electric arrays in `triggers_value_t` / `triggers_menu_t`, with sensible alarm defaults. - Add `alarm_electric_air_t` bitmask enum. - Add binary frame handler in `format_binary_packet` with canonical scaling (cells 0.02 V steps, battery 0.1 V, temp +20 offset, altitude +500 offset, current 0.1 A, capacity 10 mAh, climb rate * 100 + 30000). - Add text-mode menu handler in `format_text_packet`. - Wire HW5 and Kontronik cell_voltage/voltage/current/capacity/temps into `electric_air[]` when the EAM bit is set. Cell voltage is replicated across the auto-detected cell count (HW5 and Kontronik only report average cell voltage, not per-cell). msrc_link GUI: - Four checkboxes "ESC / GAM / EAM / Vario" replace the previous attempt at an EAM-only checkbox. Receiver tab, under cbReceiver. - Read/write of the bitmask in setUiFromConfig / getConfigFromUi. - Legacy auto-default (0x0B) displayed when read value is 0. Built with Pico SDK 2.2.0 / ARM GCC 15.2 and Qt 6.11.1 / MinGW 13.10.
f536303 to
f259931
Compare
|
Pivoted the implementation to address your concerns more comprehensively. The PR now does what we discussed in the comments: Multi-checkbox Backward-compatible at runtime. Existing flashed configs have Implementation strategy — instead of gating each ESC/GAM/Vario auto-enable inline (which would have touched ~10 sites in set_config), I kept the existing auto-enable wiring intact and added a final masking pass at the end of set_config that clears EAM frame kept from the previous revision — that part of the work is still useful regardless of how role selection happens. This also gives users a way to coexist msrc with a UniSens-E or JLog on the same bus: uncheck the role the other sensor occupies. Aligns msrc with the multi-sensor coexistence story. Let me know if you'd like this scope dialed back further, or if a different role-selection UI (radio buttons / single combo / per-role auto-detect) would fit better. |
…E style) After review feedback on PR dgatf#213, this generalizes the EAM activation into a module-role selector that lets the user choose which HoTT module types msrc announces on the bus -- matching the pattern established by UniSens-E, oXs_on_RP2040, and openXsensor. Per HoTTv4 "one sensor per type per bus", smart sensors coexist by each announcing as a different type. msrc's previous behaviour (auto- enable on every type whose data source was present) caused collisions when other smart sensors were on the bus. This change gives the user explicit per-role control. Architecture changes: - shared.h: `spare7` repurposed as `hott_modules_enabled` (uint8 bitmask). Bit 0 = ESC (0x8C), bit 1 = GAM (0x8D), bit 2 = EAM (0x8E), bit 3 = Vario (0x89). Same byte position, no layout change. - config.c: default 0x0B (ESC + GAM + Vario, EAM off) preserves pre-bitmask behaviour for new flashed configs. - hott.c: existing auto-enable wiring kept intact; a final masking pass at the end of set_config() clears `is_enabled[HOTT_TYPE_*]` for roles the user disabled. Pre-bitmask configs (`hott_modules_enabled == 0`) fall back to the legacy default at runtime, so existing flashed units keep working without a reflash or config wipe. EAM (0x8E) frame implementation: - Replace stale internal `HOTT_ELECTRIC_*` enum (was marked "shouldnt be used") with one mirroring the wire-frame layout: 7 cell slots, battery 1/2, two temperatures, altitude, current, drive voltage, capacity, two climb rates, RPM, speed. - Add `electric_air[HOTT_ELECTRIC_COUNT]` to `hott_sensors_t`. - Grow `is_enabled[]` from 4 to 5 so `HOTT_TYPE_ELECTRIC` (=4) is addressable (was a latent OOB). - Add `electric_triggers_t` enum + electric arrays in `triggers_value_t` / `triggers_menu_t`, with sensible alarm defaults. - Add `alarm_electric_air_t` bitmask enum. - Add binary frame handler in `format_binary_packet` with canonical scaling (cells 0.02 V steps, battery 0.1 V, temp +20 offset, altitude +500 offset, current 0.1 A, capacity 10 mAh, climb rate * 100 + 30000). - Add text-mode menu handler in `format_text_packet`. - Wire HW5 and Kontronik cell_voltage/voltage/current/capacity/temps into `electric_air[]` when the EAM bit is set. Cell voltage is replicated across the auto-detected cell count (HW5 and Kontronik only report average cell voltage, not per-cell). msrc_link GUI: - Four checkboxes "ESC / GAM / EAM / Vario" replace the previous attempt at an EAM-only checkbox. Receiver tab, under cbReceiver. - Read/write of the bitmask in setUiFromConfig / getConfigFromUi. - Legacy auto-default (0x0B) displayed when read value is 0. - gbHottRoles visibility gated on HOTT receiver selection in on_cbReceiver_currentTextChanged(), with defensive setVisible(false) in the constructor -- same pattern as cbVarioAutoOffset and gbFuelPressure. Without this gate the GroupBox was shown for every protocol. Built with Pico SDK 2.2.0 / ARM GCC 15.2 and Qt 6.11.1 / MinGW 13.10.
f259931 to
ee8a080
Compare
|
Heads-up: force-pushed an amend that adds protocol-conditional |
…E style) After review feedback on PR dgatf#213, this generalizes the EAM activation into a module-role selector that lets the user choose which HoTT module types msrc announces on the bus -- matching the pattern established by UniSens-E, oXs_on_RP2040, and openXsensor. Per HoTTv4 "one sensor per type per bus", smart sensors coexist by each announcing as a different type. msrc's previous behaviour (auto- enable on every type whose data source was present) caused collisions when other smart sensors were on the bus. This change gives the user explicit per-role control. Architecture changes: - shared.h: `spare7` repurposed as `hott_modules_enabled` (uint8 bitmask). Bit 0 = ESC (0x8C), bit 1 = GAM (0x8D), bit 2 = EAM (0x8E), bit 3 = Vario (0x89). Same byte position, no layout change. - config.c: default 0x0B (ESC + GAM + Vario, EAM off) preserves pre-bitmask behaviour for new flashed configs. - hott.c: existing auto-enable wiring kept intact; a final masking pass at the end of set_config() clears `is_enabled[HOTT_TYPE_*]` for roles the user disabled. Pre-bitmask configs (`hott_modules_enabled == 0`) fall back to the legacy default at runtime, so existing flashed units keep working without a reflash or config wipe. EAM (0x8E) frame implementation: - Replace stale internal `HOTT_ELECTRIC_*` enum (was marked "shouldnt be used") with one mirroring the wire-frame layout: 7 cell slots, battery 1/2, two temperatures, altitude, current, drive voltage, capacity, two climb rates, RPM, speed. - Add `electric_air[HOTT_ELECTRIC_COUNT]` to `hott_sensors_t`. - Grow `is_enabled[]` from 4 to 5 so `HOTT_TYPE_ELECTRIC` (=4) is addressable (was a latent OOB). - Add `electric_triggers_t` enum + electric arrays in `triggers_value_t` / `triggers_menu_t`, with sensible alarm defaults. - Add `alarm_electric_air_t` bitmask enum. - Add binary frame handler in `format_binary_packet` with canonical scaling (cells 0.02 V steps, battery 0.1 V, temp +20 offset, altitude +500 offset, current 0.1 A, capacity 10 mAh, climb rate * 100 + 30000). - Add text-mode menu handler in `format_text_packet`. - Wire HW5 and Kontronik cell_voltage/voltage/current/capacity/temps into `electric_air[]` when the EAM bit is set. Cell voltage is replicated across the auto-detected cell count (HW5 and Kontronik only report average cell voltage, not per-cell). - Raise STACK_RX_HOTT from 450 to 700 words: the electric_air[] array and the electric trigger arrays enlarge hott_task's stack frame by ~110 words. Without this bump the task overflowed its stack on boot, corrupting adjacent RAM and breaking USB enumeration. Found during hardware bring-up testing. msrc_link GUI: - Four checkboxes "ESC / GAM / EAM / Vario" replace the previous attempt at an EAM-only checkbox. Receiver tab, under cbReceiver. - Read/write of the bitmask in setUiFromConfig / getConfigFromUi. - Legacy auto-default (0x0B) displayed when read value is 0. - gbHottRoles visibility gated on HOTT receiver selection in on_cbReceiver_currentTextChanged(), with defensive setVisible(false) in the constructor -- same pattern as cbVarioAutoOffset and gbFuelPressure. Without this gate the GroupBox was shown for every protocol. Built with Pico SDK 2.2.0 / ARM GCC 15.2 and Qt 6.11.1 / MinGW 13.10.
ee8a080 to
ed46f4e
Compare
|
Force-pushed again — this time a real bug found during hardware bring-up on a Pico. The EAM struct additions in this PR (electric_air[HOTT_ELECTRIC_COUNT] in hott_sensors_t, plus the electric arrays in triggers_value_t / triggers_menu_t) enlarge hott_task's stack frame by roughly 110 words. That overflowed STACK_RX_HOTT (was 450 + STACK_EXTRA). On real hardware the symptom was nasty and non-obvious: the overflow corrupted adjacent RAM, the USB task's data got clobbered, and the board failed USB enumeration entirely — Windows just reported "USB device not recognized", no COM port at all. It builds clean and looks fine in review; it only shows up when you flash it. Fix in this push: STACK_RX_HOTT raised 450 -> 700 words (constants.h). With that the board boots and enumerates normally, and an EAM frame built from synthetic sweep values comes through cleanly. Flagging it explicitly because this class of bug — a struct grows, the task stack doesn't — is invisible to code review and CI. Might be worth a general note for future HoTT frame changes. |
|
Thanks for the update. I understand the goal better now, but I am still not fully convinced this should be merged as-is. This is not fixing a current bug in MSRC; it adds a new configuration model for a relatively specific HoTT coexistence use case. That can be useful, but it also adds non-trivial complexity: new GUI state, a new persisted config field, legacy handling, an EAM packet path, new alarm/menu entries, extra stack usage, and more HoTT role combinations to test. Before accepting this, I would prefer to test it on real hardware and confirm that the benefit is worth the added complexity. In particular, I want to verify whether using EAM instead of GAM actually preserves the useful telemetry in a practical setup, and whether the transmitter displays it in a way that is clearly better or necessary. So for now I am not rejecting the idea, but I am not ready to merge it yet. I will need to test it and think a bit more about whether MSRC should support this level of HoTT role configurability, or whether it is better to keep the current simpler behaviour. |
Motivation
The HoTT Electric Air Module (EAM, sensor ID
0x8E) is the spec-defined module for electric models with cell-level battery monitoring. msrc had the frame struct defined but no dispatch —HOTT_ELECTRIC_AIR_MODULE_IDwas marked "not used, for internal Hott telemetry" and never reached the polling switch.Per HoTTv4 rules:
What this PR does
enable_eamconfig flag (reusesspare7, no struct layout change; defaults tofalsefor backward compatibility)format_binary_packetandformat_text_packetdispatchHOTT_ELECTRIC_*enum with one mirroring the wire-frame layout (7 cell slots, battery 1/2, temps, altitude, current, drive voltage, capacity, climb rates, RPM, speed)electric_air[]array tohott_sensors_tis_enabled[]from[4]to[5]soHOTT_TYPE_ELECTRIC = 4is addressable (was latent OOB)electric_triggers_tenum + electric arrays intriggers_value_t/triggers_menu_twith sensible alarm defaultsalarm_electric_air_tbitmask enumenable_eamis set, wires HW5 and Kontronik ESC data intoelectric_air[]: average cell voltage replicated across the auto-detected cell count, plus battery voltage, drive voltage, current, capacity, and ESC/BEC temperaturesThe msrc_link GUI would need a corresponding "Enable EAM" checkbox to expose the flag to users — suggested as a follow-up.
Verification
hott.c,shared.h(config struct),config.c(default)