/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- #include "Plane.h" void Plane::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 (failsafe.ch3_failsafe || failsafe.ch3_counter > 0) { // when we are in ch3_failsafe mode then RC input is not // working, and we need to ignore the mode switch channel return; } if (millis() - failsafe.last_valid_rc_ms > 100) { // only use signals that are less than 0.1s old. return; } // we look for changes in the switch position. If the // RST_SWITCH_CH parameter is set, then it is a switch that can be // used to force re-reading of the control switch. This is useful // when returning to the previous mode after a failsafe or fence // breach. This channel is best used on a momentary switch (such // as a spring loaded trainer switch). if (oldSwitchPosition != switchPosition || (g.reset_switch_chan != 0 && hal.rcin->read(g.reset_switch_chan-1) > RESET_SWITCH_CHAN_PWM)) { 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; } set_mode((enum FlightMode)(flight_modes[switchPosition].get())); oldSwitchPosition = switchPosition; prev_WP_loc = current_loc; } if (g.reset_mission_chan != 0 && hal.rcin->read(g.reset_mission_chan-1) > RESET_SWITCH_CHAN_PWM) { mission.start(); prev_WP_loc = current_loc; } switch_debouncer = false; if (g.inverted_flight_ch != 0) { // if the user has configured an inverted flight channel, then // fly upside down when that channel goes above INVERTED_FLIGHT_PWM inverted_flight = (control_mode != MANUAL && hal.rcin->read(g.inverted_flight_ch-1) > INVERTED_FLIGHT_PWM); } #if CONFIG_HAL_BOARD == HAL_BOARD_PX4 if (g.override_channel > 0) { // if the user has configured an override channel then check it bool override = (hal.rcin->read(g.override_channel-1) >= PX4IO_OVERRIDE_PWM); if (override && !px4io_override_enabled) { // we only update the mixer if we are not armed. This is // important as otherwise we will need to temporarily // disarm to change the mixer if (hal.util->get_soft_armed() || setup_failsafe_mixing()) { px4io_override_enabled = true; // disable output channels to force PX4IO override gcs_send_text_P(SEVERITY_LOW, PSTR("PX4IO Override enabled")); } else { // we'll try again next loop. The PX4IO code sometimes // rejects a mixer, probably due to it being busy in // some way? gcs_send_text_P(SEVERITY_LOW, PSTR("PX4IO Override enable failed")); } } else if (!override && px4io_override_enabled) { px4io_override_enabled = false; // re-enable output channels for (uint8_t i=0; i<8; i++) { hal.rcout->enable_ch(i); } RC_Channel_aux::enable_aux_servos(); gcs_send_text_P(SEVERITY_LOW, PSTR("PX4IO Override disabled")); } if (px4io_override_enabled && hal.util->safety_switch_state() != AP_HAL::Util::SAFETY_ARMED) { // we force safety off, so that if this override is used // with a in-flight reboot it gives a way for the pilot to // re-arm and take manual control hal.rcout->force_safety_off(); } if (px4io_override_enabled) { /* ensure that all channels are disabled from the FMU. If PX4IO receives any channel input from the FMU then it will think the FMU is still active and won't enable the internal mixer. */ for (uint8_t i=0; i<16; i++) { hal.rcout->disable_ch(i); } } } #endif // CONFIG_HAL_BOARD } uint8_t Plane::readSwitch(void) { uint16_t pulsewidth = hal.rcin->read(g.flight_mode_channel - 1); if (pulsewidth <= 900 || pulsewidth >= 2200) return 255; // This is an error condition if (pulsewidth > 1230 && pulsewidth <= 1360) return 1; if (pulsewidth > 1360 && pulsewidth <= 1490) return 2; if (pulsewidth > 1490 && pulsewidth <= 1620) return 3; if (pulsewidth > 1620 && pulsewidth <= 1749) return 4; // Software Manual if (pulsewidth >= 1750) return 5; // Hardware Manual return 0; } void Plane::reset_control_switch() { oldSwitchPosition = 254; read_control_switch(); } /* called when entering autotune */ void Plane::autotune_start(void) { rollController.autotune_start(); pitchController.autotune_start(); } /* called when exiting autotune */ void Plane::autotune_restore(void) { rollController.autotune_restore(); pitchController.autotune_restore(); } /* enable/disable autotune for AUTO modes */ void Plane::autotune_enable(bool enable) { if (enable) { autotune_start(); } else { autotune_restore(); } } /* are we flying inverted? */ bool Plane::fly_inverted(void) { if (g.inverted_flight_ch != 0 && inverted_flight) { // controlled with INVERTED_FLIGHT_CH return true; } if (control_mode == AUTO && auto_state.inverted_flight) { return true; } return false; }