diff --git a/stm-firmware/calibration.c b/stm-firmware/calibration.c index dd769c0..fc70495 100644 --- a/stm-firmware/calibration.c +++ b/stm-firmware/calibration.c @@ -27,7 +27,7 @@ #include #include -extern struct stm_uart shell_uart; +enum calibration_shell_state {CAL_START = 0, CAL_WAIT_RES1, CAL_MEAS_RES1, CAL_WAIT_RES2, CAL_MEAS_RES2}; void calibration_calculate(float low_measured, float low_setpoint, float high_measured, float high_setpoint, float *sens_deviation, float *sens_corrected_offset) @@ -50,124 +50,217 @@ void calibration_calculate(float low_measured, float low_setpoint, float high_me -int calibration_acquire_data(float *mu, float *max_dev, uint32_t count) +float *calibration_acquire_data_start(uint32_t count, volatile int *flag) { int status; float *stream_mem; - float min_val = FLT_MAX; - float max_val = -FLT_MAX; - uint32_t i; - int ret_val = 0; - static volatile int flag = 0; - - if (!mu || !max_dev || !count) - return -1000; + if (!count) + return NULL; stream_mem = (float *)calloc(count, sizeof(float)); if (!stream_mem) - return -2; + return stream_mem; - status = adc_pt1000_stream_raw_value_to_memory(stream_mem, count, &flag); + *flag = 0; + status = adc_pt1000_stream_raw_value_to_memory(stream_mem, count, flag); if (status) - return status; + goto free_mem; - /* Wait for data to be transferred */ - while (flag == 0); - if (flag != 1) { + return stream_mem; +free_mem: + free(stream_mem); + return NULL; +} + +static int calibration_poll_data_acquisition(float *mem_array, uint32_t count, volatile int *flag, float *mu, float *max_dev) +{ + int ret_val = 0; + float min_val = FLT_MAX; + float max_val = -FLT_MAX; + uint32_t i; + + if (!flag || !mem_array || !mu || !max_dev) + return -1000; + + if (*flag == 0) { + /* Continue polling */ + return 1; + } + + if (*flag != 1) { /* Error */ ret_val = -1; goto ret_free_mem; } /* Convert the stream memory to Ohm readings */ - adc_pt1000_convert_raw_value_array_to_resistance(NULL, stream_mem, count); + adc_pt1000_convert_raw_value_array_to_resistance(NULL, mem_array, count); /* Do not compute std-deviation. Too imprecise * arm_std_f32(stream_mem, count, sigma); */ - arm_mean_f32(stream_mem, count, mu); + arm_mean_f32(mem_array, count, mu); /* Find min and max values of array */ for (i = 0U; i < count; i++) { - min_val = MIN(min_val, stream_mem[i]); - max_val = MAX(max_val, stream_mem[i]); + min_val = MIN(min_val, mem_array[i]); + max_val = MAX(max_val, mem_array[i]); } /* Compute maximum deviation range */ *max_dev = max_val - min_val; ret_free_mem: - free(stream_mem); + free(mem_array); return ret_val; } -static void wait_for_uart_enter() +shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, const char *arg, uint32_t len) { - int enter_received = 0; - const char *recv_data; - size_t recv_len; - size_t iter; - int uart_recv_status; + (void)arg; + (void)len; - do { - uart_recv_status = uart_receive_data_with_dma(&shell_uart, &recv_data, &recv_len); - if (uart_recv_status >= 1) { - for (iter = 0; iter < recv_len; iter++) { - if (recv_data[iter] == '\n' || recv_data[iter] == '\r') - enter_received = 1; + /* This stores the current state of the calibration process */ + static enum calibration_shell_state cal_state = CAL_START; + shellmatta_retCode_t ret_val = SHELLMATTA_BUSY; + uint32_t i; + int res; + + static float mu = 0.0f, mu2 = 0.0f, dev = 0.0f, dev2 = 0.0f; + float sens_dev, offset; + static float *data_buffer = NULL; + static volatile int flag; + char *stdin_data; + uint32_t stdin_len; + + + switch (cal_state) { + case CAL_START: + /* Clear errors of PT1000 reading */ + adc_pt1000_clear_error(); + shellmatta_printf(shell, "Starting calibration: Insert 1000 Ohm calibration resistor and press ENTER\r\n"); + cal_state = CAL_WAIT_RES1; + ret_val = SHELLMATTA_CONTINUE; + break; + case CAL_WAIT_RES1: + cal_state = CAL_WAIT_RES1; + ret_val = SHELLMATTA_CONTINUE; + shellmatta_read(shell, &stdin_data, &stdin_len); + if (stdin_len > 0) { + for (i = 0; i < stdin_len; i++) { + if (stdin_data[i] == '\r') { + cal_state = CAL_MEAS_RES1; + ret_val = SHELLMATTA_BUSY; + shellmatta_printf(shell, "Measurement...\r\n"); + adc_pt1000_clear_error(); + data_buffer = calibration_acquire_data_start(512UL, &flag); + break; + } else if (stdin_data[i] == '\x03') { + cal_state = CAL_START; + } } } - } while (enter_received == 0); -} - -int calibration_sequence_shell_cmd(shellmatta_handle_t shell) -{ - float mu, mu2, dev, dev2; - float sens_dev, offset; - - /* Clear errors of PT1000 reading */ - adc_pt1000_clear_error(); - - shellmatta_printf(shell, "Starting calibration: Insert 1000 Ohm calibration resistor and press ENTER\r\n"); - wait_for_uart_enter(); - shellmatta_printf(shell, "Measurement...\r\n"); - - /* Clear errors of PT1000 reading */ - adc_pt1000_clear_error(); - calibration_acquire_data(&mu, &dev, 512UL); - 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()); - return -1; - } - - /* Measure 2nd calibration point */ - shellmatta_printf(shell, "Insert 2000 Ohm calibration resistor and press ENTER\r\n"); - wait_for_uart_enter(); - shellmatta_printf(shell, "Measurement...\r\n"); - - /* Clear errors of PT1000 reading */ - adc_pt1000_clear_error(); - calibration_acquire_data(&mu2, &dev2, 512UL); - 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()); - return -2; - } - - /* Check noise values */ - if (dev > CALIBRATION_MAX_PEAK_PEAK_NOISE_OHM || dev2 > CALIBRATION_MAX_PEAK_PEAK_NOISE_OHM) { - shellmatta_printf(shell, "Calibration failed! Too much noise. Check your hardware.\r\n"); - return -3; - } - - /* Calculate calibration */ - calibration_calculate(mu, 1000.0f, mu2, 2000.0f, &sens_dev, &offset); - - shellmatta_printf(shell, "Calibration done:\r\n\tSENS_DEVIATION: %.4f\r\n\tOFFSET_CORR: %.2f\r\n", sens_dev, offset); - adc_pt1000_set_resistance_calibration(offset, sens_dev, true); - - return 0; + + break; + case CAL_MEAS_RES1: + if (!data_buffer) { + shellmatta_printf(shell, "Data acquisition failed!\r\n"); + ret_val = SHELLMATTA_OK; + cal_state = CAL_START; + break; + } + + res = calibration_poll_data_acquisition(data_buffer, 512UL, &flag, &mu, &dev); + /* Stay in this state until the measurements are finished */ + if (res == 1) { + ret_val = SHELLMATTA_BUSY; + 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()); + ret_val = SHELLMATTA_OK; + cal_state = CAL_START; + } else { + ret_val = SHELLMATTA_CONTINUE; + shellmatta_printf(shell, "Insert 2000 Ohm calibration resistor and press ENTER\r\n"); + cal_state = CAL_WAIT_RES2; + } + } else { + shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error()); + ret_val = SHELLMATTA_OK; + cal_state = CAL_START; + } + break; + case CAL_WAIT_RES2: + cal_state = CAL_WAIT_RES2; + ret_val = SHELLMATTA_CONTINUE; + shellmatta_read(shell, &stdin_data, &stdin_len); + if (stdin_len > 0) { + for (i = 0; i < stdin_len; i++) { + if (stdin_data[i] == '\r') { + cal_state = CAL_MEAS_RES2; + ret_val = SHELLMATTA_BUSY; + shellmatta_printf(shell, "Measurement...\r\n"); + adc_pt1000_clear_error(); + data_buffer = calibration_acquire_data_start(512UL, &flag); + break; + } else if (stdin_data[i] == '\x03') { + cal_state = CAL_START; + } + } + } + + break; + case CAL_MEAS_RES2: + if (!data_buffer) { + shellmatta_printf(shell, "Data acquisition failed!\r\n"); + ret_val = SHELLMATTA_OK; + cal_state = CAL_START; + break; + } + + res = calibration_poll_data_acquisition(data_buffer, 512UL, &flag, &mu2, &dev2); + /* Stay in this state until the measurements are finished */ + if (res == 1) { + ret_val = SHELLMATTA_BUSY; + 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()); + ret_val = SHELLMATTA_OK; + cal_state = CAL_START; + } else { + ret_val = SHELLMATTA_OK; + cal_state = CAL_START; + + if (dev > CALIBRATION_MAX_PEAK_PEAK_NOISE_OHM || + dev2 > CALIBRATION_MAX_PEAK_PEAK_NOISE_OHM) { + shellmatta_printf(shell, "Calibration failed! Too much noise. Check your hardware.\r\n"); + break; + } + shellmatta_printf(shell, "Calibartion finished successfully!\r\n"); + /* Calculate calibration */ + calibration_calculate(mu, 1000.0f, mu2, 2000.0f, &sens_dev, &offset); + + shellmatta_printf(shell, "\r\n\tSENS_DEVIATION: %.4f\r\n\tOFFSET_CORR: %.2f\r\n", sens_dev, offset); + adc_pt1000_set_resistance_calibration(offset, sens_dev, true); + } + } else { + shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error()); + ret_val = SHELLMATTA_OK; + cal_state = CAL_START; + } + break; + default: + shellmatta_printf(shell, "Undefined state reached in calibration. Aborting\r\n"); + cal_state = CAL_START; + ret_val = SHELLMATTA_OK; + break; + } + + return ret_val; } diff --git a/stm-firmware/include/reflow-controller/calibration.h b/stm-firmware/include/reflow-controller/calibration.h index 8f007e0..82aa55a 100644 --- a/stm-firmware/include/reflow-controller/calibration.h +++ b/stm-firmware/include/reflow-controller/calibration.h @@ -29,8 +29,8 @@ void calibration_calculate(float low_measured, float low_setpoint, float high_measured, float high_setpoint, float *sens_deviation, float *sens_corrected_offset); -int calibration_acquire_data(float *mu, float *max_dev, uint32_t count); +float *calibration_acquire_data_start(uint32_t count, volatile int *flag); -int calibration_sequence_shell_cmd(shellmatta_handle_t shell); +shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, const char *arg, uint32_t len); #endif /* __CALIBRATION_H__ */ diff --git a/stm-firmware/include/stm-periph/stm32-gpio-macros.h b/stm-firmware/include/stm-periph/stm32-gpio-macros.h index f94e4da..0dd3097 100644 --- a/stm-firmware/include/stm-periph/stm32-gpio-macros.h +++ b/stm-firmware/include/stm-periph/stm32-gpio-macros.h @@ -25,6 +25,7 @@ #define PUPDR_DELETE(pin) ~(0x3U << ((pin) * 2)) #define OUTPUT(pin) (0x01U << ((pin) * 2)) #define PULLUP(pin) (0x1U << ((pin)* 2)) +#define PULLDOWN(pin) (0x2U << ((pin)* 2)) #define ALTFUNC(pin) ((0x2) << ((pin) * 2)) #define PINMASK(pin) ((0x3) << ((pin) * 2)) #define SETAF(PORT,PIN,AF) PORT->AFR[((PIN) < 8 ? 0 : 1)] |= (AF) << (((PIN) < 8 ? (PIN) : ((PIN) - 8)) * 4) diff --git a/stm-firmware/main.c b/stm-firmware/main.c index e55c845..fd1b479 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -73,6 +73,11 @@ FATFS *fs_ptr = &fs; static inline void uart_gpio_config() { + /* + * In case the application is build in debug mode, use the TX/RX Pins on the debug header + * else the Pins on the DIGIO header are configured in the digio module + */ + #ifdef DEBUGBUILD rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(SHELL_UART_PORT_RCC_MASK)); SHELL_UART_PORT->MODER &= MODER_DELETE(SHELL_UART_TX_PIN) & MODER_DELETE(SHELL_UART_RX_PIN); @@ -151,7 +156,15 @@ static inline int32_t handle_pid_controller(struct pid_controller *pid, float ta return pid_out; } -const char *oven_controller_hello_world = "Hello world :)\n"; +static void setup_unused_pins() +{ + int i; + + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_GPIOEEN)); + GPIOE->MODER = 0UL; + for (i = 0; i < 16; i++) + GPIOE->PUPDR |= PULLDOWN(i); +} static inline void setup_system() { @@ -169,16 +182,26 @@ static inline void setup_system() uart_gpio_config(); setup_sell_uart(&shell_uart); + + setup_unused_pins(); +} + +static void handle_shell_uart_input(shellmatta_handle_t shell_handle) +{ + int uart_receive_status; + const char *uart_input; + size_t uart_input_len; + + /* Handle uart input for shell */ + uart_receive_status = uart_receive_data_with_dma(&shell_uart, &uart_input, &uart_input_len); + if (uart_receive_status >= 0) + shell_handle_input(shell_handle, uart_input, uart_input_len); } int main() { bool sd_card_mounted = false; - FIL test_file; - const char *uart_input; - size_t uart_input_len; shellmatta_handle_t shell_handle; - int uart_receive_status; uint64_t pid_timestamp = 0ULL; bool pid_controller_active = false; @@ -194,13 +217,6 @@ int main() shell_handle = shell_init(write_shell_callback); shell_print_motd(shell_handle); - if (f_mount(fs_ptr, "0:/", 1) == FR_OK) { - sd_card_mounted = true; - f_open(&test_file, "hello-world.txt", FA_OPEN_APPEND | FA_WRITE); - f_write(&test_file, oven_controller_hello_world, strlen(oven_controller_hello_world), NULL); - f_close(&test_file); - } - pid_init(&pid, 0.1, 0.1, 4.0, 0.0, 100.0, 40.0); pid_zero(&pid); @@ -219,6 +235,8 @@ int main() /* Blink red led in case of temp error */ if (pt1000_value_status < 0) led_set(0, !led_get(0)); + else + led_set(0, 0); } /* Handle error in case PID controller should be active, but temperature measurement failed */ @@ -243,10 +261,7 @@ int main() snprintf(&disp[1][0], 17, "Rotary: %u", (unsigned int)rot); snprintf(&disp[2][0], 17, "Button: %s", (button == BUTTON_SHORT ? "SHORT" : (button == BUTTON_LONG ? "LONG" : ""))); - /* Handle uart input for shell */ - uart_receive_status = uart_receive_data_with_dma(&shell_uart, &uart_input, &uart_input_len); - if (uart_receive_status >= 0) - shell_handle_input(shell_handle, uart_input, uart_input_len); + handle_shell_uart_input(shell_handle); if (systick_ticks_have_passed(display_timestamp, 2) || lcd_ret == LCD_FSM_CALL_AGAIN) { lcd_ret = lcd_fsm_write_buffer(disp); diff --git a/stm-firmware/shell.c b/stm-firmware/shell.c index 3054ad1..80cccb7 100644 --- a/stm-firmware/shell.c +++ b/stm-firmware/shell.c @@ -200,8 +200,7 @@ static shellmatta_retCode_t shell_cmd_cal(const shellmatta_handle_t handle, (void)arguments; (void)length; - calibration_sequence_shell_cmd(handle); - return SHELLMATTA_OK; + return calibration_sequence_shell_cmd(handle, arguments, length); } static shellmatta_retCode_t shell_meminfo(const shellmatta_handle_t handle,