Skip to content

WIP: add board battery percentage#403

Closed
446564 wants to merge 2 commits into
meshcore-dev:devfrom
446564:batt-percent
Closed

WIP: add board battery percentage#403
446564 wants to merge 2 commits into
meshcore-dev:devfrom
446564:batt-percent

Conversation

@446564

@446564 446564 commented Jun 17, 2025

Copy link
Copy Markdown
Contributor

defaults to lipo with no changes to existing variants

  • adds two chemistry types to start BAT_LIPO and BATT_LIFEPO
  • adds getBattPercent to MainBoard
  • adds getBattType to MainBoard
  • companion UI now uses getBattPercent in renderBatteryIndicator

defaults to lipo with no changes to existing variants

- adds two chemistry types to start lipo and lifepo
- adds getBattPercent to MainBoard
- adds getBattType to main board
- companion UI now uses getBattPercent in renderBatteryIndicator
@jbrazio

jbrazio commented Jun 18, 2025

Copy link
Copy Markdown
Contributor

How about the mobile apps ? This is where most people interact with the devices and the batt% is calculated by the app itself based on the telemetry.

Today all batt% are wrong because they are not reflecting the non-linear nature of LiPo when trying to translate voltage to "capacity".

I would suggest to update your implementation of getBattPercent() to better estimate the "capacity" of a LiPo.
Then it would be great for the mobile apps to start using this instead. :-P

Comment thread src/MeshCore.h Outdated
@446564

446564 commented Jun 18, 2025

Copy link
Copy Markdown
Contributor Author

I would suggest to update your implementation of getBattPercent() to better estimate the "capacity" of a LiPo. Then it would be great for the mobile apps to start using this instead. :-P

I'm working on some ideas to approach battery curves, thinking of maybe a map. Just dividing the usable range by 100 and mapping to the closest. rounding down seems better than rounding up.

Then from there mapping the values to match the actual average discharge curves.

@446564 446564 changed the title add board battery percentage WIP: add board battery percentage Jun 18, 2025
@446564

446564 commented Jun 18, 2025

Copy link
Copy Markdown
Contributor Author

This last change is giving me trouble, it should work fine but when I flash it on a companion with a display it hangs before rendering the screen. Something with the way I'm grabbing the percentage from the map but no compiler errors so I'm not sure what is wrong.

Any help is appreciated. It does not hang when flashing on a companion without a display, i.e. T1000-e.

@446564

446564 commented Jun 19, 2025

Copy link
Copy Markdown
Contributor Author

turns out arduino can't do maps, at least without a 3rd party implementation. I switched to an array of struct but the jump in storage was a bit much, from 48 bytes to 240 or so for one battery curve. I wonder if two arrays of ints is less overhead, just use the index to reference each half of the pair..

@jbrazio

jbrazio commented Jun 19, 2025

Copy link
Copy Markdown
Contributor

Keep it simple.. lookup tables.

#define TABLE_SIZE 21

const uint16_t millivoltTable[TABLE_SIZE] = {
    4200, 4150, 4120, 4100, 4050,
    4000, 3850, 3800, 3750, 3700,
    3650, 3600, 3500, 3450, 3400,
    3300, 3200, 3100, 3000, 2800,
    2700
};

const uint8_t percentTable[TABLE_SIZE] = {
    100, 95, 90, 85, 80,
    75, 70, 65, 60, 55,
    50, 45, 40, 35, 30,
    25, 20, 15, 10, 5,
    0
};


uint8_t getBestFittingValue(uint16_t mV) {
    uint8_t ret = 0;
    uint16_t min = (uint16_t)-1; // use a large initial value

    for (uint8_t i = 0; i < TABLE_SIZE; i++) {
        uint16_t diff = abs(millivoltTable[i] - mV);
        if (diff < min) {
            min = diff;
            ret = percentTable[i];
        }
    }

    return ret;
}

You can have multiple tables like millivoltTableLiPo, millivoltTableLiFe, etc.
Update the getBestFittingValue to have an additional argument [pointer] to the table.. and use it to look up the final value.

@446564

446564 commented Jun 19, 2025

Copy link
Copy Markdown
Contributor Author

this is working except for the part using classes as I have no idea what i'm doing.

I went with one multidimensional array as it was significantly less memory than multiple arrays.

@jbrazio

jbrazio commented Jun 19, 2025

Copy link
Copy Markdown
Contributor

one multidimensional array as it was significantly less memory than multiple arrays

This is not true.. let's have a look:

  1. Your array is uint16_t * 3 * 100 = 600 bytes.
  2. Those two arrays are uint16_t * 21 (42 bytes) + uint8_t * 21 (21 bytes) which is 63 bytes total.

Even if you add another 42 bytes for the LiFe array.. we are far away from your implementation memory footprint.

@446564

446564 commented Jun 19, 2025

Copy link
Copy Markdown
Contributor Author

I'm going for 1% resolution, so 3 x 100 elements for two chemistries and the charge scale.

I suppose we could get it a bit slimmer by having only the chemistry curves and infer the SoC percentage but the index we found it during the scan

@446564

446564 commented Jun 19, 2025

Copy link
Copy Markdown
Contributor Author

either way, I have it all sorted out and removed the class idea. just finishing up adding the lifepo4 values and will squash and resubmit a fresh PR

@446564 446564 closed this Jun 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants