rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
bench_state.c File Reference

The decoding, peaks and totals of the bench readings, see bench_state.h. More...

#include "bench_state.h"
#include <math.h>
#include <string.h>
#include "dshot.h"

Macros

#define CV_PER_V   100.0f
#define CA_PER_A   100.0f
#define DC_PER_C   10.0f
#define DWH_PER_WH   10.0f

Functions

static float from_u16 (uint16_t v, float per_unit)
 Decodes an unsigned register value into units.
static uint16_t to_u16 (float v, float per_unit)
 Encodes a non-negative value into an unsigned register.
static float from_i16 (uint16_t v, float per_unit)
 Decodes a signed register value into units.
static uint16_t to_i16 (float v, float per_unit)
 Encodes a signed value into a register, rounded and clamped to int16_t.
void bench_state_from_regs (bench_state_t *b, const uint16_t *regs, uint8_t offset, uint8_t count)
 Decode a BENCH page into b.
void bench_state_to_regs (const bench_state_t *b, uint16_t *regs)
 Encode into a BENCH page, for the IOmcu and for round-trip tests.
void bench_state_run_starts (bench_state_t *b, uint16_t *regs)
 A run starts: the totals of the last one go, in b and in the BENCH page regs built from it – charge and energy 0 and LINK_BN_TOTALS_OK clear – and every other register stays.
void bench_state_log_row (const bench_state_t *b, bool whole, bench_state_t *out)
 One row of the bench log from b, into out.
void bench_state_reset_peaks (bench_state_t *b)
 Clear the peaks without disturbing the live readings.
void bench_totals_reset (bench_totals_t *t)
 A run begins: nothing counted.
void bench_totals_count (bench_totals_t *t, const bench_state_t *b, float dt_s, bool driving)
 Add dt_s of b's readings, while driving, and only what its flags mark measured: charge from a current, energy from a power with both halves.
void bench_totals_show (const bench_totals_t *t, bench_state_t *b)
 Write the totals into b, over whatever its source put there.
void bench_state_set_esc (bench_state_t *b, bool v_ok, float volts, bool i_ok, float amps, bool clipped)
 The ESC's own figures while the INA228 is the source: from the SENSE page's ESC registers, v_ok and i_ok their valid bits, and whether the INA228 reads clipped.
static bool sensed (const bench_state_t *b)
 True when the readings come from the INA228 (LINK_BN_SENSED).
static bool esc_figure (const bench_state_t *b, uint8_t esc_bit, float esc, uint16_t bench_bit, float bench, float *out)
 One of the ESC's figures: from SENSE while the INA228 is the source, from BENCH's own register and flag otherwise.
bool bench_state_esc_voltage (const bench_state_t *b, float *out)
 The ESC's own voltage and current, whichever page carries them: the SENSE page's while the INA228 is BENCH's source, BENCH's own otherwise.
bool bench_state_esc_current (const bench_state_t *b, float *out)
 The ESC's own current, from the same source as bench_state_esc_voltage().
static bool ina_figure (const bench_state_t *b, uint16_t bit, float v, float *out)
 One INA228 figure, valid only while the INA228 is the source and bit is set.
bool bench_state_ina_voltage (const bench_state_t *b, float *out)
 The INA228's own voltage and current: BENCH's while it is the source.
bool bench_state_ina_current (const bench_state_t *b, float *out)
 The INA228's own current: BENCH's while it is the source.
void bench_state_fine_totals (bench_state_t *b, int32_t charge_cmah, uint32_t energy_cwh)
 With LINK_BN_TOTALS_OK, the INA228's totals in the SENSE page's finer steps – charge_cmah in 0.01mAh, energy_cwh in 0.01Wh, read in the same poll – over BENCH's 1mAh and 0.1Wh, each where it agrees with BENCH's within the tolerance above, or where BENCH reads its ceiling and the finer figure is at or above it.
void bench_state_track_peaks (bench_state_t *b)
 Take the live readings into the peaks.
void bench_state_from_telem (bench_state_t *b, const bench_telem_t *t)
 The live readings of b and their valid bits from t, for the IOmcu's sample.

Detailed Description

The decoding, peaks and totals of the bench readings, see bench_state.h.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ CA_PER_A

#define CA_PER_A   100.0f

10mA steps

◆ CV_PER_V

#define CV_PER_V   100.0f

10mV steps

◆ DC_PER_C

#define DC_PER_C   10.0f

0.1C steps

◆ DWH_PER_WH

#define DWH_PER_WH   10.0f

0.1Wh steps

Function Documentation

◆ bench_state_esc_current()

