Skip to content

Max17205 calibration and capacity persistence#121

Merged
plskeggs merged 16 commits into
oresat:masterfrom
plskeggs:max17205-refactor-fix
Aug 24, 2025
Merged

Max17205 calibration and capacity persistence#121
plskeggs merged 16 commits into
oresat:masterfrom
plskeggs:max17205-refactor-fix

Conversation

@plskeggs

@plskeggs plskeggs commented Jul 6, 2025

Copy link
Copy Markdown
Member

Major improvements to battery fuel gauge:

  1. use all values from wizard for m5 EZ model
  2. rework hardware and firmware reset handling for MAX17205 so we can do runtime register updates without wasting a MAX17205 flash cycle (limited to 7 total)
  3. adjust these with results from a full m5 EZ model learning run (7 full charge/discharge cycles)
  4. move flash_f0 handling to common folder from app_bootloader
  5. allocate 2 flash pages from end of application flash area for history storage
  6. add storage and retrieval of MIXCAP and REPCAP from ARM flash so capacity remains fairly accurate through the daily reset cycles by the C3 system
  7. add checking for critically low batteries and waiting for a charge cycle to reduce load (at least from this card)
  8. replace duplication of code for pack 1 and pack 2 by combining data into an array of structures and iterating that when needed
  9. add ability to dump MAX17205 learning logs
  10. separate out printing of non-volatile registers from volatile registers

plskeggs added 10 commits June 18, 2025 15:34
Fixes to cleanup PR:
- fix assert bug
- enable debug print
- enable NV update code
- change NV register array to match Wizard output for all registers
(not just the ones in the Google doc)
- make prompt_nv_memory_write() return true if actually written
- fix name of max17205Read() -- no longer max17205ReadRaw()
- if nv was actually written, only then print the prompt to re-flash
with update disabled and effectively halt

Use correct parameter names in max17205.h to match c file.
Make integer size conversions explicit.
Make shadow RAM changes affect operation:
- Add a chip firmware reset function.
- Use this in start, stop, hardware reset, and nv prompt code.
- Add NFullSOCThr and nRippleCfg settings per datasheet.

Remove trailing whitespace. Remove spaces in comment blocks at EOLs.
Consolidate the PACKCFG settings in one place.

Also fix problem with logging of don't vs. do match values.
Clear POR bit in status register each time we reset.

Add a small delay in the retry loops looking for POR.

Be sure to check sentinel values on register array, not
just length.

Make matching vs. non-matching registers more clear/readable.
Add learning and capacity functions:
- Add functions to read and write the learning state.
- Add a function to write capacity.
- Improve logging and add learning completion.
- Dump learning history.
- Dump volatile registers used by learning. The n* registers are not
updated generally speaking unless a write to the limited user config NV
occurs or unless the specific register is part of life logging, and that
has been updated.
- Periodically check for full condition and update learning.

Improve behavior in low battery conditions:
- Add function to check for charge complete and force transition to
learning complete.
- Add functions to check for critically low battery and wait for
charging.
- Improve startup to do as little as possible until battery
state known.

Update code based on full learning cycles:
- Set nFullCapNom and nRComp0 to learned values.

Improvements:
- Print charge and discharge stat lines each update.
- Print instantaneous current not just average, max, and min.
- Update learning complete before possibly writing NV.
- Separate printing volatile registers from printing
non-volatile; only print volatile during thread loop.
- Separate NV writing from NV RAM writing.
- Update and display everything including learn state before
possibly writing to flash.

Cleanup:
- Fix typo in current_battery_state_machine_state variable name.
- Make local functions static.
- Make update_battery_charging_state able to be re-enabled if necessary.
- Remove unnecessary cell balancing stuff.
- Move summary display of information after all register reads to
improve readability.
- Clean up logging for heater control.
- Periodically dump registers.
- Add check for out-of-writes to NV.
- replace magic numbers with macros.
Rewrite duplicate code and data to use an array of packs.

Duplicating code over and over for pack1 vs. pack2 opens the door to
mistakes by failing to change both copies upon every code change.

Also simplify main loop.
Place in common folder so can be used by multiple apps.
Use them for storing battery runtime data.
Need these for handling runtime battery data.
Periodically store runtime data to flash for restoration
after daily reset by c3. This ensures the capacity and SoC
estimates are more accurate than without them.
Add checking of CRC and validity of most recent entry before
selecting it for use.

Delay before applying most recent entry after restarting
and initializing the MAX17205s.

