// ============================================================================= // pid_inner_task.h -- 50 Hz inner-loop control task (Sprint 2) // ============================================================================= // // Wraps the header-only PidInner controller in a FreeRTOS task pinned to // Core 1 (real-time core). Reads the rudder position from hal::rudder_sensor, // consumes the setpoint that the outer loop / Modbus client wrote, and // commands hal::rudder_actuator. Refuses to act in STANDBY or with master // power off (those interlocks live in hal::rudder_command itself). // ============================================================================= #pragma once #include "pid_inner.h" namespace arautopilot::pid { /// Initialise the controller with the seed gains. Must be called from /// setup() once. void pid_inner_task_init(); /// Spawn the FreeRTOS task. Must be called after pid_inner_task_init(). void pid_inner_task_start(); /// Update the setpoint that the inner loop pursues. Called by the Modbus /// slave (when an operator writes a holding register) and, later, by the /// outer loop task. Units: degrees, signed. void pid_inner_set_setpoint_deg(float setpoint_deg); /// Read the current setpoint (thread-safe). float pid_inner_setpoint_deg(); /// Read the latest PID output command (signed PWM percent). float pid_inner_last_output_pct(); /// Read the latest error (deg) the controller saw. float pid_inner_last_error_deg(); /// Hot-swap gains at runtime (thread-safe). void pid_inner_update_gains(float kp, float ki, float kd); /// Read the gains currently in use. void pid_inner_get_gains(float& kp, float& ki, float& kd); } // namespace arautopilot::pid