bool bench_state_esc_current ( const bench_state_t * b,
float * out )

The ESC's own current, from the same source as bench_state_esc_voltage().

Parameters
bThe state to read.
outReceives the current in A; untouched when false.
Returns
true when an ESC current is available.

◆ bench_state_esc_voltage()

bool bench_state_esc_voltage ( const bench_state_t * b,
float * out )

The ESC's own voltage and current, whichever page carries them: the SENSE page's while the INA228 is BENCH's source, BENCH's own otherwise.

False, and out untouched, when the ESC reported none – and for modelled numbers (LINK_BN_SIMULATED), which no ESC reported.

Parameters
bThe state to read.
outReceives the voltage in V; untouched when false.
Returns
true when an ESC voltage is available.

◆ bench_state_fine_totals()

void bench_state_fine_totals ( bench_state_t * b,
int32_t charge_cmah,
uint32_t energy_cwh )

With LINK_BN_TOTALS_OK, the INA228's totals in the SENSE page's finer steps – charge_cmah in 0.01mAh, energy_cwh in 0.01Wh, read in the same poll – over BENCH's 1mAh and 0.1Wh, each where it agrees with BENCH's within the tolerance above, or where BENCH reads its ceiling and the finer figure is at or above it.

Nothing changes without TOTALS_OK.

Parameters
bThe state whose totals are set.
charge_cmahThe INA228 charge in 0.01mAh.
energy_cwhThe INA228 energy in 0.01Wh.

◆ bench_state_from_regs()

void bench_state_from_regs ( bench_state_t * b,
const uint16_t * regs,
uint8_t offset,
uint8_t count )

Decode a BENCH page into b.

A short read fills what arrived and leaves the rest alone, so a host that polls the first four registers at 20Hz and the whole page once a second gets a coherent state either way.

Parameters
bThe state the registers are decoded into.
regsThe page registers, count entries from offset.
offsetThe page register that regs[0] holds.
countThe number of entries in regs.

◆ bench_state_from_telem()

void bench_state_from_telem ( bench_state_t * b,
const bench_telem_t * t )

The live readings of b and their valid bits from t, for the IOmcu's sample.

voltage, current, power, rpm, temp_esc, temp_motor and flags are rebuilt; the peaks and every other field stay.

rpm with LINK_BN_RPM_OK from a speed no older than BENCH_RPM_STALE_MS and poles not 0; voltage, current and temp_esc with LINK_BN_VOLTAGE_OK, LINK_BN_CURRENT_OK and LINK_BN_TEMP_OK from readings no older than BENCH_EDT_STALE_MS, in the units of dshot_edt_*(); power, the product, only with both halves. LINK_BN_TEMP_MOT_OK is never set.

Parameters
bThe state that is written.
tThe telemetry sample that is read.

◆ bench_state_ina_current()

bool bench_state_ina_current ( const bench_state_t * b,
float * out )

The INA228's own current: BENCH's while it is the source.

Parameters
bThe state to read.
outReceives the current in A; untouched when false.
Returns
true when the INA228 current is valid.

◆ bench_state_ina_voltage()

bool bench_state_ina_voltage ( const bench_state_t * b,
float * out )

The INA228's own voltage and current: BENCH's while it is the source.

False otherwise.

Parameters
bThe state to read.
outReceives the voltage in V; untouched when false.
Returns
true when the INA228 voltage is valid.

◆ bench_state_log_row()

void bench_state_log_row ( const bench_state_t * b,
bool whole,
bench_state_t * out )

One row of the bench log from b, into out.

With whole the sample as it is. Without, the INA3221's window alone – servo_new, the servo_ fields and chw – and every other field 0 with no flag set, which the log writes as empty cells: the row of a window that closed before the newest one of its pass.

Parameters
bThe state to take the row from.
wholetrue for the whole sample, false for the INA3221 window alone.
outWhere the row is written.

◆ bench_state_reset_peaks()

void bench_state_reset_peaks ( bench_state_t * b)

Clear the peaks without disturbing the live readings.

Parameters
bThe state whose peaks are cleared.

◆ bench_state_run_starts()

void bench_state_run_starts ( bench_state_t * b,
uint16_t * regs )

A run starts: the totals of the last one go, in b and in the BENCH page regs built from it – charge and energy 0 and LINK_BN_TOTALS_OK clear – and every other register stays.

For the IOmcu, on the edge into driving: it rebuilds the page at its 50Hz sample, and until the next one a panel reading the page would see the last run's totals marked as this run's. Either pointer may be NULL.

Parameters
bThe state to update, or NULL.
regsThe page to update, or NULL.

