From da96daa767283d32511b6c3e90116c7f75182912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 27 Jul 2020 22:15:01 +0200 Subject: [PATCH] Reworked measurement ADC to use safety controller --- stm-firmware/adc-meas.c | 50 ++++++++++--------- stm-firmware/calibration.c | 23 +++++---- .../include/reflow-controller/adc-meas.h | 14 ------ .../reflow-controller/safety/safety-config.h | 7 +++ .../safety/safety-controller.h | 4 ++ stm-firmware/main.c | 4 +- stm-firmware/safety/safety-controller.c | 30 ++++++++++- stm-firmware/shell.c | 46 ++++------------- 8 files changed, 94 insertions(+), 84 deletions(-) diff --git a/stm-firmware/adc-meas.c b/stm-firmware/adc-meas.c index 254e689..243f3b3 100644 --- a/stm-firmware/adc-meas.c +++ b/stm-firmware/adc-meas.c @@ -24,14 +24,13 @@ #include #include #include +#include static float pt1000_offset; static float pt1000_sens_dev; static bool calibration_active; static float filter_alpha; static volatile float pt1000_res_raw_lf; -static volatile bool filter_ready; -static volatile enum adc_pt1000_error pt1000_error = ADC_PT1000_INACTIVE; static volatile int * volatile streaming_flag_ptr = NULL; static uint32_t filter_startup_cnt; static volatile float adc_pt1000_raw_reading_hf; @@ -73,7 +72,7 @@ static inline void adc_pt1000_disable_adc() ADC_PT1000_PERIPH->CR2 &= ~ADC_CR2_ADON; DMA2_Stream0->CR = 0; - pt1000_error |= ADC_PT1000_INACTIVE; + safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_OFF, MEAS_ADC_SAFETY_FLAG_KEY); rcc_manager_disable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(RCC_APB2ENR_ADC3EN)); rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(ADC_PT1000_PORT_RCC_MASK)); @@ -166,13 +165,13 @@ void adc_pt1000_setup_meas() adc_pt1000_setup_sample_frequency_timer(); - pt1000_error &= ~ADC_PT1000_INACTIVE; + safety_controller_ack_flag_with_key(ERR_FLAG_MEAS_ADC_OFF, MEAS_ADC_SAFETY_FLAG_KEY); } void adc_pt1000_set_moving_average_filter_param(float alpha) { filter_alpha = alpha; - filter_ready = false; + safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_UNSTABLE, MEAS_ADC_SAFETY_FLAG_KEY); filter_startup_cnt = ADC_FILTER_STARTUP_CYCLES; } @@ -181,6 +180,12 @@ void adc_pt1000_set_resistance_calibration(float offset, float sensitivity_devia pt1000_offset = offset; pt1000_sens_dev = sensitivity_deviation; calibration_active = active; + + if (calibration_active) { + safety_controller_report_error_with_key(ERR_FLAG_UNCAL, MEAS_ADC_SAFETY_FLAG_KEY); + } else { + safety_controller_ack_flag_with_key(ERR_FLAG_UNCAL, MEAS_ADC_SAFETY_FLAG_KEY); + } } void adc_pt1000_get_resistance_calibration(float *offset, float *sensitivity_deviation, bool *active) @@ -205,18 +210,23 @@ static inline float adc_pt1000_apply_calibration(float raw_resistance) int adc_pt1000_get_current_resistance(float *resistance) { int ret_val = 0; + bool flag = true; + if (!resistance) return -1001; *resistance = adc_pt1000_apply_calibration(pt1000_res_raw_lf); - if (adc_pt1000_check_error()) { + if (safety_controller_get_flags_by_mask(ERR_FLAG_MEAS_ADC_OFF | ERR_FLAG_MEAS_ADC_OVERFLOW | + ERR_FLAG_MEAS_ADC_WATCHDOG)) { ret_val = -100; goto return_value; } - if (!filter_ready) { + (void)safety_controller_get_flag(ERR_FLAG_MEAS_ADC_UNSTABLE, &flag, false); + + if (flag) { ret_val = 2; goto return_value; } @@ -260,25 +270,15 @@ void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, fl resistance_dest[i] = ADC_TO_RES(raw_source[i]); } -enum adc_pt1000_error adc_pt1000_check_error() -{ - return pt1000_error; -} - -void adc_pt1000_clear_error() -{ - pt1000_error &= ~ADC_PT1000_OVERFLOW & ~ADC_PT1000_WATCHDOG_ERROR; -} - void adc_pt1000_disable() { adc_pt1000_disable_adc(); adc_pt1000_stop_sample_frequency_timer(); adc_pt1000_disable_dma_stream(); - filter_ready = false; pt1000_res_raw_lf = 0.0f; - pt1000_error |= ADC_PT1000_INACTIVE; + safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_OFF, MEAS_ADC_SAFETY_FLAG_KEY); + safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_UNSTABLE, MEAS_ADC_SAFETY_FLAG_KEY); if (streaming_flag_ptr) { *streaming_flag_ptr = -3; @@ -288,8 +288,12 @@ void adc_pt1000_disable() static inline __attribute__((optimize("O3"))) void adc_pt1000_filter(float adc_prefiltered_value) { - if (!filter_ready && --filter_startup_cnt <= 0) - filter_ready = true; + if (filter_startup_cnt > 0) { + filter_startup_cnt--; + if (filter_startup_cnt == 0) { + safety_controller_ack_flag_with_key(ERR_FLAG_MEAS_ADC_UNSTABLE, MEAS_ADC_SAFETY_FLAG_KEY); + } + } pt1000_res_raw_lf = (1.0f-filter_alpha) * pt1000_res_raw_lf + filter_alpha * ADC_TO_RES(adc_prefiltered_value); } @@ -328,7 +332,7 @@ void ADC_IRQHandler(void) if (adc1_sr & ADC_SR_OVR) { ADC_PT1000_PERIPH->SR &= ~ADC_SR_OVR; - pt1000_error |= ADC_PT1000_OVERFLOW; + safety_controller_report_error(ERR_FLAG_MEAS_ADC_OVERFLOW); /* Disable ADC in case of overrrun*/ adc_pt1000_disable(); } @@ -337,7 +341,7 @@ void ADC_IRQHandler(void) ADC_PT1000_PERIPH->SR &= ~ADC_SR_AWD; adc_watchdog_counter++; if (adc_watchdog_counter >= ADC_PT1000_WATCHDOG_SAMPLE_COUNT) - pt1000_error |= ADC_PT1000_WATCHDOG_ERROR; + safety_controller_report_error(ERR_FLAG_MEAS_ADC_WATCHDOG); } } diff --git a/stm-firmware/calibration.c b/stm-firmware/calibration.c index fc70495..489e8f4 100644 --- a/stm-firmware/calibration.c +++ b/stm-firmware/calibration.c @@ -26,6 +26,7 @@ #include #include #include +#include enum calibration_shell_state {CAL_START = 0, CAL_WAIT_RES1, CAL_MEAS_RES1, CAL_WAIT_RES2, CAL_MEAS_RES2}; @@ -121,6 +122,8 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c { (void)arg; (void)len; + bool error_occured; + const enum safety_flag meas_adc_err_mask = ERR_FLAG_MEAS_ADC_OFF | ERR_FLAG_MEAS_ADC_WATCHDOG; /* This stores the current state of the calibration process */ static enum calibration_shell_state cal_state = CAL_START; @@ -139,7 +142,7 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c switch (cal_state) { case CAL_START: /* Clear errors of PT1000 reading */ - adc_pt1000_clear_error(); + safety_controller_ack_flag(ERR_FLAG_MEAS_ADC_WATCHDOG); shellmatta_printf(shell, "Starting calibration: Insert 1000 Ohm calibration resistor and press ENTER\r\n"); cal_state = CAL_WAIT_RES1; ret_val = SHELLMATTA_CONTINUE; @@ -154,7 +157,7 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c cal_state = CAL_MEAS_RES1; ret_val = SHELLMATTA_BUSY; shellmatta_printf(shell, "Measurement...\r\n"); - adc_pt1000_clear_error(); + safety_controller_ack_flag(ERR_FLAG_MEAS_ADC_WATCHDOG); data_buffer = calibration_acquire_data_start(512UL, &flag); break; } else if (stdin_data[i] == '\x03') { @@ -179,8 +182,9 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c cal_state = CAL_MEAS_RES1; } else if (res == 0) { shellmatta_printf(shell, "R=%.2f, Noise peak-peak: %.2f\r\n", mu, dev); - if (adc_pt1000_check_error() != ADC_PT1000_NO_ERR) { - shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error()); + error_occured = safety_controller_get_flags_by_mask(meas_adc_err_mask); + if (error_occured) { + shellmatta_printf(shell, "Error in resistance measurement"); ret_val = SHELLMATTA_OK; cal_state = CAL_START; } else { @@ -189,7 +193,7 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c cal_state = CAL_WAIT_RES2; } } else { - shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error()); + shellmatta_printf(shell, "Error in resistance measurement"); ret_val = SHELLMATTA_OK; cal_state = CAL_START; } @@ -204,7 +208,7 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c cal_state = CAL_MEAS_RES2; ret_val = SHELLMATTA_BUSY; shellmatta_printf(shell, "Measurement...\r\n"); - adc_pt1000_clear_error(); + safety_controller_ack_flag(ERR_FLAG_MEAS_ADC_WATCHDOG); data_buffer = calibration_acquire_data_start(512UL, &flag); break; } else if (stdin_data[i] == '\x03') { @@ -229,8 +233,9 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c cal_state = CAL_MEAS_RES2; } else if (res == 0) { shellmatta_printf(shell, "R=%.2f, Noise peak-peak: %.2f\r\n", mu2, dev2); - if (adc_pt1000_check_error() != ADC_PT1000_NO_ERR) { - shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error()); + error_occured = safety_controller_get_flags_by_mask(meas_adc_err_mask); + if (error_occured) { + shellmatta_printf(shell, "Error in resistance measurement"); ret_val = SHELLMATTA_OK; cal_state = CAL_START; } else { @@ -250,7 +255,7 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c adc_pt1000_set_resistance_calibration(offset, sens_dev, true); } } else { - shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error()); + shellmatta_printf(shell, "Error in resistance measurement"); ret_val = SHELLMATTA_OK; cal_state = CAL_START; } diff --git a/stm-firmware/include/reflow-controller/adc-meas.h b/stm-firmware/include/reflow-controller/adc-meas.h index d2847d2..235b58f 100644 --- a/stm-firmware/include/reflow-controller/adc-meas.h +++ b/stm-firmware/include/reflow-controller/adc-meas.h @@ -90,8 +90,6 @@ */ #define ADC_PT1000_WATCHDOG_SAMPLE_COUNT 25U -enum adc_pt1000_error {ADC_PT1000_NO_ERR= 0, ADC_PT1000_WATCHDOG_ERROR=(1UL<<0), ADC_PT1000_OVERFLOW=(1UL<<1), ADC_PT1000_INACTIVE = (1UL<<2)}; - /** * @brief This function sets up the ADC measurement fo the external PT1000 temperature sensor * @@ -162,18 +160,6 @@ int adc_pt1000_stream_raw_value_to_memory(volatile float *adc_array, uint32_t le void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, float *raw_source, uint32_t count); -/** - * @brief Check if the ADC measurement experienced any kind of error (DMA, Analog Watchdog, etc...) - * - * In case of an error, it may be necessary to call adc_pt1000_setup_meas() again in order to recover from the error - */ -enum adc_pt1000_error adc_pt1000_check_error(); - -/** - * @brief Clear the error status of the PT1000 measurement - */ -void adc_pt1000_clear_error(); - /** * @brief Disable the PT1000 measurement */ diff --git a/stm-firmware/include/reflow-controller/safety/safety-config.h b/stm-firmware/include/reflow-controller/safety/safety-config.h index 073d3f1..74feb90 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-config.h +++ b/stm-firmware/include/reflow-controller/safety/safety-config.h @@ -35,6 +35,7 @@ enum safety_flag { ERR_FLAG_SAFETY_ADC = (1<<9), ERR_FLAG_SYSTICK = (1<<10), ERR_FLAG_WTCHDG_FIRED = (1<<11), + ERR_FLAG_UNCAL = (1<<12), }; enum timing_monitor { @@ -80,4 +81,10 @@ enum analog_value_monitor { #define SAFETY_ADC_TEMP_LOW_LIM (0.0f) #define SAFETY_ADC_TEMP_HIGH_LIM (65.0f) + +/** + * @brief Key used to lock the safefety flags from external ack'ing + */ +#define MEAS_ADC_SAFETY_FLAG_KEY 0xe554dac3UL + #endif /* __SAFETY_CONFIG_H__ */ diff --git a/stm-firmware/include/reflow-controller/safety/safety-controller.h b/stm-firmware/include/reflow-controller/safety/safety-controller.h index cfe29fb..cd462b6 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-controller.h +++ b/stm-firmware/include/reflow-controller/safety/safety-controller.h @@ -55,6 +55,8 @@ int safety_controller_handle(); int safety_controller_report_error(enum safety_flag flag); +int safety_controller_report_error_with_key(enum safety_flag flag, uint32_t key); + void safety_controller_report_timing(enum timing_monitor monitor); void safety_controller_report_analog_value(enum analog_value_monitor monitor, float value); @@ -69,6 +71,8 @@ int safety_controller_ack_flag(enum safety_flag flag); int safety_controller_ack_flag_with_key(enum safety_flag flag, uint32_t key); +bool safety_controller_get_flags_by_mask(enum safety_flag mask); + #endif /* __SAFETY_CONTROLLER_H__ */ /** @} */ diff --git a/stm-firmware/main.c b/stm-firmware/main.c index 292172c..caf9c97 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -161,7 +161,7 @@ static inline void setup_system(void) setup_unused_pins(); - + safety_controller_init(); } static void handle_shell_uart_input(shellmatta_handle_t shell_handle) @@ -219,6 +219,8 @@ int main(void) menu_wait_request = reflow_menu_handle(); handle_shell_uart_input(shell_handle); + + safety_controller_handle(); oven_driver_apply_power_level(); if (menu_wait_request) diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index 7ea1a4c..94e148a 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -83,6 +83,7 @@ static volatile struct error_flag flags[] = { ERR_FLAG_ENTRY(ERR_FLAG_SAFETY_ADC, true), ERR_FLAG_ENTRY(ERR_FLAG_SYSTICK, true), ERR_FLAG_ENTRY(ERR_FLAG_WTCHDG_FIRED, true), + ERR_FLAG_ENTRY(ERR_FLAG_UNCAL, false), }; static volatile struct timing_mon timings[] = { @@ -183,6 +184,11 @@ static void safety_controller_process_checks() } int safety_controller_report_error(enum safety_flag flag) +{ + return safety_controller_report_error_with_key(flag, 0x0UL); +} + +int safety_controller_report_error_with_key(enum safety_flag flag, uint32_t key) { uint32_t i; int ret = -1; @@ -190,6 +196,7 @@ int safety_controller_report_error(enum safety_flag flag) for (i = 0; i < COUNT_OF(flags); i++) { if (flags[i].flag & flag) { flags[i].error_state = true; + flags[i].key = key; ret = 0; } } @@ -239,8 +246,14 @@ void safety_controller_report_analog_value(enum analog_value_monitor monitor, fl void safety_controller_init() { + + /* Init default flag states */ + safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_OFF | ERR_FLAG_MEAS_ADC_UNSTABLE, + MEAS_ADC_SAFETY_FLAG_KEY); + safety_adc_init(); watchdog_setup(WATCHDOG_PRESCALER); + } static void safety_controller_check_stack() @@ -400,7 +413,7 @@ int safety_controller_ack_flag_with_key(enum safety_flag flag, uint32_t key) found_flag = find_error_flag(flag); if (found_flag) { - if (!found_flag->persistent && found_flag->key == key) { + if (!found_flag->persistent && (found_flag->key == key || !key)) { found_flag->error_state = false; ret = 0; } else { @@ -411,4 +424,19 @@ int safety_controller_ack_flag_with_key(enum safety_flag flag, uint32_t key) return ret; } +bool safety_controller_get_flags_by_mask(enum safety_flag mask) +{ + uint32_t i; + bool ret = false; + + for (i = 0; i < COUNT_OF(flags); i++) { + if (flags[i].flag & mask) { + ret = true; + break; + } + } + + return ret; +} + /** @} */ diff --git a/stm-firmware/shell.c b/stm-firmware/shell.c index f3b00ab..fa4339d 100644 --- a/stm-firmware/shell.c +++ b/stm-firmware/shell.c @@ -128,7 +128,6 @@ static shellmatta_retCode_t shell_cmd_pt1000_res(const shellmatta_handle_t han (void)length; float resistance; int pt1000_status; - enum adc_pt1000_error pt1000_flags; char display_status[100]; float temp; int temp_conv_status; @@ -141,13 +140,7 @@ static shellmatta_retCode_t shell_cmd_pt1000_res(const shellmatta_handle_t han if (pt1000_status == 2) { strcat(display_status, " UNSTABLE "); } else if (pt1000_status) { - pt1000_flags = adc_pt1000_check_error(); - if (pt1000_flags & ADC_PT1000_INACTIVE) - strcat(display_status, " DEACTIVATED "); - else if (pt1000_flags & ADC_PT1000_WATCHDOG_ERROR) - strcat(display_status, " WATCHDOG "); - else if (pt1000_flags & ADC_PT1000_OVERFLOW) - strcat(display_status, " OVERFLOW "); + strcpy(display_status, "ERROR"); } else { strcpy(display_status, "VALID"); } @@ -171,17 +164,6 @@ static shellmatta_retCode_t shell_cmd_pt1000_res(const shellmatta_handle_t han return SHELLMATTA_OK; } -static shellmatta_retCode_t shell_cmd_clear_error_status(const shellmatta_handle_t handle, const char *arguments, - uint32_t length) -{ - (void)arguments; - (void)length; - (void)handle; - - adc_pt1000_clear_error(); - - return SHELLMATTA_OK; -} static shellmatta_retCode_t shell_cmd_uptime(const shellmatta_handle_t handle, const char *arguments, @@ -401,21 +383,13 @@ static shellmatta_cmd_t cmd[14] = { .cmdFct = shell_cmd_pt1000_res_loop, .next = &cmd[3], }, - { - .cmd = "pt1000-clear-error", - .cmdAlias = "pt-clear", - .helpText = "Clear error status of PT1000 reading", - .usageText = NULL, - .cmdFct = shell_cmd_clear_error_status, - .next = &cmd[4], - }, { .cmd = "digio-get", .cmdAlias = "dg", .helpText = "Read all digital input/output ports", .usageText = NULL, .cmdFct = shell_cmd_digio_get, - .next = &cmd[5], + .next = &cmd[4], }, { .cmd = "digio-set", @@ -423,7 +397,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "Set DIGIO Port", .usageText = "digio-set ", .cmdFct = shell_cmd_digio_set, - .next = &cmd[6], + .next = &cmd[5], }, { .cmd = "uptime", @@ -431,7 +405,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "Get uptime in seconds", .usageText = "", .cmdFct = shell_cmd_uptime, - .next = &cmd[7], + .next = &cmd[6], }, { .cmd = "calibrate", @@ -439,7 +413,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "Calibrate resistance measurement", .usageText = "", .cmdFct = shell_cmd_cal, - .next = &cmd[8], + .next = &cmd[7], }, { .cmd = "meminfo", @@ -447,7 +421,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "Get information about memory usage", .usageText = "", .cmdFct = shell_meminfo, - .next = &cmd[9], + .next = &cmd[8], }, { .cmd = "rotary-encoder", @@ -455,7 +429,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "Get current rotary encoder value", .usageText = "", .cmdFct = shell_cmd_rot, - .next = &cmd[10], + .next = &cmd[9], }, { .cmd = "ls", @@ -463,7 +437,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "List filesystem contents", .usageText = "", .cmdFct = shell_cmd_ls, - .next = &cmd[11], + .next = &cmd[10], }, { .cmd = "reset", @@ -471,7 +445,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "Reset controller", .usageText = "reset", .cmdFct = shell_cmd_reset, - .next = &cmd[12], + .next = &cmd[11], }, { .cmd = "cat", @@ -479,7 +453,7 @@ static shellmatta_cmd_t cmd[14] = { .helpText = "Print file contents", .usageText = "cat ", .cmdFct = shell_cmd_cat, - .next = &cmd[13], + .next = &cmd[12], }, { .cmd = "safety-adc",