Thor300: robust shutdown implementation, remove AO variant

shutdown can now only be triggered by a long-press
-500ms of button press triggers shutdown provided erpm < 100
-above 100 erpm the button must be held for 3 seconds to force shutdown

Actual shutdown happens on release of the button

Signed-off-by: Dado Mista <dadomista@gmail.com>
This commit is contained in:
Dado Mista 2024-06-26 09:28:04 -07:00
parent 898ec45cfc
commit 02c5944309
2 changed files with 126 additions and 56 deletions

View File

@ -1,29 +0,0 @@
/*
Copyright 2022 Benjamin Vedder benjamin@vedder.se
This file is part of the VESC firmware.
The VESC firmware is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The VESC firmware is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HW_Thor300_AO_H_
#define HW_Thor300_AO_H_
#define HW_NAME "Thor300_AO"
#include "hw_Thor300_core.h"
#define ALWAYS_ON 1
#endif

View File

@ -23,13 +23,19 @@
#include "stm32f4xx_conf.h"
#include "utils_math.h"
#include <math.h>
#include "terminal.h"
#include "commands.h"
#include "mc_interface.h"
// Variables
static volatile bool i2c_running = false;
static mutex_t shutdown_mutex;
static float bt_diff = 0.0;
static int pressed_time = 0;
static float bt_lastval = 0.0;
static float bt_unpressed = 0.0;
static bool will_poweroff = false;
static bool force_poweroff = false;
static unsigned int bt_hold_counter = 0;
// I2C configuration
static const I2CConfig i2cfg = {
@ -38,10 +44,13 @@ static const I2CConfig i2cfg = {
STD_DUTY_CYCLE
};
// Private functions
static void terminal_button_test(int argc, const char **argv);
void hw_init_gpio(void) {
chMtxObjectInit(&shutdown_mutex);
// GPIO clock enable
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
@ -109,7 +118,14 @@ void hw_init_gpio(void) {
palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 4, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 5, PAL_MODE_INPUT_ANALOG);
terminal_register_command_callback(
"test_button",
"Try sampling the shutdown button",
0,
terminal_button_test);
}
void hw_setup_adc_channels(void) {
// ADC1 regular channels
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_15Cycles);
@ -241,38 +257,113 @@ void hw_try_restore_i2c(void) {
}
}
#define RISING_EDGE_THRESHOLD 0.09
#define TIME_500MS 50
#define TIME_3S 300
#define ERPM_THRESHOLD 100
/**
* hw_sample_shutdown_button - return false if shutdown is requested, true otherwise
*
* Behavior: after determining the unpressed level, look for rising edges or values
* that are clearly above the unpressed level (2 x Threshold higher), triggering a counter.
*
* Once triggered, the counter keeps incrementing as long as the level is 2 x Threshold higher
* than the normal/unpressed value, otherwise it gets reset to zero.
*
* Once the counter reaches the threshold the button is considered pressed, provided that
* the erpm is below 100.
* Shutdown actually happens on the falling edge when the press is over.
*
* If the motor is spinning faster, then a 3s press is required.
* Again, shutdown happens on the falling edge.
*
* Normal shutdown time: 0.5s
* Emergency shutdown time: 3.0s
*/
bool hw_sample_shutdown_button(void) {
chMtxLock(&shutdown_mutex);
float newval = ADC_VOLTS(ADC_IND_SHUTDOWN);
chMtxUnlock(&shutdown_mutex);
if (bt_lastval == 0) {
bt_lastval = newval;
return true;
}
bt_diff = (newval - bt_lastval);
#ifdef ALWAYS_ON
return true;
#endif
bool is_steady = fabsf(bt_diff) < 0.02; // filter out noise above 20mV
bool is_rising_edge = (bt_diff > RISING_EDGE_THRESHOLD);
chMtxLock(&shutdown_mutex);
bt_diff = (ADC_VOLTS(ADC_IND_SHUTDOWN));
bt_diff = (bt_diff + ADC_VOLTS(ADC_IND_SHUTDOWN))/2;
chThdSleep(1);
bt_diff = (bt_diff + ADC_VOLTS(ADC_IND_SHUTDOWN))/2;
chThdSleep(1);
bt_diff = (bt_diff + ADC_VOLTS(ADC_IND_SHUTDOWN))/2;
chMtxUnlock(&shutdown_mutex);
bt_lastval = newval;
if(bt_diff > 2.25){
pressed_time += 12;
return true;
}else{
if(pressed_time > 1000){
pressed_time = 0;
return false;
}else{
pressed_time = 0;
return true;
}
}
if (bt_unpressed == 0.0) {
// initializing bt_unpressed
if (is_steady) {
bt_unpressed = newval;
}
// return true regardless (this happens only after boot)
return true;
}
return pressed_time < 1000 ;
if (will_poweroff) {
if (!force_poweroff && (fabsf(mc_interface_get_rpm()) > ERPM_THRESHOLD)) {
will_poweroff = false;
bt_hold_counter = 0;
return true;
}
// Now we look for a falling edge to shut down
if ((bt_diff < -RISING_EDGE_THRESHOLD) || (newval < bt_unpressed + RISING_EDGE_THRESHOLD / 2)) {
bt_hold_counter++;
return false;
}
return true;
}
if (bt_hold_counter == 0) {
if (is_rising_edge) {
// trigger by edge and by level!
bt_hold_counter = 1;
}
else {
if (is_steady && (newval < bt_unpressed + RISING_EDGE_THRESHOLD / 2)) {
// pickup drifts due to temperature
bt_unpressed = bt_unpressed * 0.9 + newval * 0.1;
}
}
}
else {
// we've had a rising edge and are now checking for a steady hold
if (newval > bt_unpressed + RISING_EDGE_THRESHOLD * 1.5) {
bt_hold_counter++;
if (bt_hold_counter > TIME_500MS) {
if (fabsf(mc_interface_get_rpm()) < ERPM_THRESHOLD) {
// after 150ms, power-down is triggered by the falling edge (releasing the button)
will_poweroff = true;
bt_hold_counter = 0;
}
else {
if (bt_hold_counter > TIME_3S) {
// Emergency Power-Down
will_poweroff = true;
force_poweroff = true;
bt_hold_counter = 0;
return true;
}
}
}
}
else {
// press is too short, abort
bt_hold_counter = 0;
}
}
return true;
}
float hw_Thor_get_temp(void) {
float t1 = (1.0 / ((logf(NTC_RES(ADC_Value[ADC_IND_TEMP_MOS]) / 10000.0) / 3380.0) + (1.0 / 298.15)) - 273.15);
float t3 = (1.0 / ((logf(NTC_RES(ADC_Value[ADC_IND_TEMP_MOS_3]) / 10000.0) / 3380.0) + (1.0 / 298.15)) - 273.15);
@ -286,5 +377,13 @@ float hw_Thor_get_temp(void) {
return res;
}
static void terminal_button_test(int argc, const char **argv) {
(void)argc;
(void)argv;
for (int i = 0;i < 40;i++) {
commands_printf("BT: %d:%d [%.2fV], %.2fV, %.2fV, OFF=%d", HW_SAMPLE_SHUTDOWN(), bt_hold_counter,
(double)bt_diff, (double)bt_unpressed, (double)bt_lastval, (int)will_poweroff);
chThdSleepMilliseconds(100);
}
}