Separate out runtime entry printing. Log more during
entry processing. Hide most verbose dumping behind a
verbose flag.
@plskeggs plskeggs force-pushed the max17205-refactor-fix branch from a143eb7 to 7d54e6b Compare July 7, 2025 20:23
When a full pack is stored in shutdown for long periods,
the pack can self-discharge. When started later, if then
charged again, the capacity estimate can grow over the
design limit.

Clamp to the design limit before storing in application
flash. This prevents out of range entries and corresponding
debug error messages later when reading the history.
@ThirteenFish

Copy link
Copy Markdown
Contributor

Sorry this took so long to review, and I'm still digging through it but in the interim can I request that the app_battery/README.md get a couple paragraphs about how this firmware is operating the MAX17205? You've learned a lot about the chip at this point and it'd be great to have a condensed "here's what we're trying to do and some of the gotchas of implementing it" kind of thing.

For a first piece on the code I'm generally not a fan of mutable globals (though I'm willing to be pragmatic, sometimes they need to exist). In batt.c the runtime_battery_data_t *last_used and last_batt_hist_entry seems like they could live on the stack and that would make the dataflow more clear there. In max17205.c history_data is too big to fit on a thread stack but could it be a static local? Or better yet it and history_length kind of look vestigial. Do they need to exist anymore?

@plskeggs

Copy link
Copy Markdown
Member Author

Sorry this took so long to review, and I'm still digging through it but in the interim can I request that the app_battery/README.md get a couple paragraphs about how this firmware is operating the MAX17205? You've learned a lot about the chip at this point and it'd be great to have a condensed "here's what we're trying to do and some of the gotchas of implementing it" kind of thing.

Yes, I am planning to add something for this. Thanks for the nudge.

For a first piece on the code I'm generally not a fan of mutable globals (though I'm willing to be pragmatic, sometimes they need to exist). In batt.c the runtime_battery_data_t *last_used and last_batt_hist_entry seems like they could live on the stack and that would make the dataflow more clear there.

I'll take a look.

In max17205.c history_data is too big to fit on a thread stack but could it be a static local? Or better yet it and history_length kind of look vestigial. Do they need to exist anymore?

It's from the original app note from Maxim. The global history_data does not need to exist -- this function is just for testing, and each history entry could instead be read into an entry on the stack and printed one at a time. Thanks for noticing this.

Eliminate global data in max17205.c.

Improve history handling in batt.c. Use better variable names, replace a
full copy of latest entry with just what is needed (reset cycle count),
and be more careful to distinguish last valid entry vs. last empty
entry. Choosing not to eliminate these globals since they are shared
between a few related functions.
@plskeggs

Copy link
Copy Markdown
Member Author

@ThirteenFish in re-reviewing the last_used and last_batt_hist_entry handling, I eliminated the full entry copy but then realized I need to use separate pointers to last valid vs. last empty, and I still need to retain a global copy of the current reset cycle count. Sorry.

It's not worth eliminating these pointers since a few related functions need them, and I don't want to bother pushing them up the call stack onto a higher level function and then passing them down to those functions as parameters. That just makes it more complicated.

I was able to eliminate the history_data and history_length globals in max17205.c.

Add information about the MAX17205, lessons learned,
and improvements made.
@plskeggs

Copy link
Copy Markdown
Member Author

@ThirteenFish I wrote an initial draft of readme improvements.

Comment thread src/f0/app_battery/Makefile Outdated
Comment thread src/f0/app_battery/source/batt.c Outdated
Comment thread src/f0/app_battery/source/batt.c
Comment thread src/f0/app_battery/source/batt.c Outdated
Comment thread src/f0/app_battery/source/batt.c Outdated
Comment thread src/f0/app_battery/source/batt.c
Comment thread src/f0/app_battery/source/batt.c Outdated
Comment thread ld/STM32F091xC-app.ld
Comment thread ld/STM32F091xC-bootloader.ld
Also add compile-time control over heaters. Needed
for board v2.1 to not brownout and reset.
Add additional comments explaining meaning of Wizard
results and identification of 2 new possible issues:

1. missing "must be 1" bit in AD_NMISCCFG --> fixed

2. potentially wrong AD_NIAVGEMPTY value compared to
nVcfg2.enIAvg setting --> no change for now, but will
test
@plskeggs plskeggs requested a review from ThirteenFish August 20, 2025 21:13

@ThirteenFish ThirteenFish left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this out on the 2.1 card on the flatsat and it looked like it all worked. I like the compile time config messages.

@plskeggs

Copy link
Copy Markdown
Member Author

OK to merge then, @ThirteenFish?

@ThirteenFish

Copy link
Copy Markdown
Contributor

Yep, go for it. Let me know if you don't have permissions and I'll try to fix it.

@plskeggs plskeggs merged commit 44f482f into oresat:master Aug 24, 2025
1 check passed
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