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

A servo swept through a curve: square, sine or triangle about its centre. More...

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

Go to the source code of this file.

Data Structures

struct  sweep_cfg_t
struct  sweep_t

Macros

#define SWEEP_MHZ_MIN   50u
 The slowest and fastest curve, in thousandths of a cycle a second.
#define SWEEP_MHZ_MAX   5000u
#define SWEEP_AMPLITUDE_MAX   500u
 The furthest from the centre a sweep goes, in command units.
#define SWEEP_DWELL_MAX_MS   5000u
 The longest hold at an end.
#define SWEEP_CENTRE   500u
 The centre, in command units.

Enumerations

enum  sweep_kind_t {
  SWEEP_OFF = 0 , SWEEP_SQUARE , SWEEP_SINE , SWEEP_TRIANGLE ,
  SWEEP_KIND_COUNT
}

Functions

bool sweep_cfg_valid (const sweep_cfg_t *cfg)
 Whether cfg is one a sweep can run: a curve, a speed and an amplitude in range, and a dwell no longer than SWEEP_DWELL_MAX_MS.
bool sweep_start (sweep_t *w, const sweep_cfg_t *cfg, uint32_t now_ms)
 Start cfg at now_ms. False, and stopped, for a configuration sweep_cfg_valid() refuses.
void sweep_stop (sweep_t *w)
 Stop, and forget any paused phase.
void sweep_pause (sweep_t *w, uint32_t now_ms)
 Stop a running sweep at now_ms and keep how far into it it was, so sweep_resume() carries on from there: the same point of the curve, the same dwell, the movements reached so far. Nothing for a sweep that is not running, finished included.
bool sweep_resume (sweep_t *w, uint32_t now_ms)
 Carry a paused sweep on at now_ms from where it was paused. False, and nothing changes, when nothing is paused: never paused, stopped or started since.
bool sweep_step (sweep_t *w, uint32_t now_ms, uint16_t *command)
 The command at now_ms into command. True while the sweep runs; false once it has stopped or made its movements, with command at the centre. The clock may wrap.
uint32_t sweep_moves (const sweep_t *w, uint32_t now_ms)
 How many ends the sweep has reached by now_ms, the moves limit included once reached.
bool sweep_slew_limited (const sweep_cfg_t *cfg, uint16_t slew_per_s)
 Whether a slew of slew_per_s command units a second is slower than the fastest change cfg's curve asks for, so the slew and not the curve decides how the output moves. The fastest change, at amplitude A and f = mhz / 1000 cycles a second, is 2 pi f A for a sine (at the centre) and 4 f A for a triangle (throughout). A square jumps, so any slew limits it. The dwell does not enter: it adds time at the ends, not to the motion.

Detailed Description

A servo swept through a curve: square, sine or triangle about its centre.

The curve runs where the pins are, on the IOmcu, so its timing does not depend on the link: a 5Hz sine over a CAN round trip of tens of milliseconds would be a staircase. The panel computes the same curve with the same code to draw the horn.

One cycle, of period 1000 / mhz seconds plus the dwells, starts at the centre and goes to +amplitude, holds there for dwell_ms, goes to -amplitude, holds again and comes back to the centre, where the next cycle carries on towards +amplitude. A square jumps between the ends at the cycle's start and half; a sine and a triangle start at the centre, so a sweep begins without a jump. An end is counted as a movement when the curve reaches it – a quarter cycle after the jump for a square.

With a movement count the sweep ends once that many ends have been reached and the last dwell is over, and the command goes back to the centre.

Commands are in the bank's units, 0..OUT_SPAN of the channel's own travel, with the centre at OUT_SPAN / 2.

SPDX-License-Identifier: MIT

Function Documentation

◆ sweep_cfg_valid()

bool sweep_cfg_valid ( const sweep_cfg_t * cfg)

Whether cfg is one a sweep can run: a curve, a speed and an amplitude in range, and a dwell no longer than SWEEP_DWELL_MAX_MS.

Parameters
cfgConfiguration to check.
Returns
true when cfg is not NULL, its kind is not SWEEP_OFF, mhz is SWEEP_MHZ_MIN to SWEEP_MHZ_MAX, amplitude is at most SWEEP_AMPLITUDE_MAX and dwell_ms at most SWEEP_DWELL_MAX_MS.

◆ sweep_moves()

uint32_t sweep_moves ( const sweep_t * w,
uint32_t now_ms )

How many ends the sweep has reached by now_ms, the moves limit included once reached.

Parameters
wSweep state. NULL or an invalid sweep gives 0.
now_msCurrent time, ms.
Returns
ends reached, at most the moves limit when moves is not 0; saturates at UINT32_MAX.

◆ sweep_pause()

void sweep_pause ( sweep_t * w,
uint32_t now_ms )

Stop a running sweep at now_ms and keep how far into it it was, so sweep_resume() carries on from there: the same point of the curve, the same dwell, the movements reached so far. Nothing for a sweep that is not running, finished included.

Parameters
wSweep state. NULL is ignored.
now_msTime of the pause, ms.

◆ sweep_resume()

bool sweep_resume ( sweep_t * w,
uint32_t now_ms )

Carry a paused sweep on at now_ms from where it was paused. False, and nothing changes, when nothing is paused: never paused, stopped or started since.

Parameters
wSweep state. NULL gives false.
now_msTime of the resume, ms.
Returns
true when a paused sweep was resumed; false for a NULL w or when nothing is paused.

◆ sweep_slew_limited()

bool sweep_slew_limited ( const sweep_cfg_t * cfg,
uint16_t slew_per_s )

Whether a slew of slew_per_s command units a second is slower than the fastest change cfg's curve asks for, so the slew and not the curve decides how the output moves. The fastest change, at amplitude A and f = mhz / 1000 cycles a second, is 2 pi f A for a sine (at the centre) and 4 f A for a triangle (throughout). A square jumps, so any slew limits it. The dwell does not enter: it adds time at the ends, not to the motion.

A slew of 0 is no limit, as on an output channel, and limits nothing. False for a configuration sweep_cfg_valid() refuses and for an amplitude of 0, which asks for no change.

Parameters
cfgConfiguration of the curve.
slew_per_sSlew limit, command units a second. 0 is no limit.
Returns
true when the slew limits the curve; false for an invalid cfg, a slew of 0 or an amplitude of 0.

◆ sweep_start()

bool sweep_start ( sweep_t * w,
const sweep_cfg_t * cfg,
uint32_t now_ms )

Start cfg at now_ms. False, and stopped, for a configuration sweep_cfg_valid() refuses.

Parameters
wSweep state. NULL gives false.
cfgConfiguration to run, checked by sweep_cfg_valid().
now_msStart time, ms.
Returns
true when the sweep started; false for a NULL w or an invalid cfg.

◆ sweep_step()

bool sweep_step ( sweep_t * w,
uint32_t now_ms,
uint16_t * command )

The command at now_ms into command. True while the sweep runs; false once it has stopped or made its movements, with command at the centre. The clock may wrap.

Parameters
wSweep state. Stops the sweep once its moves are made.
now_msCurrent time, ms.
commandOut: command in units, 0 to 2 x SWEEP_CENTRE. NULL to skip.
Returns
true while the sweep runs; false for a NULL w, a stopped sweep or one whose moves are made.

◆ sweep_stop()

void sweep_stop ( sweep_t * w)

Stop, and forget any paused phase.

Parameters
wSweep state. NULL is ignored.