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

Synchronising two servos that drive one control surface. More...

#include <stdbool.h>
#include <stdint.h>

Go to the source code of this file.

Data Structures

struct  servo_sync_cfg_t
struct  servo_sync_t

Macros

#define SERVO_SYNC_MAX_POINTS   9
 The most points one round of a scan may have.
#define SERVO_SYNC_MIN_US   500u
 The pulse widths the search commands stay within, microseconds.
#define SERVO_SYNC_MAX_US   2500u

Enumerations

enum  servo_sync_state_t { SERVO_SYNC_RUNNING = 0 , SERVO_SYNC_DONE , SERVO_SYNC_FAULT }
enum  servo_sync_fault_t { SERVO_SYNC_FAULT_NONE = 0 , SERVO_SYNC_FAULT_OVERCURRENT , SERVO_SYNC_FAULT_NO_MINIMUM }
enum  servo_sync_stage_t { SERVO_SYNC_STAGE_CENTRE = 0 , SERVO_SYNC_STAGE_HIGH , SERVO_SYNC_STAGE_LOW , SERVO_SYNC_STAGE_COUNT }
 Which of the three measurements the search is on.

Functions

void servo_sync_defaults (servo_sync_cfg_t *cfg, uint16_t centre_us)
 Defaults for a sync search.
void servo_sync_init (servo_sync_t *sy, const servo_sync_cfg_t *cfg)
 Start a sync search at the centre stage.
void servo_sync_step (servo_sync_t *sy, float total_a, uint32_t now_ms, uint16_t *cmd_a, uint16_t *cmd_b)
 Advance the search with one reading of the pair's total current.
float servo_sync_progress (const servo_sync_t *sy)
 0..1 across all three stages.

Detailed Description

Synchronising two servos that drive one control surface.

Dual ailerons, elevator halves, a rudder on two horns: two servos on one surface settle any disagreement between them through the surface. Nothing fails and nothing reports it; both servos push against each other and draw extra current continuously.

The objective is not a position. There is no reference angle. The total current the pair draws is smallest where they stop working against each other, which makes the problem a one-dimensional search per stage.

The two errors separate:

a difference at centre   is an offset error  -> trim one servo's centre
a difference at the ends is a travel error   -> scale one servo's throw

Measured at the centre and then at each end, each correction comes from its own measurement. Each end gets its own number: a linkage is not symmetric about centre once a horn and a pushrod are involved, the same reason the limit search measures both ends.

Current cannot show two servos that agree with each other and are both wrong: a surface that is stiff nowhere and sits 5 degrees off. That is a separate measurement with the accelerometer on the surface.

Fed measurements and returning commands, as servo_limit is: the host suite runs it against a modelled pair, and a real pair needs no change here. No firmware calls it.

SPDX-License-Identifier: MIT

Enumeration Type Documentation

◆ servo_sync_fault_t

Enumerator
SERVO_SYNC_FAULT_OVERCURRENT 

Current crossed the hard ceiling.

Stops where it stands.

SERVO_SYNC_FAULT_NO_MINIMUM 

The scan found no minimum distinguishable from the noise, or none inside its window.

A pair that is already synchronised still produces a minimum, at zero correction, because the scan moves one servo away from agreement. So this fault means the sensor cannot resolve the difference, and it is reported rather than a correction derived from noise. The first round's lowest point at an end of the window says the minimum lies outside it (a correction of more than window_us, or a mirrored pair); that is reported the same way, not taken as the answer.

Function Documentation

◆ servo_sync_defaults()

void servo_sync_defaults ( servo_sync_cfg_t * cfg,
uint16_t centre_us )

Defaults for a sync search.

Parameters
cfgConfiguration to fill. Does nothing when NULL.
centre_usCentre pulse width, us.

◆ servo_sync_init()

void servo_sync_init ( servo_sync_t * sy,
const servo_sync_cfg_t * cfg )

Start a sync search at the centre stage.

Parameters
sySearch state to initialise. Does nothing when NULL.
cfgConfiguration to copy. Does nothing when NULL.

◆ servo_sync_progress()

float servo_sync_progress ( const servo_sync_t * sy)

0..1 across all three stages.

Parameters
sySearch state. NULL gives 0.0.
Returns
0.0 to 1.0; 1.0 once the search is not RUNNING.

◆ servo_sync_step()

void servo_sync_step ( servo_sync_t * sy,
float total_a,
uint32_t now_ms,
uint16_t * cmd_a,
uint16_t * cmd_b )

Advance the search with one reading of the pair's total current.

Total, not per servo: the quantity minimised is what the two draw together, so one sensor across both outputs is enough.

Writes the two pulse widths to command through cmd_a and cmd_b.

Parameters
sySearch state.
total_aTotal current of the pair, A.
now_msTime of the reading, ms.
cmd_aOut: pulse width for servo A, us. NULL to skip.
cmd_bOut: pulse width for servo B, us. NULL to skip.