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

The bench readings, in the units a person reads: V, A, W, rpm (revolutions per minute), degrees Celsius, mAh and Wh. More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "link_pages.h"

Go to the source code of this file.

Data Structures

struct  bench_chw_t
 One 50ms window of every INA3221 channel, from SENSE_WIN_A and SENSE_WIN_B (protocol 4.25), for the log's columns per watched target: channel c = 3 a + CHn - 1 of the part at 0x40 + a. More...
struct  bench_state_t
 The bench readings in the units a person reads: V, A, W and rpm, with their peaks. More...
struct  bench_totals_t
 A run's charge and energy, counted by the panel. More...
struct  bench_edt_reading_t
 One extended-telemetry reading as the DShot driver holds it. More...
struct  bench_telem_t
 The ESC's telemetry as the IOmcu reads it at a sample: raw, with each reading's age and whether there is one. More...

Macros

#define BENCH_CHW_CHANNELS   12u
 The INA3221 channels SENSE_WIN_A and SENSE_WIN_B carry (4.25).
#define BENCH_FINE_MAH_TOL   2.0f
 How far the SENSE page's totals may lie from BENCH's and be the same count: half a register step of rounding, and what a few milliseconds between the two reads adds at full current.
#define BENCH_FINE_WH_TOL   0.2f
#define BENCH_CHARGE_MAH_MAX   65535.0f
 The most BENCH's charge (1mAh) and energy (0.1Wh) registers carry: a run past them reads the ceiling there, and only SENSE's 32-bit totals go on.
#define BENCH_ENERGY_WH_MAX   6553.5f
#define BENCH_COUNTED_CHARGE   0x01u
 bench_state_t.counted: the run's charge has counted a measured current.
#define BENCH_COUNTED_ENERGY   0x02u
 bench_state_t.counted: the run's energy has counted voltage and current.
#define BENCH_TOTALS_MAX_STEP_S   1.0f
 The longest step bench_totals_count() counts, in seconds.
#define BENCH_TOTALS_SETTLE_S   0.1f
 How long into a run the INA228's totals are not taken, in seconds.
#define BENCH_RPM_STALE_MS   200u
#define BENCH_EDT_STALE_MS   2000u

Functions

static bool bench_state_simulated (const bench_state_t *b)
 True when the numbers are modelled rather than measured.
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_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.
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().
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_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_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 bench readings, in the units a person reads: V, A, W, rpm (revolutions per minute), degrees Celsius, mAh and Wh.

Screens read this struct and never a register. Filled from the link's BENCH page the numbers are measured; filled from the simulator they are modelled; the screen does not distinguish the two.

Floats here, fixed-point on the wire: 16 bits with a documented scale is the contract between the two firmwares. The scales are in link_pages.h.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ BENCH_TOTALS_SETTLE_S

#define BENCH_TOTALS_SETTLE_S   0.1f

How long into a run the INA228's totals are not taken, in seconds.

An IOmcu builds the BENCH page from its 50Hz sample, so one that does not clear the page on the arm (bench_state_run_starts()) can carry the last run's totals with LINK_BN_TOTALS_OK for up to 20ms after it; the panel counts on its own until five such samples have passed.

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_simulated()

bool bench_state_simulated ( const bench_state_t * b)
inlinestatic

True when the numbers are modelled rather than measured.

Parameters
bThe state to test.
Returns
true when the numbers are modelled (LINK_BN_SIMULATED), not measured.

◆ 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.