Add safety management in PID handler and main loop
This commit is contained in:
parent
a33154b2d0
commit
cbd28f9a12
@ -25,9 +25,28 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <reflow-controller/pid-controller.h>
|
#include <reflow-controller/pid-controller.h>
|
||||||
|
|
||||||
|
enum oven_pid_error_report {
|
||||||
|
OVEN_PID_NO_ERROR = 0,
|
||||||
|
OVEN_PID_ERR_PT1000_ADC_WATCHDOG = (1<<0),
|
||||||
|
OVEN_PID_ERR_PT1000_ADC_OFF = (1<<1),
|
||||||
|
OVEN_PID_ERR_PT1000_OTHER = (1<<2),
|
||||||
|
OVEN_PID_ERR_VREF_TOL = (1<<3),
|
||||||
|
OVEN_PID_ERR_OVERTEMP = (1<<4),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct oven_pid_errors {
|
||||||
|
bool generic_error;
|
||||||
|
bool pt1000_adc_watchdog;
|
||||||
|
bool pt1000_adc_off;
|
||||||
|
bool pt1000_other;
|
||||||
|
bool vref_tol;
|
||||||
|
bool controller_overtemp;
|
||||||
|
};
|
||||||
|
|
||||||
struct oven_pid_status {
|
struct oven_pid_status {
|
||||||
bool active;
|
bool active;
|
||||||
bool aborted;
|
bool aborted;
|
||||||
|
struct oven_pid_errors error_flags;
|
||||||
float target_temp;
|
float target_temp;
|
||||||
float current_temp;
|
float current_temp;
|
||||||
uint64_t timestamp_last_run;
|
uint64_t timestamp_last_run;
|
||||||
@ -41,11 +60,11 @@ void oven_driver_disable(void);
|
|||||||
|
|
||||||
void oven_pid_init(struct pid_controller *controller_to_copy);
|
void oven_pid_init(struct pid_controller *controller_to_copy);
|
||||||
|
|
||||||
void oven_pid_handle(float target_temp, float current_temp);
|
void oven_pid_handle(float target_temp);
|
||||||
|
|
||||||
void oven_pid_stop();
|
void oven_pid_stop();
|
||||||
|
|
||||||
void oven_pid_report_error(void);
|
void oven_pid_report_error(enum oven_pid_error_report report);
|
||||||
|
|
||||||
const struct oven_pid_status *oven_pid_get_status(void);
|
const struct oven_pid_status *oven_pid_get_status(void);
|
||||||
|
|
||||||
|
@ -24,11 +24,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define SAFETY_ADC_FRAC_BITS (8)
|
#define SAFETY_ADC_VREF_MVOLT (2500.0f)
|
||||||
#define SAFETY_ADC_VREF_VOLT (2.5)
|
#define SAFETY_ADC_VREF_TOL_MVOLT (100.0f)
|
||||||
#define SAFETY_ADC_VREF_TOL (0.25)
|
#define SAFETY_ADC_TEMP_LOW_LIM (0.0f)
|
||||||
#define SAFETY_ADC_VREF_INT ()
|
#define SAFETY_ADC_TEMP_HIGH_LIM (65.0f)
|
||||||
|
|
||||||
|
|
||||||
enum safety_adc_meas_channel {SAFETY_ADC_MEAS_VREF, SAFETY_ADC_MEAS_TEMP};
|
enum safety_adc_meas_channel {SAFETY_ADC_MEAS_VREF, SAFETY_ADC_MEAS_TEMP};
|
||||||
enum safety_adc_check_result {
|
enum safety_adc_check_result {
|
||||||
|
@ -198,13 +198,17 @@ static void zero_ccm_ram(void)
|
|||||||
ptr[i] = 0UL;
|
ptr[i] = 0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile bool error_state = false;
|
||||||
|
volatile enum safety_adc_check_result safety_adc_status = SAFETY_ADC_CHECK_OK;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
bool sd_card_mounted = false;
|
bool sd_card_mounted = false;
|
||||||
shellmatta_handle_t shell_handle;
|
shellmatta_handle_t shell_handle;
|
||||||
int menu_wait_request;
|
int menu_wait_request;
|
||||||
uint64_t quarter_sec_timestamp = 0ULL;
|
uint64_t quarter_sec_timestamp = 0ULL;
|
||||||
enum safety_adc_check_result safety_adc_status;
|
const struct oven_pid_status *pid_status;
|
||||||
|
enum adc_pt1000_error pt1000_status;
|
||||||
|
|
||||||
zero_ccm_ram();
|
zero_ccm_ram();
|
||||||
setup_system();
|
setup_system();
|
||||||
@ -215,14 +219,46 @@ int main()
|
|||||||
while (1) {
|
while (1) {
|
||||||
sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted);
|
sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted);
|
||||||
|
|
||||||
|
pid_status = oven_pid_get_status();
|
||||||
|
|
||||||
if(systick_ticks_have_passed(quarter_sec_timestamp, 250)) {
|
if(systick_ticks_have_passed(quarter_sec_timestamp, 250)) {
|
||||||
safety_adc_status = handle_safety_adc();
|
safety_adc_status = handle_safety_adc();
|
||||||
quarter_sec_timestamp = systick_get_global_tick();
|
quarter_sec_timestamp = systick_get_global_tick();
|
||||||
|
|
||||||
|
if (safety_adc_status & SAFETY_ADC_CHECK_TEMP_LOW || safety_adc_status & SAFETY_ADC_CHECK_TEMP_HIGH) {
|
||||||
|
oven_pid_report_error(OVEN_PID_ERR_OVERTEMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safety_adc_status & SAFETY_ADC_CHECK_VREF_LOW || safety_adc_status & SAFETY_ADC_CHECK_VREF_HIGH) {
|
||||||
|
oven_pid_report_error(OVEN_PID_ERR_VREF_TOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safety_adc_status & SAFETY_ADC_INTERNAL_ERROR) {
|
||||||
|
oven_pid_report_error(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error_state) {
|
||||||
|
led_set(1, !led_get(1));
|
||||||
|
} else {
|
||||||
|
led_set(1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pt1000_status = adc_pt1000_check_error();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
error_state = pid_status->aborted | !!safety_adc_status | !!pt1000_status;
|
||||||
|
|
||||||
|
menu_wait_request = reflow_menu_handle();
|
||||||
|
|
||||||
|
/* Deactivate oven output in case of error! */
|
||||||
|
if (!pid_status->active || pid_status->aborted || error_state) {
|
||||||
|
oven_pid_stop();
|
||||||
|
oven_driver_set_power(0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_shell_uart_input(shell_handle);
|
handle_shell_uart_input(shell_handle);
|
||||||
|
|
||||||
menu_wait_request = reflow_menu_handle();
|
|
||||||
if (menu_wait_request)
|
if (menu_wait_request)
|
||||||
__WFI();
|
__WFI();
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <reflow-controller/periph-config/oven-driver-hwcfg.h>
|
#include <reflow-controller/periph-config/oven-driver-hwcfg.h>
|
||||||
#include <stm-periph/clock-enable-manager.h>
|
#include <stm-periph/clock-enable-manager.h>
|
||||||
#include <reflow-controller/systick.h>
|
#include <reflow-controller/systick.h>
|
||||||
|
#include <reflow-controller/adc-meas.h>
|
||||||
|
#include <reflow-controller/temp-converter.h>
|
||||||
|
|
||||||
static struct pid_controller oven_pid;
|
static struct pid_controller oven_pid;
|
||||||
|
|
||||||
@ -76,29 +78,70 @@ void oven_pid_init(struct pid_controller *controller_to_copy)
|
|||||||
oven_pid.output_sat_max = 100.0f;
|
oven_pid.output_sat_max = 100.0f;
|
||||||
oven_pid_current_status.timestamp_last_run = 0ULL;
|
oven_pid_current_status.timestamp_last_run = 0ULL;
|
||||||
oven_pid_current_status.active = true;
|
oven_pid_current_status.active = true;
|
||||||
|
oven_pid_current_status.error_flags.vref_tol = false;
|
||||||
|
oven_pid_current_status.error_flags.pt1000_other = false;
|
||||||
|
oven_pid_current_status.error_flags.generic_error = false;
|
||||||
|
oven_pid_current_status.error_flags.pt1000_adc_off = false;
|
||||||
|
oven_pid_current_status.error_flags.controller_overtemp = false;
|
||||||
|
oven_pid_current_status.error_flags.pt1000_adc_watchdog = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void oven_pid_handle(float target_temp, float current_temp)
|
void oven_pid_handle(float target_temp)
|
||||||
{
|
{
|
||||||
float pid_out;
|
float pid_out;
|
||||||
|
float current_temp;
|
||||||
|
int resistance_status;
|
||||||
|
enum adc_pt1000_error pt1000_error;
|
||||||
|
|
||||||
if (oven_pid_current_status.active) {
|
if (oven_pid_current_status.active && !oven_pid_current_status.aborted) {
|
||||||
if (systick_ticks_have_passed(oven_pid_current_status.timestamp_last_run,
|
if (systick_ticks_have_passed(oven_pid_current_status.timestamp_last_run,
|
||||||
(uint64_t)(oven_pid.sample_period * 1000))) {
|
(uint64_t)(oven_pid.sample_period * 1000))) {
|
||||||
|
|
||||||
|
resistance_status = adc_pt1000_get_current_resistance(¤t_temp);
|
||||||
|
if (resistance_status < 0) {
|
||||||
|
oven_driver_set_power(0);
|
||||||
|
pt1000_error = adc_pt1000_check_error();
|
||||||
|
if (pt1000_error & ADC_PT1000_WATCHDOG_ERROR)
|
||||||
|
oven_pid_report_error(OVEN_PID_ERR_PT1000_ADC_WATCHDOG);
|
||||||
|
if (pt1000_error & ADC_PT1000_INACTIVE)
|
||||||
|
oven_pid_report_error(OVEN_PID_ERR_PT1000_ADC_OFF);
|
||||||
|
if (pt1000_error & ADC_PT1000_OVERFLOW)
|
||||||
|
oven_pid_report_error(OVEN_PID_ERR_PT1000_OTHER);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)temp_converter_convert_resistance_to_temp(current_temp, ¤t_temp);
|
||||||
|
|
||||||
pid_out = pid_sample(&oven_pid, target_temp - current_temp);
|
pid_out = pid_sample(&oven_pid, target_temp - current_temp);
|
||||||
oven_driver_set_power((uint8_t)pid_out);
|
oven_driver_set_power((uint8_t)pid_out);
|
||||||
oven_pid_current_status.timestamp_last_run = systick_get_global_tick();
|
oven_pid_current_status.timestamp_last_run = systick_get_global_tick();
|
||||||
oven_pid_current_status.active = true;
|
|
||||||
oven_pid_current_status.target_temp = target_temp;
|
oven_pid_current_status.target_temp = target_temp;
|
||||||
oven_pid_current_status.current_temp = current_temp;
|
oven_pid_current_status.current_temp = current_temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oven_pid_report_error()
|
void oven_pid_report_error(enum oven_pid_error_report report)
|
||||||
{
|
{
|
||||||
|
struct oven_pid_errors *e = &oven_pid_current_status.error_flags;
|
||||||
|
|
||||||
oven_pid_current_status.active = false;
|
oven_pid_current_status.active = false;
|
||||||
oven_pid_current_status.aborted = true;
|
oven_pid_current_status.aborted = true;
|
||||||
|
|
||||||
|
if (report == 0) {
|
||||||
|
e->generic_error = true;
|
||||||
|
}
|
||||||
|
if (report & OVEN_PID_ERR_OVERTEMP)
|
||||||
|
e->controller_overtemp = true;
|
||||||
|
if (report & OVEN_PID_ERR_VREF_TOL)
|
||||||
|
e->controller_overtemp = true;
|
||||||
|
if (report & OVEN_PID_ERR_PT1000_OTHER)
|
||||||
|
e->pt1000_other = true;
|
||||||
|
if (report & OVEN_PID_ERR_PT1000_ADC_OFF)
|
||||||
|
e->pt1000_adc_off = true;
|
||||||
|
if (report & OVEN_PID_ERR_PT1000_ADC_WATCHDOG)
|
||||||
|
e->pt1000_adc_watchdog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct oven_pid_status *oven_pid_get_status()
|
const struct oven_pid_status *oven_pid_get_status()
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <reflow-controller/safety-adc.h>
|
#include <reflow-controller/safety-adc.h>
|
||||||
#include <reflow-controller/periph-config/safety-adc-hwcfg.h>
|
#include <reflow-controller/periph-config/safety-adc-hwcfg.h>
|
||||||
|
#include <helper-macros/helper-macros.h>
|
||||||
#include <stm-periph/clock-enable-manager.h>
|
#include <stm-periph/clock-enable-manager.h>
|
||||||
|
|
||||||
void safety_adc_init()
|
void safety_adc_init()
|
||||||
@ -50,18 +50,32 @@ enum safety_adc_check_result safety_adc_check_results(uint16_t vref_result, uint
|
|||||||
float *vref_calculated, float *temp_calculated)
|
float *vref_calculated, float *temp_calculated)
|
||||||
{
|
{
|
||||||
enum safety_adc_check_result res = SAFETY_ADC_CHECK_OK;
|
enum safety_adc_check_result res = SAFETY_ADC_CHECK_OK;
|
||||||
|
float vref;
|
||||||
|
float temp;
|
||||||
|
|
||||||
|
|
||||||
|
vref = (SAFETY_ADC_INT_REF_MV * 4095.0f) / (float)vref_result;
|
||||||
if (vref_calculated) {
|
if (vref_calculated) {
|
||||||
*vref_calculated = (SAFETY_ADC_INT_REF_MV * 4095.0f) / (float)vref_result;
|
*vref_calculated = vref;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (temp_calculated) {
|
temp = (((float)temp_result / 4095.0f * 2500.0f -
|
||||||
*temp_calculated = (((float)temp_result / 4095.0f * 2500.0f -
|
|
||||||
SAFETY_ADC_TEMP_NOM_MV) / SAFETY_ADC_TEMP_MV_SLOPE) + SAFETY_ADC_TEMP_NOM;
|
SAFETY_ADC_TEMP_NOM_MV) / SAFETY_ADC_TEMP_MV_SLOPE) + SAFETY_ADC_TEMP_NOM;
|
||||||
|
if (temp_calculated) {
|
||||||
|
*temp_calculated = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Implement safety ADC checking */
|
if (ABS(vref - SAFETY_ADC_VREF_MVOLT) > SAFETY_ADC_VREF_TOL_MVOLT) {
|
||||||
|
if (vref > SAFETY_ADC_VREF_MVOLT)
|
||||||
|
res |= SAFETY_ADC_CHECK_VREF_HIGH;
|
||||||
|
else
|
||||||
|
res |= SAFETY_ADC_CHECK_VREF_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp < SAFETY_ADC_TEMP_LOW_LIM)
|
||||||
|
res |= SAFETY_ADC_CHECK_TEMP_LOW;
|
||||||
|
else if (temp < SAFETY_ADC_CHECK_TEMP_HIGH)
|
||||||
|
res |= SAFETY_ADC_CHECK_TEMP_HIGH;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user