fmu: fix safety button

- use the orb topic safety to check the safety state, because the actual
  safety state can come from the IO
- fix initialization if circuit breaker is set
This commit is contained in:
Beat Küng
2018-07-31 11:10:00 +02:00
parent 4c572577b2
commit bc9c25a376
2 changed files with 45 additions and 24 deletions
+43 -23
View File
@@ -189,6 +189,7 @@ private:
int _armed_sub; int _armed_sub;
int _param_sub; int _param_sub;
int _safety_sub;
orb_advert_t _outputs_pub; orb_advert_t _outputs_pub;
unsigned _num_outputs; unsigned _num_outputs;
@@ -218,7 +219,8 @@ private:
uint16_t _reverse_pwm_mask; uint16_t _reverse_pwm_mask;
unsigned _num_failsafe_set; unsigned _num_failsafe_set;
unsigned _num_disarmed_set; unsigned _num_disarmed_set;
bool _safety_off; bool _safety_off; ///< State of the safety button from the subscribed safety topic
bool _safety_btn_off; ///< State of the safety button read from the HW button
bool _safety_disabled; bool _safety_disabled;
orb_advert_t _to_safety; orb_advert_t _to_safety;
orb_advert_t _to_mixer_status; ///< mixer status flags orb_advert_t _to_mixer_status; ///< mixer status flags
@@ -304,6 +306,7 @@ PX4FMU::PX4FMU(bool run_as_task) :
_run_as_task(run_as_task), _run_as_task(run_as_task),
_armed_sub(-1), _armed_sub(-1),
_param_sub(-1), _param_sub(-1),
_safety_sub(-1),
_outputs_pub(nullptr), _outputs_pub(nullptr),
_num_outputs(0), _num_outputs(0),
_class_instance(0), _class_instance(0),
@@ -321,6 +324,7 @@ PX4FMU::PX4FMU(bool run_as_task) :
_num_failsafe_set(0), _num_failsafe_set(0),
_num_disarmed_set(0), _num_disarmed_set(0),
_safety_off(false), _safety_off(false),
_safety_btn_off(false),
_safety_disabled(false), _safety_disabled(false),
_to_safety(nullptr), _to_safety(nullptr),
_to_mixer_status(nullptr), _to_mixer_status(nullptr),
@@ -358,6 +362,7 @@ PX4FMU::PX4FMU(bool run_as_task) :
// If there is no safety button, disable it on boot. // If there is no safety button, disable it on boot.
#ifndef GPIO_BTN_SAFETY #ifndef GPIO_BTN_SAFETY
_safety_off = true; _safety_off = true;
_safety_btn_off = true;
#endif #endif
/* only enable this during development */ /* only enable this during development */
@@ -374,6 +379,7 @@ PX4FMU::~PX4FMU()
orb_unsubscribe(_armed_sub); orb_unsubscribe(_armed_sub);
orb_unsubscribe(_param_sub); orb_unsubscribe(_param_sub);
orb_unsubscribe(_safety_sub);
orb_unadvertise(_outputs_pub); orb_unadvertise(_outputs_pub);
orb_unadvertise(_to_safety); orb_unadvertise(_to_safety);
@@ -415,11 +421,17 @@ PX4FMU::init()
_safety_disabled = circuit_breaker_enabled("CBRK_IO_SAFETY", CBRK_IO_SAFETY_KEY); _safety_disabled = circuit_breaker_enabled("CBRK_IO_SAFETY", CBRK_IO_SAFETY_KEY);
if (_safety_disabled) {
_safety_off = true;
_safety_btn_off = true;
}
/* force a reset of the update rate */ /* force a reset of the update rate */
_current_update_rate = 0; _current_update_rate = 0;
_armed_sub = orb_subscribe(ORB_ID(actuator_armed)); _armed_sub = orb_subscribe(ORB_ID(actuator_armed));
_param_sub = orb_subscribe(ORB_ID(parameter_update)); _param_sub = orb_subscribe(ORB_ID(parameter_update));
_safety_sub = orb_subscribe(ORB_ID(safety));
/* initialize PWM limit lib */ /* initialize PWM limit lib */
pwm_limit_init(&_pwm_limit); pwm_limit_init(&_pwm_limit);
@@ -452,25 +464,25 @@ PX4FMU::safety_check_button(void)
* state machine, keep ARM_COUNTER_THRESHOLD the same * state machine, keep ARM_COUNTER_THRESHOLD the same
* length in all cases of the if/else struct below. * length in all cases of the if/else struct below.
*/ */
if (safety_button_pressed && !_safety_off) { if (safety_button_pressed && !_safety_btn_off) {
if (counter < CYCLE_COUNT) { if (counter < CYCLE_COUNT) {
counter++; counter++;
} else if (counter == CYCLE_COUNT) { } else if (counter == CYCLE_COUNT) {
/* switch to armed state */ /* switch to armed state */
_safety_off = true; _safety_btn_off = true;
counter++; counter++;
} }
} else if (safety_button_pressed && _safety_off) { } else if (safety_button_pressed && _safety_btn_off) {
if (counter < CYCLE_COUNT) { if (counter < CYCLE_COUNT) {
counter++; counter++;
} else if (counter == CYCLE_COUNT) { } else if (counter == CYCLE_COUNT) {
/* change to disarmed state and notify the FMU */ /* change to disarmed state and notify the FMU */
_safety_off = false; _safety_btn_off = false;
counter++; counter++;
} }
@@ -494,7 +506,7 @@ PX4FMU::flash_safety_button()
/* cycle the blink state machine at 10Hz */ /* cycle the blink state machine at 10Hz */
static int blink_counter = 0; static int blink_counter = 0;
if (_safety_off) { if (_safety_btn_off) {
if (_armed.armed) { if (_armed.armed) {
pattern = LED_PATTERN_IO_FMU_ARMED; pattern = LED_PATTERN_IO_FMU_ARMED;
@@ -1240,10 +1252,7 @@ PX4FMU::cycle()
*/ */
struct safety_s safety = {}; struct safety_s safety = {};
if (_safety_disabled) { if (!_safety_disabled) {
_safety_off = true;
} else {
/* read safety switch input and control safety switch LED at 10Hz */ /* read safety switch input and control safety switch LED at 10Hz */
safety_check_button(); safety_check_button();
} }
@@ -1252,30 +1261,35 @@ PX4FMU::cycle()
flash_safety_button(); flash_safety_button();
safety.timestamp = hrt_absolute_time(); safety.timestamp = hrt_absolute_time();
safety.safety_switch_available = true;
if (_safety_off) { safety.safety_off = _safety_btn_off;
safety.safety_off = true;
safety.safety_switch_available = true;
} else {
safety.safety_off = false;
safety.safety_switch_available = true;
}
/* lazily publish the safety status */ /* lazily publish the safety status */
if (_to_safety != nullptr) { if (_to_safety != nullptr) {
orb_publish(ORB_ID(safety), _to_safety, &safety); orb_publish(ORB_ID(safety), _to_safety, &safety);
} else { } else {
int instance = _class_instance; int instance;
_to_safety = orb_advertise_multi(ORB_ID(safety), &safety, &instance, ORB_PRIO_DEFAULT); _to_safety = orb_advertise_multi(ORB_ID(safety), &safety, &instance, ORB_PRIO_DEFAULT);
} }
} }
} }
#endif #endif
/* check arming state */
/* check safety button state */
bool updated = false; bool updated = false;
orb_check(_safety_sub, &updated);
if (updated) {
safety_s safety;
if (orb_copy(ORB_ID(actuator_armed), _safety_sub, &safety) == 0) {
_safety_off = !safety.safety_switch_available || safety.safety_off;
}
}
/* check arming state */
orb_check(_armed_sub, &updated); orb_check(_armed_sub, &updated);
if (updated) { if (updated) {
@@ -1479,12 +1493,12 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
case PWM_SERVO_SET_FORCE_SAFETY_OFF: case PWM_SERVO_SET_FORCE_SAFETY_OFF:
/* force safety switch off */ /* force safety switch off */
_safety_off = true; _safety_btn_off = true;
break; break;
case PWM_SERVO_SET_FORCE_SAFETY_ON: case PWM_SERVO_SET_FORCE_SAFETY_ON:
/* force safety switch on */ /* force safety switch on */
_safety_off = false; _safety_btn_off = false;
break; break;
case PWM_SERVO_DISARM: case PWM_SERVO_DISARM:
@@ -3016,6 +3030,12 @@ int PX4FMU::print_status()
PX4_INFO("Max update rate: %i Hz", _current_update_rate); PX4_INFO("Max update rate: %i Hz", _current_update_rate);
} }
#ifdef GPIO_BTN_SAFETY
if (!PX4_MFT_HW_SUPPORTED(PX4_MFT_PX4IO)) {
PX4_INFO("Safety State (from button): %s", _safety_btn_off ? "off" : "on");
}
#endif
const char *mode_str = nullptr; const char *mode_str = nullptr;
switch (_mode) { switch (_mode) {
+2 -1
View File
@@ -1650,7 +1650,8 @@ PX4IO::io_handle_status(uint16_t status)
orb_publish(ORB_ID(safety), _to_safety, &safety); orb_publish(ORB_ID(safety), _to_safety, &safety);
} else { } else {
_to_safety = orb_advertise(ORB_ID(safety), &safety); int instance;
_to_safety = orb_advertise_multi(ORB_ID(safety), &safety, &instance, ORB_PRIO_DEFAULT);
} }
return ret; return ret;