Skip to content

Commit 3bb08ee

Browse files
committed
feat(aoa): optimize canard intervention logic and add MSP over CRSF telemetry
1 parent 0ecb78e commit 3bb08ee

4 files changed

Lines changed: 80 additions & 13 deletions

File tree

src/main/flight/pid.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ static void NOINLINE pidApplyFixedWingRateController(pidState_t *pidState, float
873873

874874
#ifdef USE_AOA
875875
if (pidState->axis == FD_PITCH) {
876-
aoaControlUpdate(axisPID[FD_PITCH], rateError, newPTerm, newDTerm, newFFTerm, pidState->errorGyroIf, limit);
876+
aoaControlUpdate(&axisPID[FD_PITCH], rateError, newPTerm, newDTerm, newFFTerm, pidState->errorGyroIf, limit);
877877
}
878878
#endif
879879

src/main/sensors/aoa.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ bool aoaControlEnable(int8_t input_rc_channel)
186186
return rcValue > 1666;
187187
}
188188

189-
void aoaControlUpdate(float pidPitchOutput, float rateError, float newPTerm, float newDTerm, float newFFTerm, float errorGyroIf, float limit)
189+
void aoaControlUpdate(float *pidPitchOutput, float rateError, float newPTerm, float newDTerm, float newFFTerm, float errorGyroIf, float limit)
190190
{
191191
isAoaControlEnabled = aoaControlEnable(aoaControlConfig()->fw_aoa_control_channel);
192192

@@ -202,22 +202,37 @@ void aoaControlUpdate(float pidPitchOutput, float rateError, float newPTerm, flo
202202
float aoaServoOffset = 0.0f;
203203

204204
if (aoaControlConfig()->fw_aoa_aircraft_type == AIRCRAFT_CANARD) {
205-
// Canard layout: always intervene with servo offset
205+
206+
const float thresholdRatio = aoaControlConfig()->fw_aoa_intervention_threshold * 0.01f;
207+
const int16_t upperThreshold = upperLimitAngle * thresholdRatio;
208+
const int16_t lowerThreshold = lowerLimitAngle * thresholdRatio;
209+
const int16_t aoaDeg = DECIDEGREES_TO_DEGREES(filteredAoa);
210+
206211
const int16_t lowerLimit = lowerLimitAngle * deg2pwm;
207212
const int16_t upperLimit = upperLimitAngle * deg2pwm;
213+
float constrainedPidOutput = constrainf(*pidPitchOutput, -upperLimit, -lowerLimit);
208214

209-
float pidOutput = pidPitchOutput * kp;
210-
float constrainedPidOutput = constrainf(pidOutput, -upperLimit, -lowerLimit);
215+
float aoaError = 0.0f;
216+
if (aoaDeg > upperThreshold) {
217+
aoaError = aoaDeg - upperThreshold;
218+
} else if (aoaDeg < lowerThreshold) {
219+
aoaError = aoaDeg - lowerThreshold;
220+
}
211221

222+
float interventionOffset = aoaError * kp * deg2pwm;
212223
aoaServoOffset = (DECIDEGREES_TO_DEGREES(filteredAoa) - aoaControlConfig()->fw_aoa_trim_angle) * deg2pwm;
213-
214-
aoaPidOutput = isAoaControlEnabled ? constrainedPidOutput + aoaServoOffset : constrainedPidOutput;
224+
aoaPidOutput = isAoaControlEnabled ? constrainedPidOutput + aoaServoOffset : constrainedPidOutput;
215225
aoaPidOutput = constrainf(aoaPidOutput, -limit, +limit);
216226

217-
DEBUG_SET(DEBUG_AOA, 1, pidOutput);
218-
DEBUG_SET(DEBUG_AOA, 2, pidPitchOutput);
227+
if (isAoaControlEnabled && aoaError != 0.0f) {
228+
*pidPitchOutput += interventionOffset;
229+
*pidPitchOutput = constrainf(*pidPitchOutput, -limit, +limit);
230+
}
231+
232+
DEBUG_SET(DEBUG_AOA, 1, aoaError);
233+
DEBUG_SET(DEBUG_AOA, 2, *pidPitchOutput);
219234
DEBUG_SET(DEBUG_AOA, 3, aoaControlConfig()->fw_aoa_kp);
220-
DEBUG_SET(DEBUG_AOA, 4, constrainedPidOutput);
235+
DEBUG_SET(DEBUG_AOA, 4, interventionOffset);
221236
DEBUG_SET(DEBUG_AOA, 5, aoaServoOffset);
222237
DEBUG_SET(DEBUG_AOA, 6, aoaPidOutput);
223238
DEBUG_SET(DEBUG_AOA, 7, rateError);
@@ -237,11 +252,11 @@ void aoaControlUpdate(float pidPitchOutput, float rateError, float newPTerm, flo
237252

238253
aoaServoOffset = aoaError * kp * deg2pwm;
239254

240-
aoaPidOutput = isAoaControlEnabled ? pidPitchOutput + aoaServoOffset : pidPitchOutput;
255+
aoaPidOutput = isAoaControlEnabled ? *pidPitchOutput + aoaServoOffset : *pidPitchOutput;
241256
aoaPidOutput = constrainf(aoaPidOutput, -limit, +limit);
242257

243258
DEBUG_SET(DEBUG_AOA, 1, aoaError);
244-
DEBUG_SET(DEBUG_AOA, 2, pidPitchOutput);
259+
DEBUG_SET(DEBUG_AOA, 2, *pidPitchOutput);
245260
DEBUG_SET(DEBUG_AOA, 3, aoaControlConfig()->fw_aoa_kp);
246261
DEBUG_SET(DEBUG_AOA, 4, aoaServoOffset);
247262
DEBUG_SET(DEBUG_AOA, 5, aoaServoOffset);

src/main/sensors/aoa.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,4 @@ timeDelta_t aoaUpdate(void);
8282
bool aoaProcess(void);
8383
bool aoaIsHealthy(void);
8484
bool aoaControlEnable(int8_t input_rc_channel);
85-
void aoaControlUpdate(float pidPitchOutput, float rateError, float newPTerm, float newDTerm, float newFFTerm, float errorGyroIf, float limit);
85+
void aoaControlUpdate(float *pidPitchOutput, float rateError, float newPTerm, float newDTerm, float newFFTerm, float errorGyroIf, float limit);

src/main/telemetry/crsf.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757

5858
#include "sensors/battery.h"
5959
#include "sensors/sensors.h"
60+
#include "sensors/aoa.h"
6061

6162
#include "telemetry/crsf.h"
6263
#include "telemetry/telemetry.h"
@@ -434,6 +435,37 @@ uint32_t Null Bytes
434435
uint8_t 255 (Max MSP Parameter)
435436
uint8_t 0x01 (Parameter version 1)
436437
*/
438+
#ifdef USE_AOA
439+
#define CRSF_AOA_MSP_SEQ_INCREMENT 1
440+
441+
static void crsfFrameAoaMsp(sbuf_t *dst)
442+
{
443+
int16_t aoa = 0;
444+
int16_t unused = 0;
445+
aoaGetLatestData(&aoa, &unused);
446+
447+
static uint8_t aoaMspSeq = 0;
448+
449+
uint8_t mspPayload[8];
450+
mspPayload[0] = 0x50 | (aoaMspSeq & 0x0F);
451+
mspPayload[1] = 0x00;
452+
mspPayload[2] = 0x08;
453+
mspPayload[3] = 0x1F;
454+
mspPayload[4] = 0x02;
455+
mspPayload[5] = 0x00;
456+
mspPayload[6] = (uint8_t)(aoa & 0xFF);
457+
mspPayload[7] = (uint8_t)((aoa >> 8) & 0xFF);
458+
459+
aoaMspSeq += CRSF_AOA_MSP_SEQ_INCREMENT;
460+
461+
sbufWriteU8(dst, sizeof(mspPayload) + CRSF_FRAME_LENGTH_EXT_TYPE_CRC);
462+
crsfSerialize8(dst, CRSF_FRAMETYPE_MSP_RESP);
463+
crsfSerialize8(dst, CRSF_ADDRESS_RADIO_TRANSMITTER);
464+
crsfSerialize8(dst, CRSF_ADDRESS_FLIGHT_CONTROLLER);
465+
crsfSerializeData(dst, mspPayload, sizeof(mspPayload));
466+
}
467+
#endif
468+
437469
static void crsfFrameDeviceInfo(sbuf_t *dst)
438470
{
439471
char buff[30];
@@ -465,6 +497,9 @@ typedef enum {
465497
CRSF_FRAME_GPS_INDEX,
466498
CRSF_FRAME_VARIO_SENSOR_INDEX,
467499
CRSF_FRAME_BAROMETER_ALTITUDE_INDEX,
500+
#ifdef USE_AOA
501+
CRSF_FRAME_AOA_INDEX,
502+
#endif
468503
CRSF_SCHEDULE_COUNT_MAX
469504
} crsfFrameTypeIndex_e;
470505

@@ -544,6 +579,13 @@ static void processCrsf(void)
544579
crsfBarometerAltitude(dst);
545580
crsfFinalize(dst);
546581
}
582+
#endif
583+
#ifdef USE_AOA
584+
if (currentSchedule & BV(CRSF_FRAME_AOA_INDEX)) {
585+
crsfInitializeFrame(dst);
586+
crsfFrameAoaMsp(dst);
587+
crsfFinalize(dst);
588+
}
547589
#endif
548590
crsfScheduleIndex = (crsfScheduleIndex + 1) % crsfScheduleCount;
549591
}
@@ -582,6 +624,11 @@ void initCrsfTelemetry(void)
582624
if (sensors(SENSOR_BARO)) {
583625
crsfSchedule[index++] = BV(CRSF_FRAME_BAROMETER_ALTITUDE_INDEX);
584626
}
627+
#endif
628+
#ifdef USE_AOA
629+
if (sensors(SENSOR_AOA)) {
630+
crsfSchedule[index++] = BV(CRSF_FRAME_AOA_INDEX);
631+
}
585632
#endif
586633
crsfScheduleCount = (uint8_t)index;
587634
}
@@ -659,6 +706,11 @@ int getCrsfFrame(uint8_t *frame, crsfFrameType_e frameType)
659706
case CRSF_FRAMETYPE_VARIO_SENSOR:
660707
crsfFrameVarioSensor(sbuf);
661708
break;
709+
#ifdef USE_AOA
710+
case CRSF_FRAMETYPE_MSP_RESP:
711+
crsfFrameAoaMsp(sbuf);
712+
break;
713+
#endif
662714
}
663715
const int frameSize = crsfFinalizeBuf(sbuf, frame);
664716
return frameSize;

0 commit comments

Comments
 (0)