From 899ce6731d5f94b4c17a9b42690bd9df0c82b908 Mon Sep 17 00:00:00 2001
From: pichim <93905657+pichim@users.noreply.github.com>
Date: Tue, 21 Jan 2025 11:22:35 +0100
Subject: [PATCH] Chirp signal generator as flight mode (#13105)
---
mk/source.mk | 1 +
src/main/blackbox/blackbox.c | 11 ++++
src/main/build/debug.c | 1 +
src/main/build/debug.h | 1 +
src/main/cli/settings.c | 11 ++++
src/main/common/chirp.c | 94 +++++++++++++++++++++++++++++++++++
src/main/common/chirp.h | 37 ++++++++++++++
src/main/fc/core.c | 10 ++++
src/main/fc/parameter_names.h | 9 ++++
src/main/fc/rc_modes.h | 1 +
src/main/fc/runtime_config.h | 3 +-
src/main/flight/pid.c | 58 +++++++++++++++++++++
src/main/flight/pid.h | 24 +++++++++
src/main/flight/pid_init.c | 19 +++++++
src/main/msp/msp_box.c | 5 ++
src/main/osd/osd_elements.c | 5 ++
src/main/osd/osd_warnings.c | 10 ++++
src/main/telemetry/crsf.c | 2 +
18 files changed, 301 insertions(+), 1 deletion(-)
create mode 100644 src/main/common/chirp.c
create mode 100644 src/main/common/chirp.h
diff --git a/mk/source.mk b/mk/source.mk
index 9f837c9caa..8fe65dde2f 100644
--- a/mk/source.mk
+++ b/mk/source.mk
@@ -57,6 +57,7 @@ COMMON_SRC = \
build/version.c \
main.c \
common/bitarray.c \
+ common/chirp.c \
common/colorconversion.c \
common/crc.c \
common/encoding.c \
diff --git a/src/main/blackbox/blackbox.c b/src/main/blackbox/blackbox.c
index c8f359b924..acebd8c2c2 100644
--- a/src/main/blackbox/blackbox.c
+++ b/src/main/blackbox/blackbox.c
@@ -1642,6 +1642,17 @@ static bool blackboxWriteSysinfo(void)
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_S_YAW, "%d", currentPidProfile->pid[PID_YAW].S);
#endif // USE_WING
+#ifdef USE_CHIRP
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_LAG_FREQ_HZ, "%d", currentPidProfile->chirp_lag_freq_hz);
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_LEAD_FREQ_HZ, "%d", currentPidProfile->chirp_lead_freq_hz);
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_AMPLITUDE_ROLL, "%d", currentPidProfile->chirp_amplitude_roll);
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_AMPLITUDE_PITCH, "%d", currentPidProfile->chirp_amplitude_pitch);
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_AMPLITUDE_YAW, "%d", currentPidProfile->chirp_amplitude_yaw);
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_FREQUENCY_START_DECI_HZ, "%d", currentPidProfile->chirp_frequency_start_deci_hz);
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_FREQUENCY_END_DECI_HZ, "%d", currentPidProfile->chirp_frequency_end_deci_hz);
+ BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_CHIRP_TIME_SECONDS, "%d", currentPidProfile->chirp_time_seconds);
+#endif // USE_CHIRP
+
// End of Betaflight controller parameters
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_DEADBAND, "%d", rcControlsConfig()->deadband);
diff --git a/src/main/build/debug.c b/src/main/build/debug.c
index 3d67bae371..fb8795bd42 100644
--- a/src/main/build/debug.c
+++ b/src/main/build/debug.c
@@ -124,4 +124,5 @@ const char * const debugModeNames[DEBUG_COUNT] = {
[DEBUG_GIMBAL] = "GIMBAL",
[DEBUG_WING_SETPOINT] = "WING_SETPOINT",
[DEBUG_AUTOPILOT_POSITION] = "AUTOPILOT_POSITION",
+ [DEBUG_CHIRP] = "CHIRP",
};
diff --git a/src/main/build/debug.h b/src/main/build/debug.h
index 6e6e43a67a..b72ebdb496 100644
--- a/src/main/build/debug.h
+++ b/src/main/build/debug.h
@@ -126,6 +126,7 @@ typedef enum {
DEBUG_GIMBAL,
DEBUG_WING_SETPOINT,
DEBUG_AUTOPILOT_POSITION,
+ DEBUG_CHIRP,
DEBUG_COUNT
} debugType_e;
diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c
index 3e79fc4d78..3db4343db9 100644
--- a/src/main/cli/settings.c
+++ b/src/main/cli/settings.c
@@ -1263,6 +1263,17 @@ const clivalue_t valueTable[] = {
{ PARAM_NAME_HORIZON_IGNORE_STICKS, VAR_UINT8 | PROFILE_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_PID_PROFILE, offsetof(pidProfile_t, horizon_ignore_sticks) },
{ PARAM_NAME_HORIZON_DELAY_MS, VAR_UINT16 | PROFILE_VALUE, .config.minmaxUnsigned = { 10, 5000 }, PG_PID_PROFILE, offsetof(pidProfile_t, horizon_delay_ms) },
+#ifdef USE_CHIRP
+ { PARAM_NAME_CHIRP_LAG_FREQ_HZ, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 255 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_lag_freq_hz) },
+ { PARAM_NAME_CHIRP_LEAD_FREQ_HZ, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 255 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_lead_freq_hz) },
+ { PARAM_NAME_CHIRP_AMPLITUDE_ROLL, VAR_UINT16 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 500 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_amplitude_roll) },
+ { PARAM_NAME_CHIRP_AMPLITUDE_PITCH, VAR_UINT16 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 500 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_amplitude_pitch) },
+ { PARAM_NAME_CHIRP_AMPLITUDE_YAW, VAR_UINT16 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 500 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_amplitude_yaw) },
+ { PARAM_NAME_CHIRP_FREQUENCY_START_DECI_HZ, VAR_UINT16 | PROFILE_VALUE, .config.minmaxUnsigned = { 1, 1000 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_frequency_start_deci_hz) },
+ { PARAM_NAME_CHIRP_FREQUENCY_END_DECI_HZ, VAR_UINT16 | PROFILE_VALUE, .config.minmaxUnsigned = { 1, 10000 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_frequency_end_deci_hz) },
+ { PARAM_NAME_CHIRP_TIME_SECONDS, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 1, 255 }, PG_PID_PROFILE, offsetof(pidProfile_t, chirp_time_seconds) },
+#endif
+
#if defined(USE_ABSOLUTE_CONTROL)
{ PARAM_NAME_ABS_CONTROL_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 20 }, PG_PID_PROFILE, offsetof(pidProfile_t, abs_control_gain) },
{ "abs_control_limit", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 10, 255 }, PG_PID_PROFILE, offsetof(pidProfile_t, abs_control_limit) },
diff --git a/src/main/common/chirp.c b/src/main/common/chirp.c
new file mode 100644
index 0000000000..20aff3db14
--- /dev/null
+++ b/src/main/common/chirp.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of Betaflight.
+ *
+ * Betaflight is free software. You can redistribute this software
+ * and/or modify this software under the terms of the GNU General
+ * Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * Betaflight is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this software.
+ *
+ * If not, see .
+ */
+
+#include
+
+#include "platform.h"
+
+#include "maths.h"
+
+#include "chirp.h"
+
+// initialize the chirp signal generator
+// f0: start frequency in Hz
+// f1: end frequency in Hz
+// t1: signal length in seconds
+// looptimeUs: loop time in microseconds
+void chirpInit(chirp_t *chirp, const float f0, const float f1, const float t1, const uint32_t looptimeUs)
+{
+ chirp->f0 = f0;
+ chirp->Ts = looptimeUs * 1e-6f;
+ chirp->N = (uint32_t)(t1 / chirp->Ts);
+ chirp->beta = pow_approx(f1 / f0, 1.0f / t1);
+ chirp->k0 = 2.0f * M_PIf / log_approx(chirp->beta);
+ chirp->k1 = chirp->k0 * f0;
+ chirpReset(chirp);
+}
+
+// reset the chirp signal generator fully
+void chirpReset(chirp_t *chirp)
+{
+ chirp->count = 0;
+ chirp->isFinished = false;
+ chirpResetSignals(chirp);
+}
+
+// reset the chirp signal generator signals
+void chirpResetSignals(chirp_t *chirp)
+{
+ chirp->exc = 0.0f;
+ chirp->fchirp = 0.0f;
+ chirp->sinarg = 0.0f;
+}
+
+// update the chirp signal generator
+bool chirpUpdate(chirp_t *chirp)
+{
+ if (chirp->isFinished) {
+
+ return false;
+
+ } else if (chirp->count == chirp->N) {
+
+ chirp->isFinished = true;
+ chirpResetSignals(chirp);
+ return false;
+
+ } else {
+
+ chirp->fchirp = chirp->f0 * pow_approx(chirp->beta, (float)(chirp->count) * chirp->Ts);
+ chirp->sinarg = chirp->k0 * chirp->fchirp - chirp->k1;
+
+ // wrap sinarg to 0...2*pi
+ chirp->sinarg = fmodf(chirp->sinarg, 2.0f * M_PIf);
+
+ // use cosine so that the angle will oscillate around 0 (integral of gyro)
+ chirp->exc = cos_approx(chirp->sinarg);
+
+ // frequencies below 1 Hz will lead to the same angle magnitude as at 1 Hz (integral of gyro)
+ if (chirp->fchirp < 1.0f) {
+ chirp->exc = chirp->fchirp * chirp->exc;
+ }
+ chirp->count++;
+
+ return true;
+ }
+}
diff --git a/src/main/common/chirp.h b/src/main/common/chirp.h
new file mode 100644
index 0000000000..211a7c66e1
--- /dev/null
+++ b/src/main/common/chirp.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of Betaflight.
+ *
+ * Betaflight is free software. You can redistribute this software
+ * and/or modify this software under the terms of the GNU General
+ * Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * Betaflight is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this software.
+ *
+ * If not, see .
+ */
+
+#pragma once
+
+#include
+#include
+
+typedef struct chirp_s {
+ float f0, Ts, beta, k0, k1;
+ uint32_t count, N;
+ float exc, fchirp, sinarg;
+ bool isFinished;
+} chirp_t;
+
+void chirpInit(chirp_t *chirp, const float f0, const float f1, const float t1, const uint32_t looptimeUs);
+void chirpReset(chirp_t *chirp);
+void chirpResetSignals(chirp_t *chirp);
+bool chirpUpdate(chirp_t *chirp);
diff --git a/src/main/fc/core.c b/src/main/fc/core.c
index 889204938b..75bd3100d0 100644
--- a/src/main/fc/core.c
+++ b/src/main/fc/core.c
@@ -1092,6 +1092,16 @@ void processRxModes(timeUs_t currentTimeUs)
}
#endif
+#ifdef USE_CHIRP
+ if (IS_RC_MODE_ACTIVE(BOXCHIRP) && !FLIGHT_MODE(FAILSAFE_MODE) && !FLIGHT_MODE(GPS_RESCUE_MODE)) {
+ if (!FLIGHT_MODE(CHIRP_MODE)) {
+ ENABLE_FLIGHT_MODE(CHIRP_MODE);
+ }
+ } else {
+ DISABLE_FLIGHT_MODE(CHIRP_MODE);
+ }
+#endif
+
if (FLIGHT_MODE(ANGLE_MODE | ALT_HOLD_MODE | POS_HOLD_MODE | HORIZON_MODE)) {
LED1_ON;
// increase frequency of attitude task to reduce drift when in angle or horizon mode
diff --git a/src/main/fc/parameter_names.h b/src/main/fc/parameter_names.h
index 43624e06ea..e677b6fe26 100644
--- a/src/main/fc/parameter_names.h
+++ b/src/main/fc/parameter_names.h
@@ -192,6 +192,15 @@
#define PARAM_NAME_HORIZON_IGNORE_STICKS "horizon_ignore_sticks"
#define PARAM_NAME_HORIZON_DELAY_MS "horizon_delay_ms"
+#define PARAM_NAME_CHIRP_LAG_FREQ_HZ "chirp_lag_freq_hz"
+#define PARAM_NAME_CHIRP_LEAD_FREQ_HZ "chirp_lead_freq_hz"
+#define PARAM_NAME_CHIRP_AMPLITUDE_ROLL "chirp_amplitude_roll"
+#define PARAM_NAME_CHIRP_AMPLITUDE_PITCH "chirp_amplitude_pitch"
+#define PARAM_NAME_CHIRP_AMPLITUDE_YAW "chirp_amplitude_yaw"
+#define PARAM_NAME_CHIRP_FREQUENCY_START_DECI_HZ "chirp_frequency_start_deci_hz"
+#define PARAM_NAME_CHIRP_FREQUENCY_END_DECI_HZ "chirp_frequency_end_deci_hz"
+#define PARAM_NAME_CHIRP_TIME_SECONDS "chirp_time_seconds"
+
#ifdef USE_GPS
#define PARAM_NAME_GPS_PROVIDER "gps_provider"
#define PARAM_NAME_GPS_SBAS_MODE "gps_sbas_mode"
diff --git a/src/main/fc/rc_modes.h b/src/main/fc/rc_modes.h
index 04bd4f2f3a..13838c1c23 100644
--- a/src/main/fc/rc_modes.h
+++ b/src/main/fc/rc_modes.h
@@ -35,6 +35,7 @@ typedef enum {
BOXMAG,
BOXALTHOLD,
BOXHEADFREE,
+ BOXCHIRP,
BOXPASSTHRU,
BOXFAILSAFE,
BOXPOSHOLD,
diff --git a/src/main/fc/runtime_config.h b/src/main/fc/runtime_config.h
index 9d3512ca41..a1df79b426 100644
--- a/src/main/fc/runtime_config.h
+++ b/src/main/fc/runtime_config.h
@@ -87,7 +87,7 @@ typedef enum {
// GPS_HOME_MODE = (1 << 4),
POS_HOLD_MODE = (1 << 5),
HEADFREE_MODE = (1 << 6),
-// UNUSED_MODE = (1 << 7), // old autotune
+ CHIRP_MODE = (1 << 7), // old autotune
PASSTHRU_MODE = (1 << 8),
// RANGEFINDER_MODE= (1 << 9),
FAILSAFE_MODE = (1 << 10),
@@ -109,6 +109,7 @@ extern uint16_t flightModeFlags;
[BOXALTHOLD] = LOG2(ALT_HOLD_MODE), \
[BOXPOSHOLD] = LOG2(POS_HOLD_MODE), \
[BOXHEADFREE] = LOG2(HEADFREE_MODE), \
+ [BOXCHIRP] = LOG2(CHIRP_MODE), \
[BOXPASSTHRU] = LOG2(PASSTHRU_MODE), \
[BOXFAILSAFE] = LOG2(FAILSAFE_MODE), \
[BOXGPSRESCUE] = LOG2(GPS_RESCUE_MODE), \
diff --git a/src/main/flight/pid.c b/src/main/flight/pid.c
index b0fa8fc43b..071c1feaf2 100644
--- a/src/main/flight/pid.c
+++ b/src/main/flight/pid.c
@@ -260,6 +260,14 @@ void resetPidProfile(pidProfile_t *pidProfile)
.tpa_speed_pitch_offset = 0,
.yaw_type = YAW_TYPE_RUDDER,
.angle_pitch_offset = 0,
+ .chirp_lag_freq_hz = 3,
+ .chirp_lead_freq_hz = 30,
+ .chirp_amplitude_roll = 230,
+ .chirp_amplitude_pitch = 230,
+ .chirp_amplitude_yaw = 180,
+ .chirp_frequency_start_deci_hz = 2,
+ .chirp_frequency_end_deci_hz = 6000,
+ .chirp_time_seconds = 20,
);
}
@@ -1200,9 +1208,49 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
disarmOnImpact();
}
+#ifdef USE_CHIRP
+
+ static int chirpAxis = 0;
+ static bool shouldChirpAxisToggle = false;
+
+ float chirp = 0.0f;
+ float sinarg = 0.0f;
+ if (FLIGHT_MODE(CHIRP_MODE)) {
+ shouldChirpAxisToggle = true; // advance chirp axis on next !CHIRP_MODE
+ // update chirp signal
+ if (chirpUpdate(&pidRuntime.chirp)) {
+ chirp = pidRuntime.chirp.exc;
+ sinarg = pidRuntime.chirp.sinarg;
+ }
+ } else {
+ if (shouldChirpAxisToggle) {
+ // toggle chirp signal logic and increment to next axis for next run
+ shouldChirpAxisToggle = false;
+ chirpAxis = (++chirpAxis > FD_YAW) ? 0 : chirpAxis;
+ // reset chirp signal generator
+ chirpReset(&pidRuntime.chirp);
+ }
+ }
+
+ // input / excitation shaping
+ float chirpFiltered = phaseCompApply(&pidRuntime.chirpFilter, chirp);
+
+ // ToDo: check if this can be reconstructed offline for rotating filter and if so, remove the debug
+ // fit (0...2*pi) into int16_t (-32768 to 32767)
+ DEBUG_SET(DEBUG_CHIRP, 0, lrintf(5.0e3f * sinarg));
+
+#endif // USE_CHIRP
+
// ----------PID controller----------
for (int axis = FD_ROLL; axis <= FD_YAW; ++axis) {
+#ifdef USE_CHIRP
+ float currentChirp = 0.0f;
+ if(axis == chirpAxis){
+ currentChirp = pidRuntime.chirpAmplitude[axis] * chirpFiltered;
+ }
+#endif // USE_CHIRP
+
float currentPidSetpoint = getSetpointRate(axis);
if (pidRuntime.maxVelocity[axis]) {
currentPidSetpoint = accelerationLimit(axis, currentPidSetpoint);
@@ -1263,6 +1311,9 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
// -----calculate error rate
const float gyroRate = gyro.gyroADCf[axis]; // Process variable from gyro output in deg/sec
+#ifdef USE_CHIRP
+ currentPidSetpoint += currentChirp;
+#endif // USE_CHIRP
float errorRate = currentPidSetpoint - gyroRate; // r - y
#if defined(USE_ACC)
handleCrashRecovery(
@@ -1596,3 +1647,10 @@ float pidGetPidFrequency(void)
{
return pidRuntime.pidFrequency;
}
+
+#ifdef USE_CHIRP
+bool pidChirpIsFinished(void)
+{
+ return pidRuntime.chirp.isFinished;
+}
+#endif
diff --git a/src/main/flight/pid.h b/src/main/flight/pid.h
index f1d077bf6b..8c217dd03c 100644
--- a/src/main/flight/pid.h
+++ b/src/main/flight/pid.h
@@ -23,6 +23,7 @@
#include
#include "common/axis.h"
+#include "common/chirp.h"
#include "common/filter.h"
#include "common/pwl.h"
#include "common/time.h"
@@ -322,6 +323,15 @@ typedef struct pidProfile_s {
int16_t tpa_speed_pitch_offset; // For wings: pitch offset in degrees*10 for craft speed estimation
uint8_t yaw_type; // For wings: type of yaw (rudder or differential thrust)
int16_t angle_pitch_offset; // For wings: pitch offset for angle modes; in decidegrees; positive values tilting the wing down
+
+ uint8_t chirp_lag_freq_hz; // leadlag1Filter cutoff/pole to shape the excitation signal
+ uint8_t chirp_lead_freq_hz; // leadlag1Filter cutoff/zero
+ uint16_t chirp_amplitude_roll; // amplitude roll in degree/second
+ uint16_t chirp_amplitude_pitch; // amplitude pitch in degree/second
+ uint16_t chirp_amplitude_yaw; // amplitude yaw in degree/second
+ uint16_t chirp_frequency_start_deci_hz; // start frequency in units of 0.1 hz
+ uint16_t chirp_frequency_end_deci_hz; // end frequency in units of 0.1 hz
+ uint8_t chirp_time_seconds; // excitation time
} pidProfile_t;
PG_DECLARE_ARRAY(pidProfile_t, PID_PROFILE_COUNT, pidProfiles);
@@ -529,6 +539,17 @@ typedef struct pidRuntime_s {
float tpaCurvePwl_yValues[TPA_CURVE_PWL_SIZE];
tpaCurveType_t tpaCurveType;
#endif // USE_ADVANCED_TPA
+
+#ifdef USE_CHIRP
+ chirp_t chirp;
+ phaseComp_t chirpFilter;
+ float chirpLagFreqHz;
+ float chirpLeadFreqHz;
+ float chirpAmplitude[3];
+ float chirpFrequencyStartHz;
+ float chirpFrequencyEndHz;
+ float chirpTimeSeconds;
+#endif // USE_CHIRP
} pidRuntime_t;
extern pidRuntime_t pidRuntime;
@@ -585,3 +606,6 @@ float pidGetDT();
float pidGetPidFrequency();
float dynLpfCutoffFreq(float throttle, uint16_t dynLpfMin, uint16_t dynLpfMax, uint8_t expo);
+#ifdef USE_CHIRP
+bool pidChirpIsFinished();
+#endif
diff --git a/src/main/flight/pid_init.c b/src/main/flight/pid_init.c
index e8ab4ab91f..d8dc0484a2 100644
--- a/src/main/flight/pid_init.c
+++ b/src/main/flight/pid_init.c
@@ -317,6 +317,14 @@ void pidInitFilters(const pidProfile_t *pidProfile)
pidRuntime.angleYawSetpoint = 0.0f;
#endif
+#ifdef USE_CHIRP
+ const float alpha = pidRuntime.chirpLeadFreqHz / pidRuntime.chirpLagFreqHz;
+ const float centerFreqHz = pidRuntime.chirpLagFreqHz * sqrtf(alpha);
+ const float centerPhaseDeg = asinf( (1.0f - alpha) / (1.0f + alpha) ) / RAD;
+ phaseCompInit(&pidRuntime.chirpFilter, centerFreqHz, centerPhaseDeg, targetPidLooptime);
+ chirpInit(&pidRuntime.chirp, pidRuntime.chirpFrequencyStartHz, pidRuntime.chirpFrequencyEndHz, pidRuntime.chirpTimeSeconds, targetPidLooptime);
+#endif
+
pt2FilterInit(&pidRuntime.antiGravityLpf, pt2FilterGain(pidProfile->anti_gravity_cutoff_hz, pidRuntime.dT));
#ifdef USE_WING
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
@@ -411,6 +419,17 @@ void pidInitConfig(const pidProfile_t *pidProfile)
pidRuntime.horizonDelayMs = pidProfile->horizon_delay_ms;
#endif
+#ifdef USE_CHIRP
+ pidRuntime.chirpLagFreqHz = pidProfile->chirp_lag_freq_hz;
+ pidRuntime.chirpLeadFreqHz = pidProfile->chirp_lead_freq_hz;
+ pidRuntime.chirpAmplitude[FD_ROLL] = pidProfile->chirp_amplitude_roll;
+ pidRuntime.chirpAmplitude[FD_PITCH] = pidProfile->chirp_amplitude_pitch;
+ pidRuntime.chirpAmplitude[FD_YAW]= pidProfile->chirp_amplitude_yaw;
+ pidRuntime.chirpFrequencyStartHz = pidProfile->chirp_frequency_start_deci_hz / 10.0f;
+ pidRuntime.chirpFrequencyEndHz = pidProfile->chirp_frequency_end_deci_hz / 10.0f;
+ pidRuntime.chirpTimeSeconds = pidProfile->chirp_time_seconds;
+#endif
+
pidRuntime.maxVelocity[FD_ROLL] = pidRuntime.maxVelocity[FD_PITCH] = pidProfile->rateAccelLimit * 100 * pidRuntime.dT;
pidRuntime.maxVelocity[FD_YAW] = pidProfile->yawRateAccelLimit * 100 * pidRuntime.dT;
pidRuntime.antiGravityGain = pidProfile->anti_gravity_gain;
diff --git a/src/main/msp/msp_box.c b/src/main/msp/msp_box.c
index 7477a5337d..e816db02d9 100644
--- a/src/main/msp/msp_box.c
+++ b/src/main/msp/msp_box.c
@@ -101,6 +101,7 @@ static const box_t boxes[CHECKBOX_ITEM_COUNT] = {
{ .boxId = BOXBEEPERMUTE, .boxName = "BEEPER MUTE", .permanentId = 52},
{ .boxId = BOXREADY, .boxName = "READY", .permanentId = 53},
{ .boxId = BOXLAPTIMERRESET, .boxName = "LAP TIMER RESET", .permanentId = 54},
+ { .boxId = BOXCHIRP, .boxName = "CHIRP", .permanentId = 55}
};
// mask of enabled IDs, calculated on startup based on enabled features. boxId_e is used as bit index
@@ -365,6 +366,10 @@ void initActiveBoxIds(void)
BME(BOXLAPTIMERRESET);
#endif
+#if defined(USE_CHIRP)
+ BME(BOXCHIRP);
+#endif
+
#undef BME
// check that all enabled IDs are in boxes array (check may be skipped when using findBoxById() functions)
for (boxId_e boxId = 0; boxId < CHECKBOX_ITEM_COUNT; boxId++)
diff --git a/src/main/osd/osd_elements.c b/src/main/osd/osd_elements.c
index 1edd59843b..43855697a1 100644
--- a/src/main/osd/osd_elements.c
+++ b/src/main/osd/osd_elements.c
@@ -1084,6 +1084,11 @@ static void osdElementFlymode(osdElementParms_t *element)
strcpy(element->buff, "HOR ");
} else if (IS_RC_MODE_ACTIVE(BOXACROTRAINER)) {
strcpy(element->buff, "ATRN");
+#ifdef USE_CHIRP
+ // the additional check for pidChirpIsFinished() is to have visual feedback for user that don't have warnings enabled in their googles
+ } else if (FLIGHT_MODE(CHIRP_MODE) && !pidChirpIsFinished()) {
+#endif
+ strcpy(element->buff, "CHIR");
} else if (isAirmodeEnabled()) {
strcpy(element->buff, "AIR ");
} else {
diff --git a/src/main/osd/osd_warnings.c b/src/main/osd/osd_warnings.c
index bf6b8e1c07..3c983946b0 100644
--- a/src/main/osd/osd_warnings.c
+++ b/src/main/osd/osd_warnings.c
@@ -432,6 +432,16 @@ void renderOsdWarning(char *warningText, bool *blinking, uint8_t *displayAttr)
return;
}
+#ifdef USE_CHIRP
+ // Visual info that chirp excitation is finished
+ if (pidChirpIsFinished()) {
+ tfp_sprintf(warningText, "CHIRP EXC FINISHED");
+ *displayAttr = DISPLAYPORT_SEVERITY_INFO;
+ *blinking = true;
+ return;
+ }
+#endif // USE_CHIRP
+
}
#endif // USE_OSD
diff --git a/src/main/telemetry/crsf.c b/src/main/telemetry/crsf.c
index 68d654831b..48140efae8 100644
--- a/src/main/telemetry/crsf.c
+++ b/src/main/telemetry/crsf.c
@@ -463,6 +463,8 @@ void crsfFrameFlightMode(sbuf_t *dst)
flightMode = "ALTH";
} else if (FLIGHT_MODE(HORIZON_MODE)) {
flightMode = "HOR";
+ } else if (FLIGHT_MODE(CHIRP_MODE)) {
+ flightMode = "CHIR";
} else if (isAirmodeEnabled()) {
flightMode = "AIR";
}