Compare commits
3 Commits
c565dab3ad
...
92526e71b2
Author | SHA1 | Date | |
---|---|---|---|
92526e71b2 | |||
b13b3b4377 | |||
c568b95cf2 |
@ -19,9 +19,11 @@
|
|||||||
|
|
||||||
#include <reflow-controller/calibration.h>
|
#include <reflow-controller/calibration.h>
|
||||||
#include <reflow-controller/adc-meas.h>
|
#include <reflow-controller/adc-meas.h>
|
||||||
|
#include <stm-periph/uart.h>
|
||||||
#include <helper-macros/helper-macros.h>
|
#include <helper-macros/helper-macros.h>
|
||||||
#include <arm_math.h>
|
#include <arm_math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
void calibration_calculate(float low_measured, float low_setpoint, float high_measured, float high_setpoint,
|
void calibration_calculate(float low_measured, float low_setpoint, float high_measured, float high_setpoint,
|
||||||
float *sens_deviation, float *sens_corrected_offset)
|
float *sens_deviation, float *sens_corrected_offset)
|
||||||
@ -44,23 +46,24 @@ void calibration_calculate(float low_measured, float low_setpoint, float high_me
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int calibration_acquire_data(float *mu, float *sigma, uint32_t count)
|
int calibration_acquire_data(float *mu, float *max_dev, uint32_t count)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
float *stream_mem;
|
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;
|
static volatile int flag = 0;
|
||||||
|
|
||||||
if (!mu || !sigma || !count)
|
if (!mu || !max_dev || !count)
|
||||||
return -1000;
|
return -1000;
|
||||||
|
|
||||||
stream_mem = (float *)calloc(count, sizeof(float));
|
stream_mem = (float *)calloc(count, sizeof(float));
|
||||||
if (!stream_mem)
|
if (!stream_mem)
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
/* Clear errors of PT1000 reading */
|
|
||||||
adc_pt1000_clear_error();
|
|
||||||
|
|
||||||
status = adc_pt1000_stream_raw_value_to_memory(stream_mem, count, &flag);
|
status = adc_pt1000_stream_raw_value_to_memory(stream_mem, count, &flag);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
@ -70,7 +73,8 @@ int calibration_acquire_data(float *mu, float *sigma, uint32_t count)
|
|||||||
|
|
||||||
if (flag != 1) {
|
if (flag != 1) {
|
||||||
/* Error */
|
/* Error */
|
||||||
return -1;
|
ret_val = -1;
|
||||||
|
goto ret_free_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the stream memory to Ohm readings */
|
/* Convert the stream memory to Ohm readings */
|
||||||
@ -79,10 +83,87 @@ int calibration_acquire_data(float *mu, float *sigma, uint32_t count)
|
|||||||
/* Do not compute std-deviation. Too imprecise
|
/* Do not compute std-deviation. Too imprecise
|
||||||
* arm_std_f32(stream_mem, count, sigma);
|
* arm_std_f32(stream_mem, count, sigma);
|
||||||
*/
|
*/
|
||||||
*sigma = 0;
|
|
||||||
arm_mean_f32(stream_mem, count, mu);
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
72
stm-firmware/create-temp-lookup-table.py
Executable file
72
stm-firmware/create-temp-lookup-table.py
Executable file
@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
license_header = """/* Reflow Oven Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* 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 GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
"""
|
||||||
|
|
||||||
|
hfile="temp-converter-data.h"
|
||||||
|
|
||||||
|
project_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
include_prefix = 'reflow-controller'
|
||||||
|
module_include_dir = os.path.join(project_dir, os.path.join('include', include_prefix))
|
||||||
|
include_file = os.path.join(module_include_dir, hfile)
|
||||||
|
|
||||||
|
h_define = '__'+hfile.replace('.', '_').replace('-', '_').upper()+'__'
|
||||||
|
|
||||||
|
min_res = 1000
|
||||||
|
max_res = 2200
|
||||||
|
res_step = 20
|
||||||
|
|
||||||
|
R_zero = 1000.0
|
||||||
|
A = 3.9083E-3
|
||||||
|
B = -5.7750E-7
|
||||||
|
|
||||||
|
def calc_temp(resistance):
|
||||||
|
temp = (-R_zero * A + np.sqrt(R_zero*R_zero * A * A - 4* R_zero * B * (R_zero - resistance)))/(2*R_zero*B)
|
||||||
|
return temp
|
||||||
|
|
||||||
|
if ((max_res-min_res) % res_step) != 0:
|
||||||
|
print('Resistance range must be a multiple of res_step!')
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
print('Calculating temperature table for %f Ohm to %f Ohm in %f Ohm steps' % (min_res, max_res, res_step))
|
||||||
|
|
||||||
|
temp_array = ''
|
||||||
|
|
||||||
|
for res in range(min_res, max_res+res_step, res_step):
|
||||||
|
temp = calc_temp(res)
|
||||||
|
temp_array = temp_array+ ',%.2ff' % temp
|
||||||
|
|
||||||
|
temp_array = temp_array[1:]
|
||||||
|
|
||||||
|
with open(include_file, 'x') as f:
|
||||||
|
f.write(license_header)
|
||||||
|
f.write('\n')
|
||||||
|
f.write('#ifndef %s\n' % h_define)
|
||||||
|
f.write('#define %s\n\n' % h_define)
|
||||||
|
f.write('#define TEMP_CONVERSION_ARRAY_DATA %s\n' % temp_array)
|
||||||
|
f.write('#define TEMP_CONVERSION_MIN_RES %d\n' % min_res)
|
||||||
|
f.write('#define TEMP_CONVERSION_MAX_RES %d\n' % max_res)
|
||||||
|
f.write('#define TEMP_CONVERSION_RES_STEP %d\n' % res_step)
|
||||||
|
f.write('\n')
|
||||||
|
f.write('#endif /* %s */\n' % h_define)
|
28
stm-firmware/include/reflow-controller/temp-converter-data.h
Normal file
28
stm-firmware/include/reflow-controller/temp-converter-data.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* Reflow Oven Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* 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 GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TEMP_CONVERTER_DATA_H__
|
||||||
|
#define __TEMP_CONVERTER_DATA_H__
|
||||||
|
|
||||||
|
#define TEMP_CONVERSION_ARRAY_DATA -0.00f,5.12f,10.25f,15.39f,20.53f,25.68f,30.84f,36.01f,41.19f,46.37f,51.57f,56.77f,61.98f,67.19f,72.42f,77.65f,82.89f,88.14f,93.40f,98.67f,103.94f,109.23f,114.52f,119.82f,125.13f,130.45f,135.77f,141.11f,146.45f,151.81f,157.17f,162.54f,167.92f,173.31f,178.71f,184.11f,189.53f,194.96f,200.39f,205.84f,211.29f,216.75f,222.22f,227.71f,233.20f,238.70f,244.21f,249.73f,255.26f,260.80f,266.35f,271.91f,277.48f,283.06f,288.65f,294.25f,299.86f,305.48f,311.11f,316.75f,322.40f
|
||||||
|
#define TEMP_CONVERSION_MIN_RES 1000
|
||||||
|
#define TEMP_CONVERSION_MAX_RES 2200
|
||||||
|
#define TEMP_CONVERSION_RES_STEP 20
|
||||||
|
|
||||||
|
#endif /* __TEMP_CONVERTER_DATA_H__ */
|
Loading…
x
Reference in New Issue
Block a user