Skip to content

Commit cfe327b

Browse files
AP_Motors: add ESC RPM as source for Heli governor
* add ESC telemetry as governor RPM source * add filtering and range checking to RPM coming from ESC * improve handling of RPM spikes during spool up (AM32 issue) * clamp RPM to 2x target RPM * add ~160ms delay to calling governor overspeed during spool up * add ~80ms delay to activating governor during spool up
1 parent df3d35f commit cfe327b

2 files changed

Lines changed: 73 additions & 20 deletions

File tree

libraries/AP_Motors/AP_MotorsHeli_RSC.cpp

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ const AP_Param::GroupInfo AP_MotorsHeli_RSC::var_info[] = {
202202

203203
// @Param: GOV_RPM
204204
// @DisplayName: Rotor RPM Setting
205-
// @Description: Main rotor RPM that governor maintains when engaged
205+
// @Description: Main rotor RPM that governor maintains when engaged, when used with H_RSC_GOV_ESC it is motor RPM instead.
206206
// @Range: 800 3500
207207
// @Units: RPM
208208
// @Increment: 10
@@ -224,6 +224,19 @@ const AP_Param::GroupInfo AP_MotorsHeli_RSC::var_info[] = {
224224

225225
// 27 was AROT_IDLE, moved to RSC autorotation sub group
226226

227+
// @Param: GOV_ESC
228+
// @DisplayName: Governor ESC index
229+
// @Description: Selects ESC used by helicopter governor for RPM, add 40 to use raw RPM, add 80 to use filtered RPM, set to -1 to use RPM sensor.
230+
// @Range: -1 101
231+
// @User: Advanced
232+
AP_GROUPINFO("GOV_ESC", 28, AP_MotorsHeli_RSC, _esc_index, -1),
233+
234+
// @Param: GOV_FLT
235+
// @DisplayName: Governor RPM lowpass filter
236+
// @Description: Controls governor RPM filter, used with ESC telemetry as it typically has lower resolution.
237+
// @Range: 0 50
238+
// @User: Advanced
239+
AP_GROUPINFO("GOV_FLT", 29, AP_MotorsHeli_RSC, _gov_filter_freq, 0),
227240
AP_GROUPEND
228241
};
229242

@@ -256,15 +269,41 @@ void AP_MotorsHeli_RSC::output(RotorControlState state)
256269
_rsc_state = state;
257270
// _rotor_RPM available to the RSC output
258271
#if AP_RPM_ENABLED
259-
const AP_RPM *rpm = AP_RPM::get_singleton();
260-
if (rpm != nullptr) {
261-
if (!rpm->get_rpm(0, _rotor_rpm)) {
262-
// No valid RPM data
272+
#ifdef ESC_TELEM_MAX_ESCS
273+
if (_esc_index>=0 && _esc_index<ESC_TELEM_MAX_ESCS)
274+
{
275+
const AP_ESC_Telem *esc_telem = AP_ESC_Telem::get_singleton();
276+
if(esc_telem != nullptr)
277+
{
278+
float new_rotor_rpm=-1;
279+
if (esc_telem->get_rpm(_esc_index, new_rotor_rpm)){
280+
const uint32_t now_us = MAX(1U ,AP_HAL::micros()); // don't allow a value of 0 in, as we use this as a flag
281+
if (_last_rpm_update == 0) {
282+
_rotor_rpm = new_rotor_rpm;
283+
_last_rpm_update = now_us;
284+
} else {
285+
new_rotor_rpm = MIN (new_rotor_rpm, 2 *_governor_rpm); //clamp sensor data to prevent excessively high values from entering the filter
286+
_rotor_rpm += (new_rotor_rpm - _rotor_rpm) * calc_lowpass_alpha_dt(((float)(now_us-_last_rpm_update))/1e6f, _gov_filter_freq);
287+
_last_rpm_update = now_us;
288+
}
289+
} else {
290+
_rotor_rpm = -1;
291+
_last_rpm_update = 0;
292+
}
293+
}
294+
} else
295+
#endif //ESC_TELEM_MAX_ESCS
296+
{
297+
const AP_RPM *rpm = AP_RPM::get_singleton();
298+
if (rpm != nullptr) {
299+
if (!rpm->get_rpm(0, _rotor_rpm)) {
300+
// No valid RPM data
301+
_rotor_rpm = -1;
302+
}
303+
} else {
304+
// No RPM because pointer is null
263305
_rotor_rpm = -1;
264306
}
265-
} else {
266-
// No RPM because pointer is null
267-
_rotor_rpm = -1;
268307
}
269308
#else
270309
_rotor_rpm = -1;
@@ -554,11 +593,13 @@ void AP_MotorsHeli_RSC::autothrottle_run()
554593
// if governor is not engaged and rotor is overspeeding by more than governor range due to
555594
// misconfigured throttle curve or stuck throttle, set a fault and governor will not operate
556595
if (_rotor_rpm > (_governor_rpm + _governor_range) && !autorotation.bailing_out()) {
557-
_governor_fault = true;
558-
governor_reset();
559-
GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Governor Fault: Rotor Overspeed");
560-
_governor_output = 0.0f;
561-
596+
_governor_fault_count++;
597+
if (_governor_fault_count > 20 ) { //allow for 20 ticks of governor fault to account for spikes produced by AM32 ESCs
598+
_governor_fault = true;
599+
governor_reset();
600+
GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Governor Fault: Rotor Overspeed");
601+
_governor_output = 0.0f;
602+
};
562603
// when performing power recovery from autorotation, this waits for user to load rotor in order to
563604
// engage the governor
564605
} else if (_rotor_rpm > _governor_rpm && autorotation.bailing_out()) {
@@ -570,13 +611,19 @@ void AP_MotorsHeli_RSC::autothrottle_run()
570611
float torque_limit = (get_governor_torque() * get_governor_torque());
571612
_governor_output = (_rotor_rpm / (float)_governor_rpm) * torque_limit;
572613
if (_rotor_rpm >= ((float)_governor_rpm - torque_ref_error_rpm)) {
573-
_governor_engage = true;
574-
_autothrottle = true;
575-
GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Governor Engaged");
614+
_governor_engage_count++;
615+
if (_governor_engage_count > 10) { //slightly delay engagement to handle spurious RPM signals from AM32 esc telemetry
616+
_governor_engage = true;
617+
_autothrottle = true;
618+
GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Governor Engaged");
619+
}
620+
} else {
621+
_governor_engage_count = 0;
576622
}
577623
} else {
578624
// temporary use of throttle curve and ramp timer to accelerate rotor to governor min torque rise speed
579625
_governor_output = 0.0f;
626+
_governor_fault_count = 0;
580627
}
581628
_control_output = constrain_float(_idle_throttle + (_rotor_ramp_output * (throttlecurve + _governor_output - _idle_throttle)), 0.0f, 1.0f);
582629
_governor_torque_reference = _control_output; // increment torque setting to be passed to main power loop
@@ -608,21 +655,23 @@ void AP_MotorsHeli_RSC::write_log(void) const
608655
// @Field: Gov: Governor Output
609656
// @Field: Throt: Throttle output
610657
// @Field: Ramp: throttle ramp up
658+
// @Field: RPM: RPM of the main rotor
611659
// @Field: Stat: RSC state
612660

613661
// Write to data flash log
614662
AP::logger().WriteStreaming("HRSC",
615-
"TimeUS,I,DRRPM,ERRPM,Gov,Throt,Ramp,Stat",
616-
"s#------",
617-
"F-------",
618-
"QBfffffB",
663+
"TimeUS,I,DRRPM,ERRPM,Gov,Throt,Ramp,RPM,Stat",
664+
"s#-----q-",
665+
"F------0-",
666+
"QBffffffB",
619667
AP_HAL::micros64(),
620668
_instance,
621669
get_desired_speed(),
622670
_rotor_runup_output,
623671
_governor_output,
624672
get_control_output(),
625673
_rotor_ramp_output,
674+
_rotor_rpm,
626675
uint8_t(_rsc_state));
627676
}
628677
#endif

libraries/AP_Motors/AP_MotorsHeli_RSC.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class AP_MotorsHeli_RSC {
130130
float _thrcrv_poly[4][4]; // spline polynomials for throttle curve interpolation
131131
float _collective_in; // collective in for throttle curve calculation, range 0-1.0f
132132
float _rotor_rpm; // rotor rpm from speed sensor for governor
133+
uint32_t _last_rpm_update; // last RPM update time
133134
bool _turbine_start; // initiates starting sequence
134135
bool _starting; // tracks if starting sequence has been used
135136
float _governor_output; // governor output for rotor speed control
@@ -139,6 +140,7 @@ class AP_MotorsHeli_RSC {
139140
bool _spooldown_complete; // flag for determining if spooldown is complete
140141
float _fast_idle_timer; // cooldown timer variable
141142
uint8_t _governor_fault_count; // variable for tracking governor speed sensor faults
143+
uint8_t _governor_engage_count; // variable for tracking governor readiness to engage
142144
float _governor_torque_reference; // governor reference for load calculations
143145
float _idle_throttle; // current idle throttle setting
144146

@@ -165,7 +167,9 @@ class AP_MotorsHeli_RSC {
165167
AP_Float _governor_droop_response; // governor response to droop under load
166168
AP_Float _governor_ff; // governor feedforward variable
167169
AP_Float _governor_range; // RPM range +/- governor rpm reference setting where governor is operational
170+
AP_Float _gov_filter_freq; // Governor RPM filter frequency
168171
AP_Int16 _cooldown_time; // cooldown time to provide a fast idle
172+
AP_Int8 _esc_index; // index of the ESC used for governor RPM control
169173

170174
// parameter accessors to allow conversions
171175
float get_critical_speed() const { return _critical_speed * 0.01; }

0 commit comments

Comments
 (0)