Skip to content

Commit

Permalink
Copter: add support for up to 12 flight modes (FLTMODE_EXT)
Browse files Browse the repository at this point in the history
  • Loading branch information
shellixyz committed Feb 5, 2024
1 parent 34ab839 commit 0e5c56c
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 29 deletions.
2 changes: 1 addition & 1 deletion ArduCopter/Copter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ void Copter::rc_loop()
// Read radio and 3-position switch on radio
// -----------------------------------------
read_radio();
rc().read_mode_switch();
read_control_switch();
}

// throttle_loop - should be run at 50 hz
Expand Down
6 changes: 6 additions & 0 deletions ArduCopter/Copter.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,14 @@ class Copter : public AP_Vehicle {

// flight modes convenience array
AP_Int8 *flight_modes;
AP_Int8 *flight_modes2 = &g2.flight_mode7;
const uint8_t num_flight_modes = 6;

uint8_t oldSwitchPosition = 254;
void read_control_switch();
uint8_t readSwitch(void) const;
void reset_control_switch();

struct RangeFinderState {
bool enabled:1;
bool alt_healthy:1; // true if we can trust the altitude from the rangefinder
Expand Down
51 changes: 49 additions & 2 deletions ArduCopter/Parameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,8 +1160,55 @@ const AP_Param::GroupInfo ParametersG2::var_info[] = {
AP_GROUPINFO("TKOFF_RPM_MIN", 58, ParametersG2, takeoff_rpm_min, 0),
#endif

// ID 62 is reserved for the SHOW_... parameters from the Skybrush fork at
// https://github.com/skybrush-io/ardupilot
// @Param: FLTMODE_EXT
// @DisplayName: Extended mode switch
// @Description: Setting this parameter to one allow to have up to 12 flight modes selectable with the flight mode channel instead of 6. Mode ranges: 901-1125, 1126-1200, 1201-1275, 1276-1350, 1351-1425, 1426-1500, 1501-1575, 1576-1650, 1651-1725, 1726-1800, 1801-1875, 1876-2199
// @Values: 0:Disabled,1:Enabled
// @User: Advanced
AP_GROUPINFO("FLTMODE_EXT", 47, ParametersG2, fltmode_ext, 0),

// @Param: FLTMODE7
// @DisplayName: FlightMode7
// @Description: Flight mode for switch position 7 (1501 to 1575), enabled with FLTMODE_EXT
// @Values: 0:Manual,1:CIRCLE,2:STABILIZE,3:TRAINING,4:ACRO,5:FBWA,6:FBWB,7:CRUISE,8:AUTOTUNE,10:Auto,11:RTL,12:Loiter,13:TAKEOFF,14:AVOID_ADSB,15:Guided,17:QSTABILIZE,18:QHOVER,19:QLOITER,20:QLAND,21:QRTL,22:QAUTOTUNE,23:QACRO,24:THERMAL
// @User: Advanced
AP_GROUPINFO("FLTMODE7", 48, ParametersG2, flight_mode7, (uint8_t)FLIGHT_MODE_7),

// @Param: FLTMODE8
// @DisplayName: FlightMode8
// @Description: Flight mode for switch position 8 (1576 to 1650), enabled with FLTMODE_EXT
// @Values: 0:Manual,1:CIRCLE,2:STABILIZE,3:TRAINING,4:ACRO,5:FBWA,6:FBWB,7:CRUISE,8:AUTOTUNE,10:Auto,11:RTL,12:Loiter,13:TAKEOFF,14:AVOID_ADSB,15:Guided,17:QSTABILIZE,18:QHOVER,19:QLOITER,20:QLAND,21:QRTL,22:QAUTOTUNE,23:QACRO,24:THERMAL
// @User: Advanced
AP_GROUPINFO("FLTMODE8", 59, ParametersG2, flight_mode8, (uint8_t)FLIGHT_MODE_8),

// @Param: FLTMODE9
// @DisplayName: FlightMode9
// @Description: Flight mode for switch position 9 (1651 to 1725), enabled with FLTMODE_EXT
// @Values: 0:Manual,1:CIRCLE,2:STABILIZE,3:TRAINING,4:ACRO,5:FBWA,6:FBWB,7:CRUISE,8:AUTOTUNE,10:Auto,11:RTL,12:Loiter,13:TAKEOFF,14:AVOID_ADSB,15:Guided,17:QSTABILIZE,18:QHOVER,19:QLOITER,20:QLAND,21:QRTL,22:QAUTOTUNE,23:QACRO,24:THERMAL
// @User: Advanced
AP_GROUPINFO("FLTMODE9", 60, ParametersG2, flight_mode9, (uint8_t)FLIGHT_MODE_9),

// @Param: FLTMODE10
// @DisplayName: FlightMode10
// @Description: Flight mode for switch position 10 (1726 to 1800), enabled with FLTMODE_EXT
// @Values: 0:Manual,1:CIRCLE,2:STABILIZE,3:TRAINING,4:ACRO,5:FBWA,6:FBWB,7:CRUISE,8:AUTOTUNE,10:Auto,11:RTL,12:Loiter,13:TAKEOFF,14:AVOID_ADSB,15:Guided,17:QSTABILIZE,18:QHOVER,19:QLOITER,20:QLAND,21:QRTL,22:QAUTOTUNE,23:QACRO,24:THERMAL
// @User: Advanced
AP_GROUPINFO("FLTMODE10", 61, ParametersG2, flight_mode10, (uint8_t)FLIGHT_MODE_10),

// @Param: FLTMODE11
// @DisplayName: FlightMode11
// @Description: Flight mode for switch position 11 (1801 to 1875), enabled with FLTMODE_EXT
// @Values: 0:Manual,1:CIRCLE,2:STABILIZE,3:TRAINING,4:ACRO,5:FBWA,6:FBWB,7:CRUISE,8:AUTOTUNE,10:Auto,11:RTL,12:Loiter,13:TAKEOFF,14:AVOID_ADSB,15:Guided,17:QSTABILIZE,18:QHOVER,19:QLOITER,20:QLAND,21:QRTL,22:QAUTOTUNE,23:QACRO,24:THERMAL
// @User: Advanced
AP_GROUPINFO("FLTMODE11", 62, ParametersG2, flight_mode11, (uint8_t)FLIGHT_MODE_11),

// @Param: FLTMODE12
// @DisplayName: FlightMode12
// @Description: Flight mode for switch position 12 (1876 to 2049), enabled with FLTMODE_EXT
// @Values: 0:Manual,1:CIRCLE,2:STABILIZE,3:TRAINING,4:ACRO,5:FBWA,6:FBWB,7:CRUISE,8:AUTOTUNE,10:Auto,11:RTL,12:Loiter,13:TAKEOFF,14:AVOID_ADSB,15:Guided,17:QSTABILIZE,18:QHOVER,19:QLOITER,20:QLAND,21:QRTL,22:QAUTOTUNE,23:QACRO,24:THERMAL
// @User: Advanced
AP_GROUPINFO("FLTMODE12", 63, ParametersG2, flight_mode12, (uint8_t)FLIGHT_MODE_12),


AP_GROUPEND
};
Expand Down
9 changes: 9 additions & 0 deletions ArduCopter/Parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,15 @@ class ParametersG2 {
#if HAL_WITH_ESC_TELEM && FRAME_CONFIG != HELI_FRAME
AP_Int16 takeoff_rpm_min;
#endif

// Extra modes.
AP_Int8 fltmode_ext;
AP_Int8 flight_mode7;
AP_Int8 flight_mode8;
AP_Int8 flight_mode9;
AP_Int8 flight_mode10;
AP_Int8 flight_mode11;
AP_Int8 flight_mode12;
};

extern const AP_Param::Info var_info[];
46 changes: 23 additions & 23 deletions ArduCopter/RC_Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,28 @@ int8_t RC_Channels_Copter::flight_mode_channel_number() const
return copter.g.flight_mode_chan.get();
}

void RC_Channel_Copter::mode_switch_changed(modeswitch_pos_t new_pos)
{
if (new_pos < 0 || (uint8_t)new_pos > copter.num_flight_modes) {
// should not have been called
return;
}

if (!copter.set_mode((Mode::Number)copter.flight_modes[new_pos].get(), ModeReason::RC_COMMAND)) {
return;
}

if (!rc().find_channel_for_option(AUX_FUNC::SIMPLE_MODE) &&
!rc().find_channel_for_option(AUX_FUNC::SUPERSIMPLE_MODE)) {
// if none of the Aux Switches are set to Simple or Super Simple Mode then
// set Simple Mode using stored parameters from EEPROM
if (BIT_IS_SET(copter.g.super_simple, new_pos)) {
copter.set_simple_mode(Copter::SimpleMode::SUPERSIMPLE);
} else {
copter.set_simple_mode(BIT_IS_SET(copter.g.simple_modes, new_pos) ? Copter::SimpleMode::SIMPLE : Copter::SimpleMode::NONE);
}
}
}
// void RC_Channel_Copter::mode_switch_changed(modeswitch_pos_t new_pos)
// {
// if (new_pos < 0 || (uint8_t)new_pos > copter.num_flight_modes) {
// // should not have been called
// return;
// }

// if (!copter.set_mode((Mode::Number)copter.flight_modes[new_pos].get(), ModeReason::RC_COMMAND)) {
// return;
// }

// if (!rc().find_channel_for_option(AUX_FUNC::SIMPLE_MODE) &&
// !rc().find_channel_for_option(AUX_FUNC::SUPERSIMPLE_MODE)) {
// // if none of the Aux Switches are set to Simple or Super Simple Mode then
// // set Simple Mode using stored parameters from EEPROM
// if (BIT_IS_SET(copter.g.super_simple, new_pos)) {
// copter.set_simple_mode(Copter::SimpleMode::SUPERSIMPLE);
// } else {
// copter.set_simple_mode(BIT_IS_SET(copter.g.simple_modes, new_pos) ? Copter::SimpleMode::SIMPLE : Copter::SimpleMode::NONE);
// }
// }
// }

bool RC_Channels_Copter::has_valid_input() const
{
Expand Down Expand Up @@ -144,7 +144,7 @@ void RC_Channel_Copter::do_aux_function_change_mode(const Mode::Number mode,
// return to flight mode switch's flight mode if we are currently
// in this mode
if (copter.flightmode->mode_number() == mode) {
rc().reset_mode_switch();
copter.reset_control_switch();
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions ArduCopter/RC_Channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ class RC_Channel_Copter : public RC_Channel
void do_aux_function_change_air_mode(const AuxSwitchPos ch_flag);
void do_aux_function_change_force_flying(const AuxSwitchPos ch_flag);

// called when the mode switch changes position:
void mode_switch_changed(modeswitch_pos_t new_pos) override;

};

class RC_Channels_Copter : public RC_Channels
Expand Down
18 changes: 18 additions & 0 deletions ArduCopter/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,24 @@
#ifndef FLIGHT_MODE_6
# define FLIGHT_MODE_6 Mode::Number::STABILIZE
#endif
#if !defined(FLIGHT_MODE_7)
# define FLIGHT_MODE_7 Mode::Number::STABILIZE
#endif
#if !defined(FLIGHT_MODE_8)
# define FLIGHT_MODE_8 Mode::Number::STABILIZE
#endif
#if !defined(FLIGHT_MODE_9)
# define FLIGHT_MODE_9 Mode::Number::STABILIZE
#endif
#if !defined(FLIGHT_MODE_10)
# define FLIGHT_MODE_10 Mode::Number::STABILIZE
#endif
#if !defined(FLIGHT_MODE_11)
# define FLIGHT_MODE_11 Mode::Number::STABILIZE
#endif
#if !defined(FLIGHT_MODE_12)
# define FLIGHT_MODE_12 Mode::Number::STABILIZE
#endif


//////////////////////////////////////////////////////////////////////////////
Expand Down
89 changes: 89 additions & 0 deletions ArduCopter/control_modes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "Copter.h"

void Copter::read_control_switch()
{
static bool switch_debouncer;
uint8_t switchPosition = readSwitch();

// If switchPosition = 255 this indicates that the mode control channel input was out of range
// If we get this value we do not want to change modes.
if(switchPosition == 255) return;

if (!rc().has_valid_input()) {
// ignore the mode switch channel if there is no valid RC input
return;
}

if (oldSwitchPosition != switchPosition) {

if (switch_debouncer == false) {
// this ensures that mode switches only happen if the
// switch changes for 2 reads. This prevents momentary
// spikes in the mode control channel from causing a mode
// switch
switch_debouncer = true;
return;
}

enum Mode::Number fm;
if (switchPosition < 6) {
fm = (enum Mode::Number)flight_modes[switchPosition].get();
} else {
fm = (enum Mode::Number)flight_modes2[switchPosition-6].get();
}

oldSwitchPosition = switchPosition;

if (!copter.set_mode(fm, ModeReason::RC_COMMAND)) {
return;
}

if (!rc().find_channel_for_option(RC_Channel_Copter::AUX_FUNC::SIMPLE_MODE) &&
!rc().find_channel_for_option(RC_Channel_Copter::AUX_FUNC::SUPERSIMPLE_MODE)) {
// if none of the Aux Switches are set to Simple or Super Simple Mode then
// set Simple Mode using stored parameters from EEPROM
if (BIT_IS_SET(copter.g.super_simple, switchPosition)) {
copter.set_simple_mode(Copter::SimpleMode::SUPERSIMPLE);
} else {
copter.set_simple_mode(BIT_IS_SET(copter.g.simple_modes, switchPosition) ? Copter::SimpleMode::SIMPLE : Copter::SimpleMode::NONE);
}
}
}

switch_debouncer = false;

}

uint8_t Copter::readSwitch(void) const
{
uint16_t pulsewidth = RC_Channels::get_radio_in(g.flight_mode_chan.get() - 1);
if (pulsewidth <= 900 || pulsewidth >= 2200) return 255; // This is an error condition

if (g2.fltmode_ext == 0) {
if (pulsewidth < 1231) return 0;
if (pulsewidth < 1361) return 1;
if (pulsewidth < 1491) return 2;
if (pulsewidth < 1621) return 3;
if (pulsewidth < 1750) return 4; // Software Manual
return 5; // Hardware Manual
} else {
if (pulsewidth < 1126) return 0;
if (pulsewidth < 1201) return 1;
if (pulsewidth < 1276) return 2;
if (pulsewidth < 1351) return 3;
if (pulsewidth < 1426) return 4;
if (pulsewidth < 1501) return 5;
if (pulsewidth < 1576) return 6;
if (pulsewidth < 1651) return 7;
if (pulsewidth < 1726) return 8;
if (pulsewidth < 1801) return 9;
if (pulsewidth < 1876) return 10;
return 11;
}
}

void Copter::reset_control_switch()
{
oldSwitchPosition = 254;
read_control_switch();
}

0 comments on commit 0e5c56c

Please sign in to comment.