LevelEstimator

Struct LevelEstimator 

Source
pub struct LevelEstimator { /* private fields */ }
Expand description

Approximate state-of-charge estimator for gauge-less boards: a rest-gated OCV table with a median filter, a discharge-direction clamp, and quantized output.

Feed it every monitor sample via Self::sample. It moves at two speeds:

  • Every quiet sample sets a ceiling. A terminal voltage that is not sagging relaxes downward toward true OCV, so the table can only overstate what is in the pack; the level is capped to that reading immediately. This is what keeps a stale estimate — most visibly the one bootstrapped from a charger’s elevated rail — from surviving long after the pack has been unplugged.
  • A rested window of [LEVEL_WINDOW] samples anchors. Only after [LEVEL_REST_MS] of quiet (no external power, no reported load) does the median become the level outright, and only then is the discharge clamp re-established.

Anchored levels never rise while discharging, so the output is stable and monotone between charge sessions. A charge since the last anchor invalidates the stored level in both directions, so until the next anchor the ceiling replaces it rather than capping it — which is how a partial charge shows up without waiting out a full window.

While charging there is no level at all: charging voltage is not comparable to the discharge table, so the estimate is withdrawn rather than frozen at its pre-charge value. It returns on the first quiet reading after the charger goes away. The one exception is the Charged classification, which is a charger’s completion signal and therefore an exact calibration point: it pins the level to 100. Boards whose charger reports no completion never see that state and simply report nothing for as long as they are plugged in.

Implementations§

Source§

impl LevelEstimator

Source

pub const fn new() -> Self

Source

pub const fn level(&self) -> Option<u8>

The current estimate, or None when no trustworthy one exists — before the first quiet sample, and for as long as the pack is charging.

Source

pub fn sample(&mut self, s: LevelSample)

Trait Implementations§

Source§

impl Default for LevelEstimator

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.