◆ bench_state_set_esc()

void bench_state_set_esc ( bench_state_t * b,
bool v_ok,
float volts,
bool i_ok,
float amps,
bool clipped )

The ESC's own figures while the INA228 is the source: from the SENSE page's ESC registers, v_ok and i_ok their valid bits, and whether the INA228 reads clipped.

All clear while it is not the source.

Parameters
bThe state to write.
v_oktrue when volts is valid.
voltsThe ESC voltage in V.
i_oktrue when amps is valid.
ampsThe ESC current in A.
clippedtrue when the INA228 reads clipped.

◆ bench_state_to_regs()

void bench_state_to_regs ( const bench_state_t * b,
uint16_t * regs )

Encode into a BENCH page, for the IOmcu and for round-trip tests.

Parameters
bThe state to encode.
regsThe page to fill, LINK_BN_COUNT registers.

◆ bench_state_track_peaks()

void bench_state_track_peaks ( bench_state_t * b)

Take the live readings into the peaks.

Only what the flags mark valid: an empty field is not a measurement of zero, and a sag floor or a current peak taken from one would stand for the rest of the run. The floor is seeded by the first valid voltage rather than by the reset, because a reset can happen before any voltage has arrived.

Parameters
bThe state whose peaks are updated.

◆ bench_totals_count()

void bench_totals_count ( bench_totals_t * t,
const bench_state_t * b,
float dt_s,
bool driving )

Add dt_s of b's readings, while driving, and only what its flags mark measured: charge from a current, energy from a power with both halves.

dt_s is the time since the last call, clamped to 0 .. BENCH_TOTALS_MAX_STEP_S, so a loop that stalled counts at most one second of its last reading. With LINK_BN_TOTALS_OK in b's flags and BENCH_TOTALS_SETTLE_S of the run counted, the count is b's own charge and energy instead, both counted.

Parameters
tThe running totals.
bThe readings of this sample.
dt_sThe time since the last call in s, clamped to 0 .. BENCH_TOTALS_MAX_STEP_S.
drivingtrue while the bench is driving.

◆ bench_totals_reset()

void bench_totals_reset ( bench_totals_t * t)

A run begins: nothing counted.

Parameters
tThe totals to clear.

◆ bench_totals_show()

void bench_totals_show ( const bench_totals_t * t,
bench_state_t * b )

Write the totals into b, over whatever its source put there.

Parameters
tThe totals to show.
bThe state that receives them.

◆ esc_figure()

bool esc_figure ( const bench_state_t * b,
uint8_t esc_bit,
float esc,
uint16_t bench_bit,
float bench,
float * out )
static

One of the ESC's figures: from SENSE while the INA228 is the source, from BENCH's own register and flag otherwise.

Parameters
bThe state to read.
esc_bitThe valid bit in esc_ok.
escThe SENSE value.
bench_bitThe valid bit in flags.
benchThe BENCH value.
outReceives the value; untouched when false.
Returns
true when the figure is available.

◆ from_i16()

float from_i16 ( uint16_t v,
float per_unit )
static

Decodes a signed register value into units.

Parameters
vThe raw register value, two's complement.
per_unitRegister steps per unit.
Returns
The signed value divided by per_unit.

◆ from_u16()

float from_u16 ( uint16_t v,
float per_unit )
static

Decodes an unsigned register value into units.

Parameters
vThe raw register value.
per_unitRegister steps per unit.
Returns
v divided by per_unit.

◆ ina_figure()

bool ina_figure ( const bench_state_t * b,
uint16_t bit,
float v,
float * out )
static

One INA228 figure, valid only while the INA228 is the source and bit is set.

Parameters
bThe state to read.
bitThe valid bit in flags.
vThe value.
outReceives the value; untouched when false.
Returns
true when the figure is valid.

◆ sensed()

bool sensed ( const bench_state_t * b)
static

True when the readings come from the INA228 (LINK_BN_SENSED).

Parameters
bThe state to test.
Returns
true when LINK_BN_SENSED is set in the flags of b.

◆ to_i16()

uint16_t to_i16 ( float v,
float per_unit )
static

Encodes a signed value into a register, rounded and clamped to int16_t.

Parameters
vThe value in units.
per_unitRegister steps per unit.
Returns
The register value as two's complement.

◆ to_u16()

uint16_t to_u16 ( float v,
float per_unit )
static

Encodes a non-negative value into an unsigned register.

Parameters
vThe value in units.
per_unitRegister steps per unit.
Returns
The rounded register value, 0 for a value not above zero and 65535 at the top.