From 7c6205d20ab71014abc051b25d787f9921ad83b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Fri, 1 Jan 2021 19:48:53 +0100 Subject: [PATCH] Add supply voltage monitor to safety adc and safety controller --- .../periph-config/safety-adc-hwcfg.h | 12 ++++++++-- .../reflow-controller/safety/safety-adc.h | 1 + .../reflow-controller/safety/safety-config.h | 11 +++++++--- stm-firmware/safety/safety-adc.c | 22 +++++++++++++++++-- stm-firmware/safety/safety-controller.c | 17 +++++++++++++- 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h b/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h index a3ab478..e2e1e97 100644 --- a/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h +++ b/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h @@ -49,6 +49,12 @@ */ #define INT_REF_CHANNEL_NUM (17) +#define SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_CHANNEL_NUM (15) +#define SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PIN (5) +#define SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT GPIOC +#define SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT_RCC_MASK RCC_AHB1ENR_GPIOCEN + + /** * @brief Nominal value of the internal reference voltage. * @@ -77,7 +83,7 @@ * @brief Number of channels to handle for the SAFETY ADC. * @note The maximum amount of channels is limited to 16 */ -#define SAFETY_ADC_NUM_OF_CHANNELS 8 +#define SAFETY_ADC_NUM_OF_CHANNELS 12 /** * @brief Channel numbers to sample with the SAFETY ADC @@ -91,7 +97,9 @@ * @warning Safety controller expects the current measurment list. If you change it, check @ref safety_controller_handle_safety_adc */ #define SAFETY_ADC_CHANNELS TEMP_CHANNEL_NUM, TEMP_CHANNEL_NUM, TEMP_CHANNEL_NUM, TEMP_CHANNEL_NUM, \ - INT_REF_CHANNEL_NUM, INT_REF_CHANNEL_NUM, INT_REF_CHANNEL_NUM, INT_REF_CHANNEL_NUM + INT_REF_CHANNEL_NUM, INT_REF_CHANNEL_NUM, INT_REF_CHANNEL_NUM, INT_REF_CHANNEL_NUM, \ + SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_CHANNEL_NUM, SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_CHANNEL_NUM, \ + SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_CHANNEL_NUM, SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_CHANNEL_NUM /* Check the channel count of the safety ADC */ diff --git a/stm-firmware/include/reflow-controller/safety/safety-adc.h b/stm-firmware/include/reflow-controller/safety/safety-adc.h index 3860407..8755109 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-adc.h +++ b/stm-firmware/include/reflow-controller/safety/safety-adc.h @@ -35,6 +35,7 @@ enum safety_adc_meas_channel { SAFETY_ADC_MEAS_VREF, /**< @brief Internal reference voltage @note This will not output the internal reference voltage but the recalculated external voltage! */ SAFETY_ADC_MEAS_TEMP, /**< @brief Internal temperature sensor */ + SAFETY_ADC_MEAS_SUPPLY, /**< @brief Supply voltage */ }; /** diff --git a/stm-firmware/include/reflow-controller/safety/safety-config.h b/stm-firmware/include/reflow-controller/safety/safety-config.h index 4c63a8b..be274c4 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-config.h +++ b/stm-firmware/include/reflow-controller/safety/safety-config.h @@ -52,6 +52,7 @@ enum safety_flag { ERR_FLAG_TIMING_MAIN_LOOP = (1<<14), ERR_FLAG_SAFETY_MEM_CORRUPT = (1<<15), ERR_FLAG_SAFETY_TAB_CORRUPT = (1<<16), + ERR_FLAG_AMON_SUPPLY_VOLT = (1<<17), }; /** @@ -76,6 +77,7 @@ enum timing_monitor { enum analog_value_monitor { ERR_AMON_VREF = (1<<0), ERR_AMON_UC_TEMP = (1<<1), + ERR_AMON_SUPPLY_VOLT = (1<<2), }; #define ERR_FLAG_ENTRY(errflag) {.name=#errflag, .flag = (errflag), .error_state = false, .error_state_inv = true, .key = 0UL, .weight = NULL, .persistency = NULL} @@ -117,7 +119,8 @@ enum analog_value_monitor { #define SAFETY_ADC_VREF_TOL_MVOLT (100.0f) #define SAFETY_ADC_TEMP_LOW_LIM (0.0f) #define SAFETY_ADC_TEMP_HIGH_LIM (65.0f) - +#define SAFETY_ADC_SUPPLY_MVOLT (3300.0f) +#define SAFETY_ADC_SUPPLY_TOL_MVOLT (150.0f) #define SAFETY_EXT_WATCHDOG_PORT GPIOD #define SAFETY_EXT_WATCHDOG_RCC_MASK RCC_AHB1ENR_GPIODEN @@ -149,7 +152,8 @@ enum analog_value_monitor { ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_DEBUG, true), \ ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_TIMING_MAIN_LOOP, true), \ ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_SAFETY_MEM_CORRUPT, true), \ - ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT, true), + ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT, true), \ + ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_AMON_SUPPLY_VOLT, false), \ #define SAFETY_CONFIG_DEFAULT_WEIGHTS ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_MEAS_ADC_OFF, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ @@ -169,6 +173,7 @@ enum analog_value_monitor { ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_DEBUG, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_TIMING_MAIN_LOOP, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_SAFETY_MEM_CORRUPT, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ - ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), + ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ + ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_AMON_SUPPLY_VOLT, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ #endif /* __SAFETY_CONFIG_H__ */ diff --git a/stm-firmware/safety/safety-adc.c b/stm-firmware/safety/safety-adc.c index dedb00a..8e3b4e1 100644 --- a/stm-firmware/safety/safety-adc.c +++ b/stm-firmware/safety/safety-adc.c @@ -27,6 +27,7 @@ #include #include #include +#include static const uint8_t safety_adc_channels[SAFETY_ADC_NUM_OF_CHANNELS] = {SAFETY_ADC_CHANNELS}; static volatile uint8_t safety_adc_conversion_complete; @@ -35,16 +36,25 @@ static volatile uint16_t safety_adc_conversions[SAFETY_ADC_NUM_OF_CHANNELS]; void safety_adc_init(void) { + enum hw_revision hw_rev; int i; + hw_rev = get_pcb_hardware_version(); + rcc_manager_enable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(SAFETY_ADC_ADC_RCC_MASK)); rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA2EN)); + if (hw_rev != HW_REV_V1_2) { + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT_RCC_MASK)); + SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT->MODER &= MODER_DELETE(SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PIN); + SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT->MODER |= ANALOG(SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PIN); + } + /* Enable temperature and VREFINT measurement */ ADC->CCR |= ADC_CCR_TSVREFE; - /* Set sample time for channels 16 and 17 */ - SAFETY_ADC_ADC_PERIPHERAL->SMPR1 |= ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16; + /* Set sample time for channels 16 and 17 and 15 */ + SAFETY_ADC_ADC_PERIPHERAL->SMPR1 |= ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16 | ADC_SMPR1_SMP15; /* Standard sequence. Measure all channels in one sequence */ SAFETY_ADC_ADC_PERIPHERAL->SQR1 = (SAFETY_ADC_NUM_OF_CHANNELS - 1) << 20 ; @@ -93,6 +103,7 @@ void safety_adc_deinit(void) float safety_adc_convert_channel(enum safety_adc_meas_channel channel, uint16_t analog_value) { float converted_val; + enum hw_revision hw_rev; switch (channel) { case SAFETY_ADC_MEAS_TEMP: @@ -102,6 +113,13 @@ float safety_adc_convert_channel(enum safety_adc_meas_channel channel, uint16_t case SAFETY_ADC_MEAS_VREF: converted_val = (SAFETY_ADC_INT_REF_MV * 4095.0f) / (float)analog_value; break; + case SAFETY_ADC_MEAS_SUPPLY: + hw_rev = get_pcb_hardware_version(); + if (hw_rev >= HW_REV_V1_3) + converted_val = ((float)analog_value) / 4095.0f * 2500.0f * 2.0f; + else + converted_val = 3300.0f; + break; default: /* Generate NaN value as default return */ converted_val = 0.0f / 0.0f; diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index ec40416..53b539d 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -111,6 +111,7 @@ static volatile struct error_flag IN_SECTION(.ccm.data) flags[] = { ERR_FLAG_ENTRY(ERR_FLAG_TIMING_MAIN_LOOP), ERR_FLAG_ENTRY(ERR_FLAG_SAFETY_MEM_CORRUPT), ERR_FLAG_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT), + ERR_FLAG_ENTRY(ERR_FLAG_AMON_SUPPLY_VOLT), }; static volatile struct timing_mon IN_SECTION(.ccm.data) timings[] = { @@ -124,7 +125,10 @@ static volatile struct analog_mon IN_SECTION(.ccm.data) analog_mons[] = { ANA_MON_ENTRY(ERR_AMON_VREF, SAFETY_ADC_VREF_MVOLT - SAFETY_ADC_VREF_TOL_MVOLT, SAFETY_ADC_VREF_MVOLT + SAFETY_ADC_VREF_TOL_MVOLT, ERR_FLAG_AMON_VREF), ANA_MON_ENTRY(ERR_AMON_UC_TEMP, SAFETY_ADC_TEMP_LOW_LIM, SAFETY_ADC_TEMP_HIGH_LIM, - ERR_FLAG_AMON_UC_TEMP), + ERR_FLAG_AMON_UC_TEMP), + ANA_MON_ENTRY(ERR_AMON_SUPPLY_VOLT, SAFETY_ADC_SUPPLY_MVOLT - SAFETY_ADC_SUPPLY_TOL_MVOLT, + SAFETY_ADC_SUPPLY_MVOLT + SAFETY_ADC_SUPPLY_TOL_MVOLT, + ERR_FLAG_AMON_SUPPLY_VOLT), }; static const struct safety_weight default_flag_weights[] = { SAFETY_CONFIG_DEFAULT_WEIGHTS }; @@ -361,6 +365,9 @@ static void safety_controller_process_monitor_checks() amon_state = safety_controller_get_analog_mon_value(ERR_AMON_UC_TEMP, &amon_value); if (amon_state != ANALOG_MONITOR_OK) safety_controller_report_error(ERR_FLAG_AMON_UC_TEMP); + amon_state = safety_controller_get_analog_mon_value(ERR_AMON_SUPPLY_VOLT, &amon_value); + if (amon_state != ANALOG_MONITOR_OK) + safety_controller_report_error(ERR_FLAG_AMON_SUPPLY_VOLT); } safety_controller_process_active_timing_mons(); @@ -582,6 +589,14 @@ static void safety_controller_handle_safety_adc() analog_value = safety_adc_convert_channel(SAFETY_ADC_MEAS_VREF, (uint16_t)sum); safety_controller_report_analog_value(ERR_AMON_VREF, analog_value); + + /* Compute supply voltage reading */ + sum = channels[8] + channels[9] + channels[10] + channels[11]; + sum /= 4; + analog_value = safety_adc_convert_channel(SAFETY_ADC_MEAS_SUPPLY, (uint16_t)sum); + + safety_controller_report_analog_value(ERR_AMON_SUPPLY_VOLT, analog_value); + last_result_timestamp = systick_get_global_tick(); safety_controller_report_timing(ERR_TIMING_SAFETY_ADC); }