File syn_motor_ctrl.h¶
FileList > motor > syn_motor_ctrl.h
Go to the source code of this file
Closed-loop motor controller — generic feedback + PID + motor. More...
#include "../common/syn_defs.h"#include "../control/syn_pid.h"#include "../log/syn_datalog.h"#include "../motor/syn_motor_output.h"#include "../port/syn_port_system.h"#include "../system/syn_errlog.h"#include "../util/syn_ramp.h"#include "../util/syn_scurve.h"#include <stdbool.h>#include <stdint.h>
Classes¶
| Type | Name |
|---|---|
| struct | SYN_MotorCtrl Motor controller instance (opaque — use API to access). |
| struct | SYN_MotorCtrl_Config Motor controller configuration (passed to init, copied internally). |
| struct | SYN_MotorCtrl_Metrics Accumulated metrics for a single move/trajectory. |
| struct | SYN_MotorCtrl_Sample One sample of control-loop telemetry. |
| struct | SYN_MotorCtrl_Trajectory Trajectory setpoint for feedforward control. |
Public Types¶
| Type | Name |
|---|---|
| enum | SYN_MotorCtrl_Mode Control loop operating mode. |
| typedef int32_t(* | SYN_MotorCtrl_ReadPos Position feedback function. |
| typedef void(* | SYN_MotorCtrl_StallCallback Callback invoked when a motor stall is detected. |
| enum | SYN_MotorCtrl_State Motor controller runtime state. |
| typedef void(* | SYN_MotorCtrl_TargetCallback Callback invoked when position reaches the target deadband. |
Public Functions¶
| Type | Name |
|---|---|
| void | syn_motor_ctrl_clear_stall (SYN_MotorCtrl * ctrl) Clear a stall condition and return to idle. |
| void | syn_motor_ctrl_estop (SYN_MotorCtrl * ctrl) Emergency stop — immediate brake/coast. |
| SYN_Status | syn_motor_ctrl_init (SYN_MotorCtrl * ctrl, const SYN_MotorCtrl_Config * cfg) Initialize the closed-loop controller. |
| void | syn_motor_ctrl_move_to (SYN_MotorCtrl * ctrl, int32_t target, int32_t max_velocity, int32_t acceleration) Move to position with a built-in trapezoidal velocity profile. |
| void | syn_motor_ctrl_move_to_scurve (SYN_MotorCtrl * ctrl, int32_t target, int32_t max_velocity, int32_t max_accel, int32_t max_jerk) Move to position with a built-in jerk-limited S-curve profile. |
| void | syn_motor_ctrl_on_stall (SYN_MotorCtrl * ctrl, SYN_MotorCtrl_StallCallback cb, void * ctx) Register stall callback. |
| void | syn_motor_ctrl_on_target (SYN_MotorCtrl * ctrl, SYN_MotorCtrl_TargetCallback cb, void * ctx) Register on-target callback (position mode). |
| void | syn_motor_ctrl_reset_metrics (SYN_MotorCtrl * ctrl) Reset move metrics. Call before starting a move you want to measure. |
| int32_t | syn_motor_ctrl_rms_error (const SYN_MotorCtrl * ctrl) Compute RMS tracking error from accumulated metrics. |
| void | syn_motor_ctrl_set_datalog (SYN_MotorCtrl * ctrl, SYN_DataLog * log) Attach a datalog for tuning capture. |
| void | syn_motor_ctrl_set_ff_gains (SYN_MotorCtrl * ctrl, int32_t ff_kv, int32_t ff_ka) Update feedforward gains at runtime. |
| void | syn_motor_ctrl_set_gains (SYN_MotorCtrl * ctrl, int32_t kp, int32_t ki, int32_t kd) Update PID gains at runtime. |
| void | syn_motor_ctrl_set_output (SYN_MotorCtrl * ctrl, int32_t output) Drive the motor at a fixed output level (open-loop). |
| void | syn_motor_ctrl_set_position (SYN_MotorCtrl * ctrl, int32_t target) Set position target (absolute feedback units). |
| void | syn_motor_ctrl_set_trajectory (SYN_MotorCtrl * ctrl, const SYN_MotorCtrl_Trajectory * traj) Feed a trajectory point for feedforward + PID tracking. |
| void | syn_motor_ctrl_set_velocity (SYN_MotorCtrl * ctrl, int32_t units_per_sec) Set velocity target (units/second). |
| void | syn_motor_ctrl_stop (SYN_MotorCtrl * ctrl) Stop the motor and enter idle mode. |
| SYN_MotorCtrl_State | syn_motor_ctrl_update (SYN_MotorCtrl * ctrl) Run the control loop. Call at cfg.update_hz rate. |
Public Static Functions¶
| Type | Name |
|---|---|
| int32_t | syn_motor_ctrl_error (const SYN_MotorCtrl * ctrl) Get last position error. |
| int32_t | syn_motor_ctrl_ff_output (const SYN_MotorCtrl * ctrl) Get last feedforward output component. |
| const SYN_MotorCtrl_Metrics * | syn_motor_ctrl_get_metrics (const SYN_MotorCtrl * ctrl) Get accumulated move metrics. |
| SYN_MotorCtrl_Mode | syn_motor_ctrl_mode (const SYN_MotorCtrl * ctrl) Get the current operating mode. |
| uint32_t | syn_motor_ctrl_move_duration (const SYN_MotorCtrl * ctrl) Get move duration in milliseconds. |
| int32_t | syn_motor_ctrl_output (const SYN_MotorCtrl * ctrl) Get total output (PID + feedforward). |
| int32_t | syn_motor_ctrl_pid_output (const SYN_MotorCtrl * ctrl) Get last PID output component. |
| int32_t | syn_motor_ctrl_position (const SYN_MotorCtrl * ctrl) Get measured position. |
| uint32_t | syn_motor_ctrl_settle_time (const SYN_MotorCtrl * ctrl) Get settling time in milliseconds (0 if never settled). |
| SYN_MotorCtrl_State | syn_motor_ctrl_state (const SYN_MotorCtrl * ctrl) Get the current controller state. |
| int32_t | syn_motor_ctrl_velocity (const SYN_MotorCtrl * ctrl) Get measured velocity. |
Macros¶
| Type | Name |
|---|---|
| define | SYN_MCTRL_DATALOG_ID 0x4D43 /\* 'MC' \*/ |
| define | SYN_MOTOR_CTRL_DEFAULTS (motor_out, read_fn, read_ctx, hz, out_max) /* multi line expression */Convenience macro for a motor controller config with sane defaults. |
Detailed Description¶
Combines any position/velocity feedback source with PID control to drive DC or stepper motors in closed loop. The feedback source is a function pointer, so it works equally well with: * Rotary encoder (syn_encoder) * Potentiometer / linear pot on ADC (syn_adc) * Hall sensor, absolute encoder, or any other position source
** **
- Velocity: PID maintains target units/second
- Position: PID drives to target position value
- Trajectory: PID + feedforward tracks a trajectory from an external generator (syn_ramp, syn_scurve, or application code)
** **
// Feedback: read encoder position
int32_t encoder_feedback(void *ctx) {
return syn_encoder_position((SYN_Encoder *)ctx);
}
SYN_MotorCtrl ctrl;
SYN_MotorCtrl_Config cfg = {
.motor = syn_dc_motor_output(&my_dc),
.read_pos = encoder_feedback,
.read_pos_ctx = &my_encoder,
.pid_kp = 200, .pid_ki = 50, .pid_kd = 10, .pid_scale = 8,
.update_hz = 1000,
.output_min = -1000, .output_max = 1000,
};
syn_motor_ctrl_init(&ctrl, &cfg);
syn_motor_ctrl_set_velocity(&ctrl, 500); // 500 counts/sec
** **
SYN_MotorCtrl_Config cfg = {
// ... feedback, motor, PID as above ...
.ff_kv = 128, // velocity feedforward gain
.ff_ka = 64, // acceleration feedforward gain
.ff_scale = 8, // feedforward divisor = 1 << 8 = 256
};
syn_motor_ctrl_init(&ctrl, &cfg);
// In your control loop, feed trajectory from any generator:
SYN_MotorCtrl_Trajectory traj = {
.position = profile_position,
.velocity = profile_velocity,
.acceleration = profile_acceleration,
};
syn_motor_ctrl_set_trajectory(&ctrl, &traj);
syn_motor_ctrl_update(&ctrl);
Public Types Documentation¶
enum SYN_MotorCtrl_Mode¶
Control loop operating mode.
enum SYN_MotorCtrl_Mode {
SYN_MCTRL_MODE_IDLE = 0,
SYN_MCTRL_MODE_VELOCITY = 1,
SYN_MCTRL_MODE_POSITION = 2,
SYN_MCTRL_MODE_OPEN_LOOP = 3
};
typedef SYN_MotorCtrl_ReadPos¶
Position feedback function.
Returns the current position in whatever units the sensor provides (encoder counts, ADC ticks, millivolts — the PID doesn't care). The same units must be used for all targets and deadbands.
Parameters:
ctxUser context.
Returns:
Current position in feedback units.
typedef SYN_MotorCtrl_StallCallback¶
Callback invoked when a motor stall is detected.
Parameters:
ctrlController that detected the stall.ctxUser context.
enum SYN_MotorCtrl_State¶
Motor controller runtime state.
enum SYN_MotorCtrl_State {
SYN_MCTRL_STOPPED = 0,
SYN_MCTRL_RUNNING = 1,
SYN_MCTRL_ON_TARGET = 2,
SYN_MCTRL_STALLED = 3,
SYN_MCTRL_LIMIT = 4
};
typedef SYN_MotorCtrl_TargetCallback¶
Callback invoked when position reaches the target deadband.
Parameters:
ctrlController that reached target.ctxUser context.
Public Functions Documentation¶
function syn_motor_ctrl_clear_stall¶
Clear a stall condition and return to idle.
After a stall, the controller locks in STALLED state until this is called.
Parameters:
ctrlController instance.
function syn_motor_ctrl_estop¶
Emergency stop — immediate brake/coast.
Parameters:
ctrlController instance.
function syn_motor_ctrl_init¶
Initialize the closed-loop controller.
Parameters:
ctrlController instance to initialize.cfgConfiguration (copied internally).
Returns:
SYN_OK on success.
function syn_motor_ctrl_move_to¶
Move to position with a built-in trapezoidal velocity profile.
void syn_motor_ctrl_move_to (
SYN_MotorCtrl * ctrl,
int32_t target,
int32_t max_velocity,
int32_t acceleration
)
This is the "batteries included" path — no external profile generator needed. The controller internally generates a trapezoidal ramp (accelerate → cruise → decelerate) and feeds it through the normal trajectory/feedforward path each update() call.
Equivalent to manually calling syn_ramp_set_target_trapezoid() and feeding the output into set_trajectory() each tick, but with zero user-side wiring.
Parameters:
ctrlController instance.targetTarget position in feedback units.max_velocityMaximum velocity (units/second).accelerationAcceleration (units/second²).
function syn_motor_ctrl_move_to_scurve¶
Move to position with a built-in jerk-limited S-curve profile.
void syn_motor_ctrl_move_to_scurve (
SYN_MotorCtrl * ctrl,
int32_t target,
int32_t max_velocity,
int32_t max_accel,
int32_t max_jerk
)
Like move_to(), but uses a 7-phase S-curve trajectory that bounds jerk for the smoothest possible motion. The S-curve natively provides position, velocity, and acceleration — all three are fed into the trajectory/feedforward path.
All kinematic limits are in per-second units: * max_velocity: units/second * max_accel: units/second² * max_jerk: units/second³
Parameters:
ctrlController instance.targetTarget position in feedback units.max_velocityMaximum velocity (units/second).max_accelMaximum acceleration (units/second²).max_jerkMaximum jerk (units/second³).
function syn_motor_ctrl_on_stall¶
Register stall callback.
Parameters:
ctrlController instance.cbCallback function, or NULL to unregister.ctxUser context passed to callback.
function syn_motor_ctrl_on_target¶
Register on-target callback (position mode).
Parameters:
ctrlController instance.cbCallback function, or NULL to unregister.ctxUser context passed to callback.
function syn_motor_ctrl_reset_metrics¶
Reset move metrics. Call before starting a move you want to measure.
Parameters:
ctrlController instance.
function syn_motor_ctrl_rms_error¶
Compute RMS tracking error from accumulated metrics.
Returns the integer square root of (error_sq_sum / sample_count). Only valid if sample_count > 0.
Parameters:
ctrlController instance.
Returns:
RMS tracking error in feedback units.
function syn_motor_ctrl_set_datalog¶
Attach a datalog for tuning capture.
When attached, every update() writes a SYN_MotorCtrl_Sample frame to the datalog at full control-loop rate.
Parameters:
ctrlController.logDatalog instance (caller-owned), or NULL to detach.
function syn_motor_ctrl_set_ff_gains¶
Update feedforward gains at runtime.
Parameters:
ctrlController instance.ff_kvVelocity feedforward gain (÷ 1 << ff_scale).ff_kaAcceleration feedforward gain (÷ 1 << ff_scale).
function syn_motor_ctrl_set_gains¶
Update PID gains at runtime.
Parameters:
ctrlController instance.kpProportional gain (÷ 1 << pid_scale).kiIntegral gain (÷ 1 << pid_scale).kdDerivative gain (÷ 1 << pid_scale).
function syn_motor_ctrl_set_output¶
Drive the motor at a fixed output level (open-loop).
Bypasses PID — the output value is passed directly to the motor. Useful for manual jogging, testing motor wiring, or when simple open-loop control is sufficient. Position feedback is still read (for soft limits and stall detection) but not used for control.
Parameters:
ctrlController instance.outputOutput level (clamped to [output_min, output_max]).
function syn_motor_ctrl_set_position¶
Set position target (absolute feedback units).
Switches to position mode. Controller drives toward target and enters ON_TARGET state when within deadband.
Parameters:
ctrlController instance.targetAbsolute position in feedback units.
function syn_motor_ctrl_set_trajectory¶
Feed a trajectory point for feedforward + PID tracking.
Call this each update with the current output of your trajectory generator (syn_ramp, syn_scurve, or application code). The controller uses PID on position error plus feedforward from the trajectory's velocity and acceleration.
Parameters:
ctrlController instance.trajTrajectory point (position, velocity, acceleration).
function syn_motor_ctrl_set_velocity¶
Set velocity target (units/second).
Switches to velocity mode. Positive = forward, negative = reverse.
Parameters:
ctrlController instance.units_per_secTarget velocity in feedback units per second.
function syn_motor_ctrl_stop¶
Stop the motor and enter idle mode.
Parameters:
ctrlController instance.
function syn_motor_ctrl_update¶
Run the control loop. Call at cfg.update_hz rate.
Reads feedback, computes PID, drives motor output. If a datalog is attached, writes a SYN_MotorCtrl_Sample each call.
Parameters:
ctrlController instance.
Returns:
Current controller state.
Public Static Functions Documentation¶
function syn_motor_ctrl_error¶
Get last position error.
Parameters:
ctrlController.
Returns:
Position error in feedback units.
function syn_motor_ctrl_ff_output¶
Get last feedforward output component.
Parameters:
ctrlController.
Returns:
Feedforward output.
function syn_motor_ctrl_get_metrics¶
Get accumulated move metrics.
static inline const SYN_MotorCtrl_Metrics * syn_motor_ctrl_get_metrics (
const SYN_MotorCtrl * ctrl
)
Read this after a move completes to evaluate performance. Contains max error, RMS error data, overshoot, peak output, and timing — everything needed for tuning, in a single read.
Parameters:
ctrlController.
Returns:
Pointer to metrics struct.
function syn_motor_ctrl_mode¶
Get the current operating mode.
Parameters:
ctrlController.
Returns:
Operating mode.
function syn_motor_ctrl_move_duration¶
Get move duration in milliseconds.
Parameters:
ctrlController.
Returns:
Duration in ms, or 0 if no move started.
function syn_motor_ctrl_output¶
Get total output (PID + feedforward).
Parameters:
ctrlController.
Returns:
Combined output.
function syn_motor_ctrl_pid_output¶
Get last PID output component.
Parameters:
ctrlController.
Returns:
PID output.
function syn_motor_ctrl_position¶
Get measured position.
Parameters:
ctrlController.
Returns:
Position in feedback units.
function syn_motor_ctrl_settle_time¶
Get settling time in milliseconds (0 if never settled).
Parameters:
ctrlController.
Returns:
Settle time in ms.
function syn_motor_ctrl_state¶
Get the current controller state.
Parameters:
ctrlController.
Returns:
Runtime state.
function syn_motor_ctrl_velocity¶
Get measured velocity.
Parameters:
ctrlController.
Returns:
Velocity in feedback units/second.
Macro Definition Documentation¶
define SYN_MCTRL_DATALOG_ID¶
Datalog stream ID for motor controller telemetry.
define SYN_MOTOR_CTRL_DEFAULTS¶
Convenience macro for a motor controller config with sane defaults.
#define SYN_MOTOR_CTRL_DEFAULTS (
motor_out,
read_fn,
read_ctx,
hz,
out_max
) `/* multi line expression */`
Provides a conservative P-only configuration that is stable on most systems. Override individual fields after initialization to tune.
Parameters:
motor_outSYN_MotorOutput (e.g., syn_dc_motor_output(&motor)).read_fnPosition read function.read_ctxContext for read_fn (NULL if unused).hzControl loop frequency (e.g., 1000).out_maxMaximum output magnitude (symmetric ±out_max).
** **
SYN_MotorCtrl_Config cfg = SYN_MOTOR_CTRL_DEFAULTS(
syn_dc_motor_output(&motor), encoder_read, NULL, 1000, 1000
);
cfg.pid_ki = 500; // add integral if needed
syn_motor_ctrl_init(&ctrl, &cfg);
The documentation for this class was generated from the following file src/syntropic/motor/syn_motor_ctrl.h