@@ -70,6 +70,11 @@ typedef struct{
70
70
float z1 , z2 ;
71
71
} Biquad ;
72
72
73
+ typedef enum {
74
+ BQ_LOWPASS ,
75
+ BQ_HIGHPASS
76
+ } BiquadType ;
77
+
73
78
// Balance thread
74
79
static THD_FUNCTION (balance_thread , arg ) ;
75
80
static THD_WORKING_AREA (balance_thread_wa , 2048 ) ; // 2kb stack for this thread
@@ -128,12 +133,33 @@ static void app_balance_sample_debug(void);
128
133
static void app_balance_experiment (void );
129
134
130
135
// Utility Functions
131
- float biquad_process (float in , Biquad * biquad ) {
136
+ float biquad_process (Biquad * biquad , float in ) {
132
137
float out = in * biquad -> a0 + biquad -> z1 ;
133
138
biquad -> z1 = in * biquad -> a1 + biquad -> z2 - biquad -> b1 * out ;
134
139
biquad -> z2 = in * biquad -> a2 - biquad -> b2 * out ;
135
140
return out ;
136
141
}
142
+ void biquad_config (Biquad * biquad , BiquadType type , float Fc ) {
143
+ float K = tanf (M_PI * Fc ); // -0.0159;
144
+ float Q = 0.707 ; // maximum sharpness (0.5 = maximum smoothness)
145
+ float norm = 1 / (1 + K / Q + K * K );
146
+ if (type == BQ_LOWPASS ) {
147
+ biquad -> a0 = K * K * norm ;
148
+ biquad -> a1 = 2 * biquad -> a0 ;
149
+ biquad -> a2 = biquad -> a0 ;
150
+ }
151
+ else if (type == BQ_HIGHPASS ) {
152
+ biquad -> a0 = 1 * norm ;
153
+ biquad -> a1 = -2 * biquad -> a0 ;
154
+ biquad -> a2 = biquad -> a0 ;
155
+ }
156
+ biquad -> b1 = 2 * (K * K - 1 ) * norm ;
157
+ biquad -> b2 = (1 - K / Q + K * K ) * norm ;
158
+ }
159
+ void biquad_reset (Biquad * biquad ) {
160
+ biquad -> z1 = 0 ;
161
+ biquad -> z2 = 0 ;
162
+ }
137
163
138
164
// Exposed Functions
139
165
void app_balance_configure (balance_config * conf , imu_config * conf2 ) {
@@ -166,36 +192,15 @@ void app_balance_configure(balance_config *conf, imu_config *conf2) {
166
192
}
167
193
if (balance_conf .kd_biquad_lowpass > 0 ){
168
194
float Fc = balance_conf .kd_biquad_lowpass / balance_conf .hertz ;
169
- float Q = 0.707 ; // Flat response
170
- float K = tan (M_PI * Fc );
171
- float norm = 1 / (1 + K / Q + K * K );
172
- d_biquad_lowpass .a0 = K * K * norm ;
173
- d_biquad_lowpass .a1 = 2 * d_biquad_lowpass .a0 ;
174
- d_biquad_lowpass .a2 = d_biquad_lowpass .a0 ;
175
- d_biquad_lowpass .b1 = 2 * (K * K - 1 ) * norm ;
176
- d_biquad_lowpass .b2 = (1 - K / Q + K * K ) * norm ;
195
+ biquad_config (& d_biquad_lowpass , BQ_LOWPASS , Fc );
177
196
}
178
197
if (balance_conf .kd_biquad_highpass > 0 ){
179
198
float Fc = balance_conf .kd_biquad_highpass / balance_conf .hertz ;
180
- float Q = 0.707 ; // Flat response
181
- float K = tan (M_PI * Fc );
182
- float norm = 1 / (1 + K / Q + K * K );
183
- d_biquad_highpass .a0 = 1 * norm ;
184
- d_biquad_highpass .a1 = -2 * d_biquad_highpass .a0 ;
185
- d_biquad_highpass .a2 = d_biquad_highpass .a0 ;
186
- d_biquad_highpass .b1 = 2 * (K * K - 1 ) * norm ;
187
- d_biquad_highpass .b2 = (1 - K / Q + K * K ) * norm ;
199
+ biquad_config (& d_biquad_highpass , BQ_HIGHPASS , Fc );
188
200
}
189
201
if (balance_conf .torquetilt_filter > 0 ){ // Torquetilt Current Biquad
190
202
float Fc = balance_conf .torquetilt_filter / balance_conf .hertz ;
191
- float Q = 0.707 ; // Flat response
192
- float K = tan (M_PI * Fc );
193
- float norm = 1 / (1 + K / Q + K * K );
194
- torquetilt_current_biquad .a0 = K * K * norm ;
195
- torquetilt_current_biquad .a1 = 2 * torquetilt_current_biquad .a0 ;
196
- torquetilt_current_biquad .a2 = torquetilt_current_biquad .a0 ;
197
- torquetilt_current_biquad .b1 = 2 * (K * K - 1 ) * norm ;
198
- torquetilt_current_biquad .b2 = (1 - K / Q + K * K ) * norm ;
203
+ biquad_config (& torquetilt_current_biquad , BQ_LOWPASS , Fc );
199
204
}
200
205
201
206
// Variable nose angle adjustment / tiltback (setting is per 1000erpm, convert to per erpm)
@@ -283,10 +288,8 @@ static void reset_vars(void){
283
288
yaw_last_proportional = 0 ;
284
289
d_pt1_lowpass_state = 0 ;
285
290
d_pt1_highpass_state = 0 ;
286
- d_biquad_lowpass .z1 = 0 ;
287
- d_biquad_lowpass .z2 = 0 ;
288
- d_biquad_highpass .z1 = 0 ;
289
- d_biquad_highpass .z2 = 0 ;
291
+ biquad_reset (& d_biquad_lowpass );
292
+ biquad_reset (& d_biquad_highpass );
290
293
// Set values for startup
291
294
setpoint = pitch_angle ;
292
295
setpoint_target_interpolated = pitch_angle ;
@@ -295,8 +298,7 @@ static void reset_vars(void){
295
298
torquetilt_target = 0 ;
296
299
torquetilt_interpolated = 0 ;
297
300
torquetilt_filtered_current = 0 ;
298
- torquetilt_current_biquad .z1 = 0 ;
299
- torquetilt_current_biquad .z2 = 0 ;
301
+ biquad_reset (& torquetilt_current_biquad );
300
302
turntilt_target = 0 ;
301
303
turntilt_interpolated = 0 ;
302
304
setpointAdjustmentType = CENTERING ;
@@ -450,7 +452,7 @@ static void apply_noseangling(void){
450
452
static void apply_torquetilt (void ){
451
453
// Filter current (Biquad)
452
454
if (balance_conf .torquetilt_filter > 0 ){
453
- torquetilt_filtered_current = biquad_process (motor_current , & torquetilt_current_biquad );
455
+ torquetilt_filtered_current = biquad_process (& torquetilt_current_biquad , motor_current );
454
456
}else {
455
457
torquetilt_filtered_current = motor_current ;
456
458
}
@@ -701,10 +703,10 @@ static THD_FUNCTION(balance_thread, arg) {
701
703
derivative = derivative - d_pt1_highpass_state ;
702
704
}
703
705
if (balance_conf .kd_biquad_lowpass > 0 ){
704
- derivative = biquad_process (derivative , & d_biquad_lowpass );
706
+ derivative = biquad_process (& d_biquad_lowpass , derivative );
705
707
}
706
708
if (balance_conf .kd_biquad_highpass > 0 ){
707
- derivative = biquad_process (derivative , & d_biquad_highpass );
709
+ derivative = biquad_process (& d_biquad_highpass , derivative );
708
710
}
709
711
710
712
pid_value = (balance_conf .kp * proportional ) + (balance_conf .ki * integral ) + (balance_conf .kd * derivative );
0 commit comments