Added kill switch support

This commit is contained in:
Benjamin Vedder 2021-06-13 13:46:27 +02:00
parent 5742d1baf1
commit 75b84f1f2d
16 changed files with 142 additions and 41 deletions

View File

@ -27,6 +27,7 @@
* Dynamic QML-script write support.
* Use fast speed tracker for current controller.
* Disable motor for 5 seconds after flash operations.
* Added kill switch support.
=== FW 5.02 ===
* IMU calibration improvement.

View File

@ -45,6 +45,9 @@
#ifndef APPCONF_SERVO_OUT_ENABLE
#define APPCONF_SERVO_OUT_ENABLE false
#endif
#ifndef APPCONF_KILL_SW_MODE
#define APPCONF_KILL_SW_MODE KILL_SW_MODE_DISABLED
#endif
#ifndef APPCONF_SEND_CAN_STATUS_RATE_HZ
#define APPCONF_SEND_CAN_STATUS_RATE_HZ 50
#endif

View File

@ -426,6 +426,12 @@ void commands_process_packet(unsigned char *data, unsigned int len,
if (mask & ((uint32_t)1 << 20)) {
buffer_append_float32(send_buffer, mc_interface_read_reset_avg_vq(), 1e3, &ind);
}
if (mask & ((uint32_t)1 << 21)) {
uint8_t status = 0;
status |= timeout_has_timeout();
status |= timeout_kill_sw_active() << 1;
send_buffer[ind++] = status;
}
reply_func(send_buffer, ind);
chMtxUnlock(&send_buffer_mutex);
@ -565,7 +571,7 @@ void commands_process_packet(unsigned char *data, unsigned int len,
conf_general_store_app_configuration(appconf);
app_set_configuration(appconf);
timeout_configure(appconf->timeout_msec, appconf->timeout_brake_current);
timeout_configure(appconf->timeout_msec, appconf->timeout_brake_current, appconf->kill_sw_mode);
chThdSleepMilliseconds(200);
int32_t ind = 0;
@ -1122,6 +1128,16 @@ void commands_process_packet(unsigned char *data, unsigned int len,
buffer_append_float32_auto(send_buffer, q[3], &ind);
}
if (mask & ((uint32_t)1 << 16)) {
uint8_t current_controller_id = app_get_configuration()->controller_id;
#ifdef HW_HAS_DUAL_MOTORS
if (mc_interface_get_motor_thread() == 2) {
current_controller_id = utils_second_motor_id();
}
#endif
send_buffer[ind++] = current_controller_id;
}
reply_func(send_buffer, ind);
} break;

View File

@ -531,8 +531,9 @@ bool conf_general_detect_motor_param(float current, float min_rpm, float low_dut
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
mc_interface_lock();
@ -597,7 +598,7 @@ bool conf_general_detect_motor_param(float current, float min_rpm, float low_dut
if (!started) {
mc_interface_set_current(0.0);
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_set_configuration(mcconf_old);
mc_interface_unlock();
mempools_free_mcconf(mcconf);
@ -689,7 +690,7 @@ bool conf_general_detect_motor_param(float current, float min_rpm, float low_dut
// Restore settings
mc_interface_set_configuration(mcconf_old);
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
@ -762,8 +763,9 @@ bool conf_general_measure_flux_linkage(float current, float duty,
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
mc_interface_lock();
@ -838,7 +840,7 @@ bool conf_general_measure_flux_linkage(float current, float duty,
if (!started) {
mc_interface_set_current(0.0);
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_set_configuration(mcconf);
mc_interface_unlock();
mempools_free_mcconf(mcconf);
@ -861,7 +863,7 @@ bool conf_general_measure_flux_linkage(float current, float duty,
chThdSleepMilliseconds(1.0);
}
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_set_configuration(mcconf_old);
mc_interface_unlock();
mc_interface_set_current(0.0);
@ -978,8 +980,9 @@ bool conf_general_measure_flux_linkage_openloop(float current, float duty,
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
mc_interface_lock();
@ -1100,7 +1103,7 @@ bool conf_general_measure_flux_linkage_openloop(float current, float duty,
result = true;
}
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
mc_interface_release_motor();
mc_interface_wait_for_motor_release(1.0);
@ -1166,8 +1169,9 @@ int conf_general_autodetect_apply_sensors_foc(float current,
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
mc_interface_lock();
@ -1242,7 +1246,7 @@ int conf_general_autodetect_apply_sensors_foc(float current,
res = true;
}
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
mc_interface_release_motor();
mc_interface_wait_for_motor_release(1.0);
@ -1531,8 +1535,9 @@ int conf_general_detect_apply_all_foc(float max_power_loss,
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
mc_interface_lock();
@ -1565,7 +1570,7 @@ int conf_general_detect_apply_all_foc(float max_power_loss,
#endif
if (!res_r_l_imax_m1 || !res_r_l_imax_m2) {
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
mc_interface_release_motor();
mc_interface_wait_for_motor_release(1.0);
@ -1690,7 +1695,7 @@ int conf_general_detect_apply_all_foc(float max_power_loss,
result = -10;
}
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_lock_override_once();
mc_interface_release_motor();
mc_interface_wait_for_motor_release(1.0);

View File

@ -24,7 +24,7 @@
#define FW_VERSION_MAJOR 5
#define FW_VERSION_MINOR 03
// Set to 0 for building a release and iterate during beta test builds
#define FW_TEST_VERSION_NUMBER 38
#define FW_TEST_VERSION_NUMBER 39
#include "datatypes.h"

View File

@ -200,6 +200,7 @@ int32_t confgenerator_serialize_appconf(uint8_t *buffer, const app_configuration
buffer[ind++] = (uint8_t)conf->uavcan_esc_index;
buffer[ind++] = conf->uavcan_raw_mode;
buffer[ind++] = conf->servo_out_enable;
buffer[ind++] = conf->kill_sw_mode;
buffer[ind++] = conf->app_to_use;
buffer[ind++] = conf->app_ppm_conf.ctrl_type;
buffer_append_float32_auto(buffer, conf->app_ppm_conf.pid_max_erpm, &ind);
@ -560,6 +561,7 @@ bool confgenerator_deserialize_appconf(const uint8_t *buffer, app_configuration
conf->uavcan_esc_index = buffer[ind++];
conf->uavcan_raw_mode = buffer[ind++];
conf->servo_out_enable = buffer[ind++];
conf->kill_sw_mode = buffer[ind++];
conf->app_to_use = buffer[ind++];
conf->app_ppm_conf.ctrl_type = buffer[ind++];
conf->app_ppm_conf.pid_max_erpm = buffer_get_float32_auto(buffer, &ind);
@ -904,6 +906,7 @@ void confgenerator_set_defaults_appconf(app_configuration *conf) {
conf->uavcan_esc_index = APPCONF_UAVCAN_ESC_INDEX;
conf->uavcan_raw_mode = APPCONF_UAVCAN_RAW_MODE;
conf->servo_out_enable = APPCONF_SERVO_OUT_ENABLE;
conf->kill_sw_mode = APPCONF_KILL_SW_MODE;
conf->app_to_use = APPCONF_APP_TO_USE;
conf->app_ppm_conf.ctrl_type = APPCONF_PPM_CTRL_TYPE;
conf->app_ppm_conf.pid_max_erpm = APPCONF_PPM_PID_MAX_ERPM;

View File

@ -9,7 +9,7 @@
// Constants
#define MCCONF_SIGNATURE 4213619100
#define APPCONF_SIGNATURE 470228522
#define APPCONF_SIGNATURE 2268062315
// Functions
int32_t confgenerator_serialize_mcconf(uint8_t *buffer, const mc_configuration *conf);

View File

@ -797,6 +797,14 @@ typedef enum {
UAVCAN_RAW_MODE_DUTY
} UAVCAN_RAW_MODE;
typedef enum {
KILL_SW_MODE_DISABLED = 0,
KILL_SW_MODE_PPM_LOW,
KILL_SW_MODE_PPM_HIGH,
KILL_SW_MODE_ADC2_LOW,
KILL_SW_MODE_ADC2_HIGH
} KILL_SW_MODE;
typedef struct {
// Settings
uint8_t controller_id;
@ -809,6 +817,7 @@ typedef struct {
bool permanent_uart_enabled;
SHUTDOWN_MODE shutdown_mode;
bool servo_out_enable;
KILL_SW_MODE kill_sw_mode;
// CAN modes
CAN_MODE can_mode;

View File

@ -120,8 +120,7 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
new_app_size += flash_addr[NEW_APP_BASE];
mc_interface_unlock();
mc_interface_release_motor();
mc_interface_release_motor_override();
mc_interface_ignore_input_both(5000);
if (!mc_interface_wait_for_motor_release(3.0)) {
@ -214,8 +213,7 @@ uint16_t flash_helper_qmlui_flags(void) {
void flash_helper_jump_to_bootloader(void) {
typedef void (*pFunction)(void);
mc_interface_unlock();
mc_interface_release_motor();
mc_interface_release_motor_override();
usbDisconnectBus(&USBD1);
usbStop(&USBD1);
@ -370,8 +368,7 @@ static uint16_t erase_sector(uint32_t sector) {
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
mc_interface_unlock();
mc_interface_release_motor();
mc_interface_release_motor_override();
mc_interface_ignore_input_both(5000);
if (!mc_interface_wait_for_motor_release(3.0)) {
@ -404,8 +401,7 @@ static uint16_t write_data(uint32_t base, uint8_t *data, uint32_t len) {
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
mc_interface_unlock();
mc_interface_release_motor();
mc_interface_release_motor_override();
mc_interface_ignore_input_both(5000);
if (!mc_interface_wait_for_motor_release(3.0)) {

2
main.c
View File

@ -264,7 +264,7 @@ int main(void) {
chThdCreateStatic(flash_integrity_check_thread_wa, sizeof(flash_integrity_check_thread_wa), LOWPRIO, flash_integrity_check_thread, NULL);
timeout_init();
timeout_configure(appconf->timeout_msec, appconf->timeout_brake_current);
timeout_configure(appconf->timeout_msec, appconf->timeout_brake_current, appconf->kill_sw_mode);
mempools_free_appconf(appconf);

View File

@ -805,6 +805,22 @@ void mc_interface_release_motor(void) {
mc_interface_set_current(0.0);
}
void mc_interface_release_motor_override(void) {
switch (motor_now()->m_conf.motor_type) {
case MOTOR_TYPE_BLDC:
case MOTOR_TYPE_DC:
mcpwm_set_current(0.0);
break;
case MOTOR_TYPE_FOC:
mcpwm_foc_set_current(0.0);
break;
default:
break;
}
}
bool mc_interface_wait_for_motor_release(float timeout) {
systime_t time_start = chVTGetSystemTimeX();
bool res = false;

View File

@ -52,6 +52,7 @@ void mc_interface_set_handbrake_rel(float val);
int mc_interface_set_tachometer_value(int steps);
void mc_interface_brake_now(void);
void mc_interface_release_motor(void);
void mc_interface_release_motor_override(void);
bool mc_interface_wait_for_motor_release(float timeout);
float mc_interface_get_duty_cycle_set(void);
float mc_interface_get_duty_cycle_now(void);

View File

@ -1470,8 +1470,9 @@ void mcpwm_foc_encoder_detect(float current, bool print, float *offset, float *r
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(600000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
// Save configuration
float offset_old = motor->m_conf->foc_encoder_offset;
@ -1671,7 +1672,7 @@ void mcpwm_foc_encoder_detect(float current, bool print, float *offset, float *r
motor->m_conf->foc_motor_ld_lq_diff = ldiff_old;
// Enable timeout
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
}
@ -1708,8 +1709,9 @@ float mcpwm_foc_measure_resistance(float current, int samples, bool stop_after)
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
// Ramp up the current slowly
while (fabsf(motor->m_iq_set - current) > 0.001) {
@ -1742,7 +1744,7 @@ float mcpwm_foc_measure_resistance(float current, int samples, bool stop_after)
motor->m_state = MC_STATE_OFF;
stop_pwm_hw(motor);
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
return 0.0;
@ -1763,7 +1765,7 @@ float mcpwm_foc_measure_resistance(float current, int samples, bool stop_after)
}
// Enable timeout
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
return (voltage_avg / current_avg) * (2.0 / 3.0);
@ -2023,8 +2025,9 @@ bool mcpwm_foc_hall_detect(float current, uint8_t *hall_table) {
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
// Lock the motor
motor->m_phase_now_override = 0;
@ -2081,7 +2084,7 @@ bool mcpwm_foc_hall_detect(float current, uint8_t *hall_table) {
motor->m_conf->foc_motor_ld_lq_diff = ldiff_old;
// Enable timeout
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
int fails = 0;
for(int i = 0;i < 8;i++) {
@ -2131,8 +2134,9 @@ int mcpwm_foc_dc_cal(bool cal_undriven) {
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(600000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
// Measure driven offsets
@ -2314,7 +2318,7 @@ int mcpwm_foc_dc_cal(bool cal_undriven) {
// TODO: Make sure that offsets are no more than e.g. 5%, as larger values indicate hardware problems.
// Enable timeout
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
mc_interface_unlock();
m_dccal_done = true;

View File

@ -448,8 +448,9 @@ void terminal_process_string(char *str) {
// Disable timeout
systime_t tout = timeout_get_timeout_msec();
float tout_c = timeout_get_brake_current();
KILL_SW_MODE tout_ksw = timeout_get_kill_sw_mode();
timeout_reset();
timeout_configure(60000, 0.0);
timeout_configure(60000, 0.0, KILL_SW_MODE_DISABLED);
for (int i = 0;i < 100;i++) {
mc_interface_set_duty(((float)i / 100.0) * duty);
@ -476,7 +477,7 @@ void terminal_process_string(char *str) {
mempools_free_mcconf(mcconf_old);
// Enable timeout
timeout_configure(tout, tout_c);
timeout_configure(tout, tout_c, tout_ksw);
vq_avg /= samples;
rpm_avg /= samples;

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Benjamin Vedder benjamin@vedder.se
Copyright 2016 - 2021 Benjamin Vedder benjamin@vedder.se
This file is part of the VESC firmware.
@ -27,7 +27,9 @@ static volatile bool init_done = false;
static volatile systime_t timeout_msec;
static volatile systime_t last_update_time;
static volatile float timeout_brake_current;
static volatile KILL_SW_MODE timeout_kill_sw_mode;
static volatile bool has_timeout;
static volatile bool kill_sw_active;
static volatile uint32_t feed_counter[MAX_THREADS_MONITOR];
// Threads
@ -38,7 +40,9 @@ void timeout_init(void) {
timeout_msec = 1000;
last_update_time = 0;
timeout_brake_current = 0.0;
timeout_kill_sw_mode = KILL_SW_MODE_DISABLED;
has_timeout = false;
kill_sw_active = false;
init_done = true;
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
@ -77,9 +81,10 @@ void timeout_init(void) {
chThdCreateStatic(timeout_thread_wa, sizeof(timeout_thread_wa), NORMALPRIO, timeout_thread, NULL);
}
void timeout_configure(systime_t timeout, float brake_current) {
void timeout_configure(systime_t timeout, float brake_current, KILL_SW_MODE kill_sw_mode) {
timeout_msec = timeout;
timeout_brake_current = brake_current;
timeout_kill_sw_mode = kill_sw_mode;
}
void timeout_reset(void) {
@ -90,6 +95,10 @@ bool timeout_has_timeout(void) {
return has_timeout;
}
bool timeout_kill_sw_active(void) {
return kill_sw_active;
}
systime_t timeout_get_timeout_msec(void) {
return timeout_msec;
}
@ -98,6 +107,10 @@ float timeout_get_brake_current(void) {
return timeout_brake_current;
}
KILL_SW_MODE timeout_get_kill_sw_mode(void) {
return timeout_kill_sw_mode;
}
void timeout_feed_WDT(uint8_t index) {
++feed_counter[index];
}
@ -172,17 +185,47 @@ static THD_FUNCTION(timeout_thread, arg) {
chRegSetThreadName("Timeout");
for(;;) {
if (timeout_msec != 0 && chVTTimeElapsedSinceX(last_update_time) > MS2ST(timeout_msec)) {
bool kill_sw = false;
switch (timeout_kill_sw_mode) {
case KILL_SW_MODE_PPM_LOW:
kill_sw = !palReadPad(HW_ICU_GPIO, HW_ICU_PIN);
break;
case KILL_SW_MODE_PPM_HIGH:
kill_sw = palReadPad(HW_ICU_GPIO, HW_ICU_PIN);
break;
case KILL_SW_MODE_ADC2_LOW:
kill_sw = ADC_VOLTS(ADC_IND_EXT2) < 1.65;
break;
case KILL_SW_MODE_ADC2_HIGH:
kill_sw = ADC_VOLTS(ADC_IND_EXT2) > 1.65;
break;
default:
break;
}
if (kill_sw || (timeout_msec != 0 && chVTTimeElapsedSinceX(last_update_time) > MS2ST(timeout_msec))) {
mc_interface_release_motor_override();
mc_interface_unlock();
mc_interface_select_motor_thread(1);
mc_interface_set_brake_current(timeout_brake_current);
mc_interface_select_motor_thread(2);
mc_interface_set_brake_current(timeout_brake_current);
has_timeout = true;
mc_interface_ignore_input(20);
if (!kill_sw) {
has_timeout = true;
}
} else {
has_timeout = false;
}
kill_sw_active = kill_sw;
bool threads_ok = true;
// Monitored threads (foc, can, timer) must report at least one iteration,

View File

@ -23,6 +23,7 @@
#include "ch.h"
#include "chtypes.h"
#include "chsystypes.h"
#include "datatypes.h"
#define MAX_THREADS_MONITOR 10
#define MIN_THREAD_ITERATIONS 1
@ -36,14 +37,16 @@ typedef enum {
// Functions
void timeout_init(void);
void timeout_configure(systime_t timeout, float brake_current);
void timeout_configure(systime_t timeout, float brake_current, KILL_SW_MODE kill_sw_mode);
void timeout_reset(void);
bool timeout_has_timeout(void);
bool timeout_kill_sw_active(void);
systime_t timeout_get_timeout_msec(void);
void timeout_configure_IWDT(void);
void timeout_configure_IWDT_slowest(void);
bool timeout_had_IWDG_reset(void);
void timeout_feed_WDT(uint8_t index);
float timeout_get_brake_current(void);
KILL_SW_MODE timeout_get_kill_sw_mode(void);
#endif /* TIMEOUT_H_ */