|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The limit run: the limit search (servo_limit.h) run on the SERVO screen against the INA3221's windows, and for a KST or Chaservo servo on the programming port, the servo's own travel limits lowered until neither end binds. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include "servo_limit.h"#include "servo_test.h"Go to the source code of this file.
Data Structures | |
| struct | servo_limrun_cfg_t |
| struct | servo_limrun_servo_t |
| The servo the programmer read. More... | |
| struct | servo_limrun_in_t |
| What the caller knows each step. More... | |
| struct | servo_limrun_do_t |
| What the run wants done. More... | |
| struct | servo_limrun_side_t |
| What one search of one side found. More... | |
| struct | servo_limrun_t |
Macros | |
| #define | SERVO_LIMRUN_WRITES_MAX 8u |
| Register values a run writes at most: PULSE LOWER and PULSE UPPER for SERVO PULSES at 1000-2000, two a side, the overset and the final value, and two for a first write that went to the register of the other side, that value and LEFT ANGLE's own value back. | |
| #define | SERVO_LIMRUN_OVERSET_PCT 3u |
| The overset write lies this far above the share at the first search's first bound pulse: the stop stays in reach, close to the pulse limit. | |
| #define | SERVO_LIMRUN_STD_LOWER_DUS 10000u |
| The pulses SERVO PULSES at 1000-2000 writes, 0.1us. | |
| #define | SERVO_LIMRUN_STD_UPPER_DUS 20000u |
| #define | SERVO_LIMRUN_MOVED_US 20u |
| An endpoint that moves this far out moved; one within it stayed. | |
| #define | SERVO_LIMRUN_SEARCH_MS 40000u |
| One search of one side at most: 1000us of travel, PULSE MIN 500us to a 1500us centre, is 100 positions of 250ms, 25s; the baseline's three and the slower windows of a busy panel fit in the rest. | |
| #define | SERVO_LIMRUN_RETURN_MS 1000u |
| Each search starts with the servo held at PULSE CENTRE this long, and each session waits this long at PULSE CENTRE before the bench is asked to SAFE: the return from the last end, 600us at 0.67us/ms (0.3s for 60 degrees) is 900ms, and the search's baseline is not to see it travel. | |
| #define | SERVO_LIMRUN_PROG_MS 150000u |
| One step of the programmer – CONNECT with its read, a write, LEAVE – at most: past the programmer's own 120s of an operation. | |
| #define | SERVO_LIMRUN_BENCH_MS 3000u |
| The bench switches to SAFE, or to ARMED, within this of being asked. | |
| #define | SERVO_LIMRUN_HARD_MA 3000 |
| The protections: a 1ms sample, and the window means for a time. | |
| #define | SERVO_LIMRUN_STALL_MA 1000 |
| #define | SERVO_LIMRUN_STALL_MS 400u |
| #define | SERVO_LIMRUN_WIN_STALE_MS SERVO_TEST_WIN_STALE_MS |
| No window for this long ends the run: the automatic test's figure. | |
| #define | SERVO_LIMRUN_RAIL_DV_MV 1000 |
| The rail voltage, a window's mean, this far from the first window's ends the run as a changed supply. | |
| #define | SERVO_LIMRUN_RAIL_MIN_MV 3000 |
| The servo rail a run starts on at least, the last INA3221 window's mean (the screen's START check): an output that is off reads 0V, and a search there finds two free ends on a servo that never moved. | |
| #define | SERVO_LIMRUN_OUTBOX 2u |
Enumerations | |
| enum | { SERVO_LIMRUN_LO = 0 , SERVO_LIMRUN_HI = 1 } |
| The two sides of PULSE CENTRE: shorter and longer pulses. | |
| enum | { SERVO_LIMRUN_LEFT = 0 , SERVO_LIMRUN_RIGHT = 1 } |
| The two registers. | |
| enum | { SERVO_LIMRUN_P_NEUTRAL = 0 , SERVO_LIMRUN_P_LOWER = 1 , SERVO_LIMRUN_P_UPPER = 2 } |
| The servo's pulses, in pulse_dus. | |
| enum | servo_limrun_state_t { SERVO_LIMRUN_IDLE = 0 , SERVO_LIMRUN_RUNNING , SERVO_LIMRUN_DONE } |
| enum | servo_limrun_phase_t { SERVO_LIMRUN_PH_NONE = 0 , SERVO_LIMRUN_PH_SEARCH , SERVO_LIMRUN_PH_SAFE , SERVO_LIMRUN_PH_CONNECT , SERVO_LIMRUN_PH_WRITE , SERVO_LIMRUN_PH_LEAVE , SERVO_LIMRUN_PH_ARM , SERVO_LIMRUN_PH_PROBE , SERVO_LIMRUN_PH_CHECK } |
| enum | servo_limrun_verdict_t { SERVO_LIMRUN_FOUND = 0 , SERVO_LIMRUN_FREE , SERVO_LIMRUN_PASS , SERVO_LIMRUN_FAIL , SERVO_LIMRUN_ABORTED } |
| enum | servo_limrun_why_t { SERVO_LIMRUN_WHY_NONE = 0 , SERVO_LIMRUN_WHY_TEST , SERVO_LIMRUN_WHY_HARD , SERVO_LIMRUN_WHY_CLIPPED , SERVO_LIMRUN_WHY_STALL , SERVO_LIMRUN_WHY_SEARCH_LONG , SERVO_LIMRUN_WHY_SUPPLY_CHANGED , SERVO_LIMRUN_WHY_BENCH , SERVO_LIMRUN_WHY_NOT_KST , SERVO_LIMRUN_WHY_PROG , SERVO_LIMRUN_WHY_WRITE , SERVO_LIMRUN_WHY_OTHER_VALUES , SERVO_LIMRUN_WHY_MAPPING , SERVO_LIMRUN_WHY_SMALLEST , SERVO_LIMRUN_WHY_WRITE_CAP , SERVO_LIMRUN_WHY_STILL_BINDS , SERVO_LIMRUN_WHY_NO_VOLTAGE , SERVO_LIMRUN_WHY_NO_STOP , SERVO_LIMRUN_WHY_BEFORE_NEUTRAL , SERVO_LIMRUN_WHY_NEUTRAL , SERVO_LIMRUN_WHY_RANGE , SERVO_LIMRUN_WHY_COUNT } |
| Why a run failed or was aborted. More... | |
Functions | |
| void | servo_limrun_init (servo_limrun_t *r) |
| Clear a run state to idle. | |
| bool | servo_limrun_start (servo_limrun_t *r, const servo_limrun_cfg_t *cfg, uint32_t now_ms) |
Start at now_ms. False, and nothing started, for a configuration whose centre is not between its MIN and MAX. | |
| void | servo_limrun_window (servo_limrun_t *r, const servo_test_win_t *w) |
| One INA3221 window, as the automatic test takes it. | |
| void | servo_limrun_supply (servo_limrun_t *r, const servo_test_reading_t *s, uint32_t now_ms) |
| The supply's reading. | |
| void | servo_limrun_connected (servo_limrun_t *r, const servo_limrun_servo_t *sv, uint32_t now_ms) |
| The programmer's answers: the servo read after CONNECT, a write's end with the values the servo holds (servo_limrun_pulsed() for the pulse write: NEUTRAL, PULSE LOWER, PULSE UPPER), and the port back in PWM. | |
| void | servo_limrun_written (servo_limrun_t *r, bool ok, const uint16_t *angle, uint32_t now_ms) |
| Feed the end of a write: the values the servo holds. | |
| void | servo_limrun_pulsed (servo_limrun_t *r, bool ok, const uint16_t *pulse_dus, uint32_t now_ms) |
| Feed the end of the pulse write: the pulses the servo holds. | |
| void | servo_limrun_left (servo_limrun_t *r, bool ok, uint32_t now_ms) |
| Feed the answer to LEAVE: the port is given back. | |
| void | servo_limrun_supply_refused (servo_limrun_t *r, bool output_on, uint32_t now_ms) |
The caller will not hand the programmer's CONNECT a PD mini that the run did not start with, or one whose output is off (output_on false). A supply the run started with, its output off, ends the run as a reading outside a session does (SERVO_TEST_AB_SUPPLY_OFF); one the run did not start with ends it as a changed supply (SERVO_LIMRUN_WHY_SUPPLY_CHANGED). | |
| void | servo_limrun_backup (servo_limrun_t *r, const char *name) |
| The file the servo's values before the run were saved in, once the programmer names it: its first write saves it. | |
| void | servo_limrun_refused (servo_limrun_t *r, uint32_t now_ms) |
| The programmer refused the CONNECT, write or LEAVE asked: it never started. | |
| void | servo_limrun_no_servo (servo_limrun_t *r, uint32_t now_ms) |
| The programmer's CONNECT ended with no servo answering (KST_SES_ERR_NO_SERVO). | |
| void | servo_limrun_step (servo_limrun_t *r, uint32_t now_ms, const servo_limrun_in_t *in, servo_limrun_do_t *out) |
Advance to now_ms: what to do comes back in out. | |
| void | servo_limrun_abort (servo_limrun_t *r, servo_test_abort_t why, uint32_t now_ms) |
| The caller's reasons. | |
| bool | servo_limrun_running (const servo_limrun_t *r) |
| Tell whether the run is RUNNING. | |
| bool | servo_limrun_switching (const servo_limrun_t *r) |
| The run asked the bench to SAFE or to ARMED and waits for it, or holds the programmer: a disarm then is its own, not the operator's. Not while the servo returns to the centre before a session: a disarm then is the operator's. | |
| bool | servo_limrun_programming (const servo_limrun_t *r) |
| The run holds the programmer: CONNECT to LEAVE. | |
| bool | servo_limrun_wrote (const servo_limrun_t *r) |
| A value was written and the servo may not hold its own any more. | |
| bool | servo_limrun_restore (const servo_limrun_t *r) |
| The run ended as FAIL or ABORTED with the servo's values changed: RESTORE gives back the ones before it. | |
| bool | servo_limrun_original (const servo_limrun_t *r, uint16_t *left, uint16_t *right) |
| The values the servo held before the run, valid once read. | |
| servo_test_out_t | servo_limrun_peek (servo_limrun_t *r, const char **text) |
| The report's lines, in order, then END; OPEN_TXT first. | |
| void | servo_limrun_pop (servo_limrun_t *r) |
| Take the outbox entry last returned by servo_limrun_peek(). | |
| bool | servo_limrun_drained (const servo_limrun_t *r) |
| Tell whether the run has nothing left to hand over. | |
| bool | servo_limrun_report_line (const servo_limrun_t *r, unsigned idx, char *buf, size_t n) |
Line idx of the report into buf; false past the last. | |
| servo_str_t | servo_limrun_verdict_str (servo_limrun_verdict_t v) |
| The table entries the screen and the report name these by. | |
| servo_str_t | servo_limrun_why_str (const servo_limrun_t *r) |
| Name table entry for the reason of a run. | |
| servo_str_t | servo_limrun_phase_str (servo_limrun_phase_t ph) |
| Table entry for a phase of the limit run. | |
| int32_t | servo_limrun_dist (const servo_limrun_servo_t *sv, uint8_t side, uint16_t p_us) |
The share of travel, 0.1us of pulse: p_us's distance from NEUTRAL on side, positive outward, and the pulse limit's. | |
| int32_t | servo_limrun_span (const servo_limrun_servo_t *sv, uint8_t side) |
| Span of one side, as servo_limrun_span() reports it. | |
| uint16_t | servo_limrun_overset (uint16_t v0, int32_t d, int32_t span, uint16_t lo_raw) |
The overset for value v0 and share d / span: ceil(v0 x share x (100 + SERVO_LIMRUN_OVERSET_PCT) / 100), within lo_raw to v0. | |
| uint16_t | servo_limrun_scaled (uint16_t v, int32_t d, int32_t span, uint16_t lo_raw) |
The final value for value v and share d / span: floor(v x
share), within lo_raw to v. | |
The limit run: the limit search (servo_limit.h) run on the SERVO screen against the INA3221's windows, and for a KST or Chaservo servo on the programming port, the servo's own travel limits lowered until neither end binds.
The search. A side is searched from its centre outward, a servo_limit search in steps of 10us, the position bound once its current is above 1.8 times the free current and 0.15A above it. A side whose end is measured free is free. The endpoints are reported; the bench's own pulse range is not changed. Where the search runs depends on the target:
SERVO PULSES (cfg.set_pulses, programming port only). At 1000-2000 the read session writes PULSE LOWER 1000.0us and PULSE UPPER 2000.0us before anything is driven, and reads them back; NEUTRAL is not written. A servo at those values already gets no write. The search then runs out to 1000us and 2000us. The pulse write counts toward SERVO_LIMRUN_WRITES_MAX and RESTORE takes it back with the rest.
The programming (cfg.program). LEFT ANGLE and RIGHT ANGLE are the servo's own travel limits, one register each, in a unit that is not known. The run takes the servo as linear: PULSE LOWER and PULSE UPPER are the input pulses at which it reaches the full travel LEFT ANGLE and RIGHT ANGLE set, between NEUTRAL and such a pulse its travel is linear in the pulse, and past it the servo holds that travel. That is an assumption, not a measurement. The share of a side at pulse p is
f = (p - NEUTRAL) / (P_lim - NEUTRAL)
with P_lim PULSE LOWER on the short-pulse side and PULSE UPPER on the long one, both as the servo holds them when the search runs. f is formed from input pulses only, so REVERSION does not enter it: REVERSION decides which register limits that side, and the run finds that (below). A bound side whose last free pulse is not past NEUTRAL ends the run as FAIL (SERVO_LIMRUN_WHY_BEFORE_NEUTRAL) before any write.
Two writes a bound side, v0 the value its register holds at the read:
Worked: NEUTRAL 1500.2us, PULSE LOWER 900.0us, v0 150, the stop at 1000us. The first search is free at 1000us and bound at 990us: fb = 510.2 / 600.2 = 0.850, v1 = ceil(150 x 0.850 x 1.03) = 132. A linear servo at 132 is free out to 930us: f1 = 570.2 / 600.2 = 0.950, v2 = floor(132 x 0.950) = 125. At 125 the full travel ends at 1000.2us.
The overset is left out, and the first search counts as its search, where v1 would not lie below v0 (fb above about 0.97) or where the model moves the stop, estimated at the first search's last free pulse, less than SERVO_LIMRUN_MOVED_US further out: d0 x (v0 - v1) / v1 under 20us, d0 that pulse's distance from NEUTRAL. A search could not tell that move from no move. The final value is then v2 = floor(v0 x f0), f0 the share at the first search's last free pulse.
Which pulse side each register limits is not stated by the protocol notes, so the run finds it on the first bound side's first write: that value goes to LEFT ANGLE (RIGHT ANGLE where LEFT ANGLE holds the smallest value already) and the side is searched. The end moved when it is free now or its endpoint lies SERVO_LIMRUN_MOVED_US further out; it stayed when its endpoint lies within that of where it was. An end that stayed sends LEFT ANGLE back to its value and the value, worked out again from RIGHT ANGLE's v0, to RIGHT ANGLE; stayed again, the run ends as FAIL. An end that moved inward ends it as FAIL too: nothing about the servo is guessed. The register found limits that side, the other one the other side; a register whose side never bound keeps its value.
Last, both ends are searched again: PASS when both are free, FAIL when either binds. No further write follows a FAIL; RESTORE gives the values before the run back.
Writes. A value is written in a session of the programmer: the servo held at the centre for SERVO_LIMRUN_RETURN_MS after the search, so a session never starts with the servo against an end, the bench switched to SAFE, the port taken (CONNECT reads all registers), the write, the port given back (LEAVE), the bench switched to ARMED again. The read session writes nothing but the pulses of SERVO PULSES; each angle write has a session of its own. A LEAVE this link or supply does not complete ends the run before any value changes. No step of the protocol is known to make a value permanent, and no RAM-only write exists: every write is the register write the programmer reads back. The run counts register values written and stops at SERVO_LIMRUN_WRITES_MAX, the most this flow can need.
Protections, for the whole run, whatever phase it is in:
The supply is also held to what it was at the start, its set points and its output, in every phase but the programmer's sessions (CONNECT to LEAVE): those own the port and the supply (kst_prog.h), and a change then is theirs. While a search drives the servo the rail voltage stays within SERVO_LIMRUN_RAIL_DV_MV of the run's first window. A search's window without the rail voltage ends the run (SERVO_LIMRUN_WHY_NO_VOLTAGE), so that reference is a window's and no window escapes the band. A window without a current reading is not counted at all: the meter's silence runs on through it.
The caller ends the run (servo_limrun_abort()) for STOP, SAFE, link loss, leaving the screen, the operator taking the servo, changed settings, lost touch events, the INA3221 no longer the meter, and a supply that stops answering, trips, switches off or has its set points changed. An ended run asks the output off and lets the servo go (servo_limrun_do_t.off and release), and asks SAFE where it waited for ARMED; the values last written stay in the servo.
Pure: fed windows, the programmer's results and the clock, it moves nothing itself. Its report leaves through an outbox (servo_limrun_peek()) as one LIMITnnn.TXT.
SPDX-License-Identifier: MIT
| #define SERVO_LIMRUN_RAIL_MIN_MV 3000 |
The servo rail a run starts on at least, the last INA3221 window's mean (the screen's START check): an output that is off reads 0V, and a search there finds two free ends on a servo that never moved.
3.0V lies under the 4.8V servos are commonly specified from, so a single lithium cell's rail, 3.0V to 4.2V, still starts. The voltage a given servo stops moving at is not measured.
| enum servo_limrun_phase_t |
| enum servo_limrun_why_t |
Why a run failed or was aborted.
| Enumerator | |
|---|---|
| SERVO_LIMRUN_WHY_TEST | a reason of servo_test_abort_t, in test_why |
| SERVO_LIMRUN_WHY_HARD | a sample at SERVO_LIMRUN_HARD_MA |
| SERVO_LIMRUN_WHY_CLIPPED | a sample at the meter's end |
| SERVO_LIMRUN_WHY_STALL | above SERVO_LIMRUN_STALL_MA |
| SERVO_LIMRUN_WHY_SEARCH_LONG | a search past its cap |
| SERVO_LIMRUN_WHY_SUPPLY_CHANGED | set points or rail voltage moved |
| SERVO_LIMRUN_WHY_BENCH | the bench did not switch |
| SERVO_LIMRUN_WHY_NOT_KST | no KST or Chaservo servo read |
| SERVO_LIMRUN_WHY_PROG | CONNECT or LEAVE did not end well |
| SERVO_LIMRUN_WHY_WRITE | a write refused or lost |
| SERVO_LIMRUN_WHY_OTHER_VALUES | the servo read holds other values |
| SERVO_LIMRUN_WHY_MAPPING | which end LEFT ANGLE moves is not found |
| SERVO_LIMRUN_WHY_SMALLEST | binds at the smallest value |
| SERVO_LIMRUN_WHY_WRITE_CAP | SERVO_LIMRUN_WRITES_MAX reached |
| SERVO_LIMRUN_WHY_STILL_BINDS | an end binds after programming |
| SERVO_LIMRUN_WHY_NO_VOLTAGE | a search's window without the rail voltage |
| SERVO_LIMRUN_WHY_NO_STOP | free after the overset write |
| SERVO_LIMRUN_WHY_BEFORE_NEUTRAL | a free end not past NEUTRAL |
| SERVO_LIMRUN_WHY_NEUTRAL | NEUTRAL not between PULSE LOWER and PULSE UPPER |
| SERVO_LIMRUN_WHY_RANGE | PULSE LOWER to PULSE UPPER not inside PULSE MIN to PULSE MAX |
| void servo_limrun_abort | ( | servo_limrun_t * | r, |
| servo_test_abort_t | why, | ||
| uint32_t | now_ms ) |
The caller's reasons.
| r | Run state. Does nothing unless the run is RUNNING. |
| why | Reason from the caller. |
| now_ms | Time of the abort, ms. |
| void servo_limrun_backup | ( | servo_limrun_t * | r, |
| const char * | name ) |
The file the servo's values before the run were saved in, once the programmer names it: its first write saves it.
| r | Run state. |
| name | File name. Ignored when NULL or empty, or when the servo was not read. |
| void servo_limrun_connected | ( | servo_limrun_t * | r, |
| const servo_limrun_servo_t * | sv, | ||
| uint32_t | now_ms ) |
The programmer's answers: the servo read after CONNECT, a write's end with the values the servo holds (servo_limrun_pulsed() for the pulse write: NEUTRAL, PULSE LOWER, PULSE UPPER), and the port back in PWM.
| r | Run state. |
| sv | Servo as read. Ignored when NULL. |
| now_ms | Time of the answer, ms. |
| int32_t servo_limrun_dist | ( | const servo_limrun_servo_t * | sv, |
| uint8_t | side, | ||
| uint16_t | p_us ) |
The share of travel, 0.1us of pulse: p_us's distance from NEUTRAL on side, positive outward, and the pulse limit's.
| sv | Servo pulses, 0.1us. |
| side | SERVO_LIMRUN_LO or SERVO_LIMRUN_HI. |
| p_us | Pulse width, microseconds. |
| bool servo_limrun_drained | ( | const servo_limrun_t * | r | ) |
Tell whether the run has nothing left to hand over.
| r | Run state. |
| void servo_limrun_init | ( | servo_limrun_t * | r | ) |
Clear a run state to idle.
| r | Run state. Does nothing when NULL. |
| void servo_limrun_left | ( | servo_limrun_t * | r, |
| bool | ok, | ||
| uint32_t | now_ms ) |
Feed the answer to LEAVE: the port is given back.
| r | Run state. |
| ok | false ends the run as ABORTED with PROG. |
| now_ms | Time of the answer, ms. |
| void servo_limrun_no_servo | ( | servo_limrun_t * | r, |
| uint32_t | now_ms ) |
The programmer's CONNECT ended with no servo answering (KST_SES_ERR_NO_SERVO).
The run's first CONNECT ends it as FAIL with SERVO_LIMRUN_WHY_NOT_KST, as a read that is no KST or Chaservo servo does; a later CONNECT ends it as servo_limrun_refused() does, with SERVO_LIMRUN_WHY_PROG. Nothing at any other step.
| r | The run; NULL, or one not running, is left as it is. |
| now_ms | Current time, ms. |
| bool servo_limrun_original | ( | const servo_limrun_t * | r, |
| uint16_t * | left, | ||
| uint16_t * | right ) |
The values the servo held before the run, valid once read.
| r | Run state. |
| left | Out: LEFT ANGLE before the run. NULL to skip. |
| right | Out: RIGHT ANGLE before the run. NULL to skip. |
| uint16_t servo_limrun_overset | ( | uint16_t | v0, |
| int32_t | d, | ||
| int32_t | span, | ||
| uint16_t | lo_raw ) |
The overset for value v0 and share d / span: ceil(v0 x share x (100 + SERVO_LIMRUN_OVERSET_PCT) / 100), within lo_raw to v0.
| v0 | Register value at the read. |
| d | Distance of the bound pulse from NEUTRAL, 0.1us. 0 or less returns the lower bound. |
| span | Span of the side, 0.1us. 0 or less returns the lower bound. |
| lo_raw | Smallest value the hard rules take. |
| servo_test_out_t servo_limrun_peek | ( | servo_limrun_t * | r, |
| const char ** | text ) |
The report's lines, in order, then END; OPEN_TXT first.
| r | Run state. NULL gives NONE. |
| text | Out: text of the entry; empty when there is none. |
| servo_str_t servo_limrun_phase_str | ( | servo_limrun_phase_t | ph | ) |
Table entry for a phase of the limit run.
| ph | Phase to name. |
| void servo_limrun_pop | ( | servo_limrun_t * | r | ) |
Take the outbox entry last returned by servo_limrun_peek().
| r | Run state. |
| bool servo_limrun_programming | ( | const servo_limrun_t * | r | ) |
The run holds the programmer: CONNECT to LEAVE.
| r | Run state. NULL gives false. |
| void servo_limrun_pulsed | ( | servo_limrun_t * | r, |
| bool | ok, | ||
| const uint16_t * | pulse_dus, | ||
| uint32_t | now_ms ) |
Feed the end of the pulse write: the pulses the servo holds.
| r | Run state. |
| ok | false ends the run as ABORTED with WRITE. |
| pulse_dus | NEUTRAL, PULSE LOWER and PULSE UPPER, 0.1us. NULL ends the run as WRITE. |
| now_ms | Time of the answer, ms. |
| void servo_limrun_refused | ( | servo_limrun_t * | r, |
| uint32_t | now_ms ) |
The programmer refused the CONNECT, write or LEAVE asked: it never started.
| r | Run state. |
| now_ms | Time of the refusal, ms. |
| bool servo_limrun_report_line | ( | const servo_limrun_t * | r, |
| unsigned | idx, | ||
| char * | buf, | ||
| size_t | n ) |
Line idx of the report into buf; false past the last.
| r | Run state. |
| idx | Line index, from 0. |
| buf | Out: line text. |
| n | Size of buf, bytes. |
| bool servo_limrun_restore | ( | const servo_limrun_t * | r | ) |
The run ended as FAIL or ABORTED with the servo's values changed: RESTORE gives back the ones before it.
| r | Run state. |
| bool servo_limrun_running | ( | const servo_limrun_t * | r | ) |
Tell whether the run is RUNNING.
| r | Run state. NULL gives false. |
| uint16_t servo_limrun_scaled | ( | uint16_t | v, |
| int32_t | d, | ||
| int32_t | span, | ||
| uint16_t | lo_raw ) |
The final value for value v and share d / span: floor(v x
share), within lo_raw to v.
| v | Value the share applies to. |
| d | Distance of the free pulse from NEUTRAL, 0.1us. 0 or less returns the lower bound. |
| span | Span of the side, 0.1us. 0 or less returns the lower bound. |
| lo_raw | Smallest value the hard rules take. |
| int32_t servo_limrun_span | ( | const servo_limrun_servo_t * | sv, |
| uint8_t | side ) |
Span of one side, as servo_limrun_span() reports it.
| sv | Servo pulses, 0.1us. |
| side | SERVO_LIMRUN_LO or SERVO_LIMRUN_HI. |
| bool servo_limrun_start | ( | servo_limrun_t * | r, |
| const servo_limrun_cfg_t * | cfg, | ||
| uint32_t | now_ms ) |
Start at now_ms. False, and nothing started, for a configuration whose centre is not between its MIN and MAX.
| r | Run state. Cleared before the run starts. |
| cfg | Configuration of the run. |
| now_ms | Start time, ms. |
| void servo_limrun_step | ( | servo_limrun_t * | r, |
| uint32_t | now_ms, | ||
| const servo_limrun_in_t * | in, | ||
| servo_limrun_do_t * | out ) |
Advance to now_ms: what to do comes back in out.
| r | Run state. |
| now_ms | Current time, ms. |
| in | What the caller knows this step. NULL skips the checks on it. |
| out | Out: cleared, then filled with what the run wants done. NULL to skip. |
| void servo_limrun_supply | ( | servo_limrun_t * | r, |
| const servo_test_reading_t * | s, | ||
| uint32_t | now_ms ) |
The supply's reading.
The first one after the start, answering or not, is what it must stay at: its set points, and its output on or off. An output off then and on later, or a supply that did not answer and answers later, its output on or off, ends the run as a changed supply (SERVO_LIMRUN_WHY_SUPPLY_CHANGED). The caller passes a reading that does not answer where it has none at the start.
| r | Run state. |
| s | Supply reading. Ignored when NULL or during the programmer session. |
| now_ms | Time of the reading, ms. |
| void servo_limrun_supply_refused | ( | servo_limrun_t * | r, |
| bool | output_on, | ||
| uint32_t | now_ms ) |
The caller will not hand the programmer's CONNECT a PD mini that the run did not start with, or one whose output is off (output_on false). A supply the run started with, its output off, ends the run as a reading outside a session does (SERVO_TEST_AB_SUPPLY_OFF); one the run did not start with ends it as a changed supply (SERVO_LIMRUN_WHY_SUPPLY_CHANGED).
| r | Run state. |
| output_on | Whether the supply output is on. |
| now_ms | Time of the refusal, ms. |
| bool servo_limrun_switching | ( | const servo_limrun_t * | r | ) |
The run asked the bench to SAFE or to ARMED and waits for it, or holds the programmer: a disarm then is its own, not the operator's. Not while the servo returns to the centre before a session: a disarm then is the operator's.
| r | Run state. NULL gives false. |
| servo_str_t servo_limrun_verdict_str | ( | servo_limrun_verdict_t | v | ) |
The table entries the screen and the report name these by.
| v | Verdict to name. |
| servo_str_t servo_limrun_why_str | ( | const servo_limrun_t * | r | ) |
Name table entry for the reason of a run.
| r | Run state. NULL gives the NONE entry. |
| void servo_limrun_window | ( | servo_limrun_t * | r, |
| const servo_test_win_t * | w ) |
One INA3221 window, as the automatic test takes it.
| r | Run state. |
| w | Window to feed. Ignored when NULL or when it has no current reading. |
| void servo_limrun_written | ( | servo_limrun_t * | r, |
| bool | ok, | ||
| const uint16_t * | angle, | ||
| uint32_t | now_ms ) |
Feed the end of a write: the values the servo holds.
| r | Run state. |
| ok | false ends the run as ABORTED with WRITE. |
| angle | LEFT and RIGHT ANGLE the servo holds, two values. NULL ends the run as WRITE. |
| now_ms | Time of the answer, ms. |
| bool servo_limrun_wrote | ( | const servo_limrun_t * | r | ) |
A value was written and the servo may not hold its own any more.
| r | Run state. |