/* Reflow Oven Controller * * Copyright (C) 2020 Mario Hüttel * * This file is part of the Reflow Oven Controller Project. * * The reflow oven controller is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * GDSII-Converter 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 the reflow oven controller project. * If not, see . */ #include #include #include #include #include #include #include void calibration_calculate(float low_measured, float low_setpoint, float high_measured, float high_setpoint, float *sens_deviation, float *sens_corrected_offset) { if (!sens_deviation || !sens_corrected_offset) return; float delta_y; float delta_x; float sens_corr_mult; delta_y = high_measured - low_measured; delta_x = high_setpoint - low_setpoint; sens_corr_mult = delta_x / delta_y; *sens_deviation = sens_corr_mult - 1.0f; *sens_corrected_offset = low_setpoint - low_measured * sens_corr_mult; } int calibration_acquire_data(float *mu, float *max_dev, uint32_t count) { 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; stream_mem = (float *)calloc(count, sizeof(float)); if (!stream_mem) return -2; status = adc_pt1000_stream_raw_value_to_memory(stream_mem, count, &flag); if (status) return status; /* Wait for data to be transferred */ while (flag == 0); 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); /* Do not compute std-deviation. Too imprecise * arm_std_f32(stream_mem, count, sigma); */ arm_mean_f32(stream_mem, 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]); } /* Compute maximum deviation range */ *max_dev = max_val - min_val; ret_free_mem: free(stream_mem); return ret_val; } static void wait_for_uart_enter() { int enter_received = 0; const char *recv_data; size_t recv_len; size_t iter; int uart_recv_status; do { uart_recv_status = uart_receive_data_with_dma(&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; } } } 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 you're 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; }