ACwing FC firmware
STM32WB55: attitude IEKF, altitude Kalman filter, flight core, protocol v2
Loading...
Searching...
No Matches
app_config.h
Go to the documentation of this file.
1
7#ifndef APP_CONFIG_H
8#define APP_CONFIG_H
9
10#define DEG2RAD_F 0.017453292519943295f
11
12/* ---------------- IMU ---------------- */
13/* Bring-up: 960 Hz with I2C at 400 kHz. 1920 Hz requires Fast-mode Plus (1 MHz);
14 * try it only after checking the bus edges with an oscilloscope: the IKS4A1 has
15 * level translators and 4k7 pull-ups. The pipeline adapts automatically. */
16#define APP_IMU_ODR IMU_ODR_960HZ
17#define APP_IMU_WATERMARK 4u
18#define APP_GY_LPF1_BW LSM6DSV16X_GY_LIGHT
19#define APP_XL_LPF2_ENABLE 1
20#define APP_XL_LPF2_BW LSM6DSV16X_XL_STRONG
21#define APP_MAG_FAST 1
22/* ---------------- rates (derived) ---------------- */
23#define APP_STEP_HZ 960u
24#define APP_STEPS_PER_ACC 4u
25/* ---------------- static calibration ---------------- */
26#define APP_CALIB_SAMPLES 100u
27#define APP_CALIB_GYRO_STILL (5.0f * DEG2RAD_F)
28
29/* ---------------- IEKF ----------------
30 * State: attitude (3) + gyro bias (3). IEKF_ESTIMATE_BIAS = 0 -> 3 states.
31 * sigma_gyro is the EFFECTIVE gyro process noise (Q = sigma^2 * dt).
32 * It must cover not only the sensor noise (~0.003 deg/s/rtHz from the datasheet)
33 * but also what the model ignores: scale-factor error, misalignment,
34 * acceleration sensitivity. In simulation with 1% scale error and 1 deg of
35 * misalignment: sigma 0.1 -> RMSE 1.17 deg, sigma 0.5 -> 0.42 deg.
36 * Hence 0.5: it can be lowered only after calibrating gyro scale and
37 * misalignment (see 03 - Docs/theory/iekf-embedded.md). */
38#define IEKF_SIGMA_GYRO (0.5f * DEG2RAD_F)
39#define IEKF_SIGMA_BIAS 1e-4f
40#define IEKF_SIGMA_VEC_MIN 0.01f
41#define IEKF_ACC_TOL 0.08f
42#define IEKF_MAG_TOL 0.08f
43#define IEKF_P0_ATT ((2.0f * DEG2RAD_F) * (2.0f * DEG2RAD_F))
44#define IEKF_P0_BIAS ((0.2f * DEG2RAD_F) * (0.2f * DEG2RAD_F))
45#define IEKF_ESTIMATE_BIAS 1
46#define IEKF_ADAPTIVE 1
47#define IEKF_TILT_COMP_MAG 1
48
49/* ---------------- robustness (external accelerations / magnetic disturbances) ----
50 * Accelerometer: R inflated by NIS/gate when the innovation is inconsistent with
51 * the covariance (this also catches accelerations PERPENDICULAR to gravity, which
52 * the magnitude check barely sees), with a memory of IEKF_INFL_TAU_S.
53 * Magnetometer: de-weighted when the measured field-gravity angle departs from
54 * the calibration value (independent of the estimate: it does not slow down yaw
55 * recovery).
56 * Stillness detector: board at rest -> the accelerometer is trusted again at once. */
57#define IEKF_ACC_NIS_GATE 4.0f
58#define IEKF_MAG_NIS_GATE 0.0f
59#define IEKF_INFL_TAU_S 0.5f
60#define IEKF_DIP_TOL (5.0f * DEG2RAD_F)
61#define IEKF_DECOUPLE 0
62/* "Lockout" protection: without it, a true attitude error during motion inflates
63 * R_acc forever (recovery > 20 s). The inflation is capped and, if the innovation
64 * is persistent in the world frame (a true error, not shaking), after
65 * IEKF_LOCKOUT_S the covariance is reopened and the accelerometer trusted again. */
66#define IEKF_RESET_JACOBIAN 1
67/* Tangential vector innovation: the radial part of y - yhat (along yhat) is
68 * dropped, it is outside the range of H and only inflated the NIS of large
69 * errors (see 03 - Docs/theory/iekf-embedded.md, "Tangential innovation"). */
70#define IEKF_TANGENT_INNOV 1
71#define IEKF_INFL_MAX 100.0f
72#define IEKF_LOCKOUT_S 0.5f
73#define IEKF_LOCKOUT_BUMP ((10.0f * DEG2RAD_F) * (10.0f * DEG2RAD_F))
74#define IEKF_GRACE_S 0.25f
75#define IEKF_PERSIST_TAU_S 1.0f
76#define IEKF_PERSIST_RATIO 0.6f
77#define IEKF_PERSIST_MIN 0.02f
78
79/* ---------------- diagnostic comparison profile ----------------
80 * 1 = filter as in the earlier "works better" version: no inflation cap,
81 * no lockout protection, no error reset. */
82#define APP_PROFILE_PREVIOUS 0
83#if APP_PROFILE_PREVIOUS
84#undef IEKF_RESET_JACOBIAN
85#define IEKF_RESET_JACOBIAN 0
86#undef IEKF_INFL_MAX
87#define IEKF_INFL_MAX 1e4f
88#undef IEKF_LOCKOUT_S
89#define IEKF_LOCKOUT_S 0.0f
90#endif
91#define APP_STILL_ACC_TOL 0.02f
92#define APP_STILL_GYRO_THR (3.0f * DEG2RAD_F)
93#define APP_STILL_TIME_S 0.3f
94
95/* ---------------- comparison with the original MATLAB filter ----------------
96 * 1 = disables the extensions that the original iekfAttitude.m does not have
97 * (NIS inflation, dip check, stillness detector, variance due to the age of
98 * the mag sample, error reset). The embedded filter must then match the
99 * original up to float32 precision: this proves that the C code implements
100 * the equations validated in MATLAB.
101 * 0 = full configuration: the comparison quantifies the effect of the extensions. */
102#define APP_COMPARE_ORIGINAL 0
103
104/* ---------------- magnetometer -> body (LSM6DSV16X frame) ----------------
105 * Calibration of 2026-10-07 (calibMagAxes.m on the board): LIS2MDL axes rotated
106 * by 180 deg about x w.r.t. the LSM6DSV16X (y and z flipped).
107 * Large hard-iron (~194 uT, ~4x the Earth field): recalibrate whenever anything
108 * near the sensor changes (cables, battery, screws, motors). */
109#define MAG_AXIS_MAP { 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f }
110#define MAG_HARD_IRON { 31.61f, 16.44f, -26.23f }
111/* ---------------- telemetry (phase 1: ST-LINK virtual COM port) ---------------- */
112#define APP_TLM_DECIMATION 1u
113#define APP_TLM_DECIM_REPLAY 8u /* with REPLAY on, STATE drops to 30 Hz:
114 REPLAY already carries q and bias at 240 Hz */
115#define APP_TLM_TX_TIMEOUT_MS 20u
116#define APP_INIT_EVERY_N 480u
117#define APP_TLM_REPLAY 0 /* 1 only for the MATLAB comparison: raises the
118 telemetry from ~19 to ~44 kB/s, too much for
119 the real-time viewer -> record with
120 tlmCapture.m and analyse offline */
122/* ---------------- telemetry over BLE (phase 2, see 03 - Docs/firmware/ble.md) ----------------
123 * Same frames as the UART, as a byte stream on a GATT notification. The UART
124 * keeps working unchanged (REPLAY and comparison stay USB-only). */
125#define APP_TLM_BLE 1 /* 1 once STM32_WPAN (BLE) is enabled in CubeMX
126 and the CPU2 wireless stack is flashed */
127#define APP_BLE_STATE_DECIM 4u /* STATE over BLE: 240/4 = 60 Hz (~5.4 kB/s in
128 total with STATUS and INIT). Changeable at run
129 time with the CMD characteristic. */
130#define APP_BLE_FLUSH_MS 10u /* TX thread period: groups frames in one
131 notification when the MTU allows it */
132#define APP_BLE_CONN_INT_MIN 12u
133#define APP_BLE_CONN_INT_MAX 24u
134#define APP_BLE_SUPERV_TIMEOUT 400u
135/* ---------------- ACwing Pilot protocol v2 ---------------- */
136#define APP_HW_REV 'N'
137/* ACwing Flow: PMW3901 counts -> body axes (frame C2: board t forward, s left).
138 * To be confirmed on the first build (FLOW_TOF calibration, "match"). */
139#define APP_FLOW_SIGN_X (1.0f)
140#define APP_FLOW_SIGN_Y (1.0f)
141/* PMW3901 minimum working distance (datasheet: 80 mm). Landed, the lens is
142 * ~11 mm above the floor (frame C2): below this height the flow is not used
143 * (no velocity, no POS_HOLD, no FLOW_LOST failsafe); usable again 20 mm above. */
144#define APP_FLOW_MIN_H 0.08f
145
146/* ---------------- battery (BattTask) ---------------- */
147/* ADC1 injected group, VBAT + CUR + VREFINT, 16x oversampling.
148 * ACwing FC rev A: PA5 = VBAT_SNS (ADC1_IN10, 100k/10k), PA4 = ESC_CUR (ADC1_IN9).
149 * Bench (NUCLEO-WB55): off by default -- nothing is wired. To try it, wire a
150 * 100k/10k divider from a bench supply to A0 (PC0, ADC1_IN1) and optionally a
151 * voltage for the current to A1 (PC1, ADC1_IN2), then set APP_BATT_ADC 1. */
152#if APP_HW_REV == 'A'
153#define APP_BATT_ADC 1
154#define APP_BATT_VBAT_CH 10u
155#define APP_BATT_VBAT_PORT GPIOA
156#define APP_BATT_VBAT_PIN (1u << 5)
157#define APP_BATT_CUR_CH 9u
158#define APP_BATT_CUR_PORT GPIOA
159#define APP_BATT_CUR_PIN (1u << 4)
160#else
161#define APP_BATT_ADC 0
162#define APP_BATT_VBAT_CH 1u
163#define APP_BATT_VBAT_PORT GPIOC
164#define APP_BATT_VBAT_PIN (1u << 0)
165#define APP_BATT_CUR_CH 2u
166#define APP_BATT_CUR_PORT GPIOC
167#define APP_BATT_CUR_PIN (1u << 1)
168#endif
169#define APP_BATT_CURRENT 1
170#define APP_BATT_SENS_V_A 0.1f
172/* ---------------- flight log (LogTask) ---------------- */
173/* 0 none, 1 RAM (bench: the log is lost at power-off), 2 W25Q128JV on SPI1 (rev A) */
174#if APP_HW_REV == 'A'
175#define APP_LOG_FLASH 2
176#else
177#define APP_LOG_FLASH 1
178#endif
179#define APP_LOG_RAM_KB 48u
181/* ---------------- USB device (CDC: ground link, ADR 0009) ---------------- */
182#define APP_USB_CDC 1
183/* The USB link carries the flight log, parameters, calibrations and telemetry,
184 * never flight commands; ARM, TAKEOFF and MOTOR_TEST are refused while a USB
185 * host is connected. With a program on the port it also gets the PC telemetry
186 * (STATE, INIT, STATUS, and REPLAY when enabled) that the UART carries: on the
187 * ACwing FC there is no ST-LINK virtual COM port. */
188#define APP_USB_TLM 1
189
190#endif /* APP_CONFIG_H */