|
|
|
@ -26,17 +26,17 @@ const float V_REFINT = 1.23f; |
|
|
|
|
|
|
|
|
|
static struct App { |
|
|
|
|
float oven_temp; |
|
|
|
|
float oven_temp_raw; |
|
|
|
|
float soc_temp; |
|
|
|
|
float v_sensor; |
|
|
|
|
float cal_a; |
|
|
|
|
float cal_b; |
|
|
|
|
float oventemp_history[OVENTEMP_HISTORY_DEPTH]; // raw temp
|
|
|
|
|
uint16_t adc_averagebuf[AVERAGEBUF_DEPTH * 4]; |
|
|
|
|
uint8_t averagebuf_ptr; |
|
|
|
|
float adc_averages[4]; |
|
|
|
|
float oventemp_history[OVENTEMP_HISTORY_DEPTH]; |
|
|
|
|
uint8_t oventemp_history_ptr; |
|
|
|
|
} s_analog = { |
|
|
|
|
.cal_a = 1.0f, |
|
|
|
|
// Ax + B = y ... X = raw sample (ratio 0-1 of 3.3), Y = corrected sample
|
|
|
|
|
.cal_a = 1.0f, // safe default calibration constants
|
|
|
|
|
.cal_b = 0.0f, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -148,6 +148,35 @@ static const float TSENSE_LOOKUP[TSENSE_LOOKUP_LEN] = { |
|
|
|
|
0.219346163379138f, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// if the calibration constants are zero, reset to defaults
|
|
|
|
|
static void correct_invalid_calib() { |
|
|
|
|
if (s_analog.cal_a == 0.0f || s_analog.cal_b == 0.0f) { |
|
|
|
|
PRINTF("ADC invalid calib, reset\r\n"); |
|
|
|
|
s_analog.cal_a = 1.0f; |
|
|
|
|
s_analog.cal_b = 0.0f; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Set and persist calibration constants
|
|
|
|
|
void app_temp_set_calib(float a, float b) { |
|
|
|
|
s_analog.cal_a = a; |
|
|
|
|
s_analog.cal_b = b; |
|
|
|
|
correct_invalid_calib(); |
|
|
|
|
|
|
|
|
|
EE_Status st = EE_WriteVariable32bits(EE_ADDR_CAL_A, ((x32_t) { .f = a }).u); |
|
|
|
|
if (st == EE_CLEANUP_REQUIRED) { |
|
|
|
|
EE_CleanUp(); |
|
|
|
|
} else if (st != EE_OK) { |
|
|
|
|
PRINTF("EE write err %d!\r\n", st); |
|
|
|
|
} |
|
|
|
|
st = EE_WriteVariable32bits(EE_ADDR_CAL_B, ((x32_t) { .f = b }).u); |
|
|
|
|
if (st == EE_CLEANUP_REQUIRED) { |
|
|
|
|
EE_CleanUp(); |
|
|
|
|
} else if (st != EE_OK) { |
|
|
|
|
PRINTF("EE write err %d!\r\n", st); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void app_analog_init() |
|
|
|
|
{ |
|
|
|
|
// read calibration constants
|
|
|
|
@ -161,11 +190,7 @@ void app_analog_init() |
|
|
|
|
PRINTF("ADC calib b read from EE: %f\r\n", s_analog.cal_b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (s_analog.cal_a == 0.0f || s_analog.cal_b == 0.0f) { |
|
|
|
|
PRINTF("ADC invalid calib, reset\r\n"); |
|
|
|
|
s_analog.cal_a = 1.0f; |
|
|
|
|
s_analog.cal_b = 0.0f; |
|
|
|
|
} |
|
|
|
|
correct_invalid_calib(); |
|
|
|
|
|
|
|
|
|
LL_ADC_Enable(ADC_TEMP); |
|
|
|
|
|
|
|
|
@ -192,7 +217,7 @@ void app_analog_init() |
|
|
|
|
LL_TIM_EnableCounter(TIM1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static float val_to_c(float val) |
|
|
|
|
float val_to_c(float val) |
|
|
|
|
{ |
|
|
|
|
// TODO use binary search.. lol
|
|
|
|
|
for (int i = 1; i < TSENSE_LOOKUP_LEN; i++) { |
|
|
|
@ -207,6 +232,22 @@ static float val_to_c(float val) |
|
|
|
|
return TSENSE_T_MAX; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float c_to_val(float cf) |
|
|
|
|
{ |
|
|
|
|
int lower = (int) (cf / TSENSE_T_STEP); |
|
|
|
|
|
|
|
|
|
if (lower < 0) { |
|
|
|
|
lower = 0; |
|
|
|
|
} |
|
|
|
|
if (lower >= TSENSE_LOOKUP_LEN - 1) { |
|
|
|
|
lower = TSENSE_LOOKUP_LEN - 2; |
|
|
|
|
} |
|
|
|
|
int upper = lower + 1; |
|
|
|
|
|
|
|
|
|
float ratio = (cf - ((float)lower * TSENSE_T_STEP)) / 5.0f; |
|
|
|
|
return TSENSE_LOOKUP[lower] + (TSENSE_LOOKUP[upper] - TSENSE_LOOKUP[lower]) * ratio; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void app_temp_sample() |
|
|
|
|
{ |
|
|
|
|
uint32_t sums[4] = {}; |
|
|
|
@ -224,39 +265,38 @@ void app_temp_sample() |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
s_analog.adc_averages[0] = (float) sums[0] / count; |
|
|
|
|
s_analog.adc_averages[1] = (float) sums[1] / count; |
|
|
|
|
s_analog.adc_averages[2] = (float) sums[2] / count; |
|
|
|
|
s_analog.adc_averages[3] = (float) sums[3] / count; |
|
|
|
|
float adc_averages[4]; |
|
|
|
|
|
|
|
|
|
adc_averages[0] = (float) sums[0] / count; |
|
|
|
|
adc_averages[1] = (float) sums[1] / count; |
|
|
|
|
adc_averages[2] = (float) sums[2] / count; |
|
|
|
|
adc_averages[3] = (float) sums[3] / count; |
|
|
|
|
|
|
|
|
|
PRINTF("%f\t%f\t%f\t%f\r\n", |
|
|
|
|
s_analog.adc_averages[0], |
|
|
|
|
s_analog.adc_averages[1], |
|
|
|
|
s_analog.adc_averages[2], |
|
|
|
|
s_analog.adc_averages[3] |
|
|
|
|
adc_averages[0], |
|
|
|
|
adc_averages[1], |
|
|
|
|
adc_averages[2], |
|
|
|
|
adc_averages[3] |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
/* r_pt100, r_ref, internal_temp, v_ref_int */ |
|
|
|
|
float refint = s_analog.adc_averages[3]; |
|
|
|
|
float refint = adc_averages[3]; |
|
|
|
|
float scale = V_REFINT / refint; |
|
|
|
|
|
|
|
|
|
const float avg_slope = 4.3f * scale; |
|
|
|
|
const float v25 = 1.43f; |
|
|
|
|
const float v_tsen = s_analog.adc_averages[2] * scale; |
|
|
|
|
const float v_tsen = adc_averages[2] * scale; |
|
|
|
|
|
|
|
|
|
s_analog.soc_temp = (v25 - v_tsen) / avg_slope + 25.f; |
|
|
|
|
s_analog.v_sensor = s_analog.adc_averages[0] * scale; // good for debug/tuning
|
|
|
|
|
//s_analog.v_sensor = adc_averages[0] * scale; // good for debug/tuning
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// using a voltage divider, so assuming the reference resistor is measured well,
|
|
|
|
|
// we can just use the ratio and the exact voltage value is not important.
|
|
|
|
|
|
|
|
|
|
float x = s_analog.adc_averages[0] / s_analog.adc_averages[1]; |
|
|
|
|
float y = s_analog.cal_a * x + s_analog.cal_b; |
|
|
|
|
float actual_temp = val_to_c(y); |
|
|
|
|
PRINTF("Compensated x %f -> y %f, temp %f C\r\n", x, y, actual_temp); |
|
|
|
|
float oventemp_sample = adc_averages[0] / adc_averages[1]; |
|
|
|
|
|
|
|
|
|
s_analog.oventemp_history[s_analog.oventemp_history_ptr] = actual_temp; |
|
|
|
|
s_analog.oventemp_history[s_analog.oventemp_history_ptr] = oventemp_sample; |
|
|
|
|
s_analog.oventemp_history_ptr = (s_analog.oventemp_history_ptr + 1) % OVENTEMP_HISTORY_DEPTH; |
|
|
|
|
|
|
|
|
|
float sum = 0; |
|
|
|
@ -270,15 +310,21 @@ void app_temp_sample() |
|
|
|
|
if (depth > 0) { |
|
|
|
|
sum /= depth; |
|
|
|
|
} |
|
|
|
|
s_analog.oven_temp = sum; |
|
|
|
|
|
|
|
|
|
float y = s_analog.cal_a * sum + s_analog.cal_b; |
|
|
|
|
float actual_temp = val_to_c(y); |
|
|
|
|
PRINTF("Compensated x %f -> y %f, temp %f C\r\n", sum, y, actual_temp); |
|
|
|
|
|
|
|
|
|
s_analog.oven_temp = actual_temp; |
|
|
|
|
s_analog.oven_temp_raw = sum; |
|
|
|
|
|
|
|
|
|
app_safety_pass_temp_calculation(); |
|
|
|
|
|
|
|
|
|
if (s_analog.oven_temp >= 5.0 && s_analog.oven_temp <= 455.0) { |
|
|
|
|
if (s_analog.oven_temp_raw >= 0.05 && s_analog.oven_temp_raw <= 0.22) { |
|
|
|
|
app_safety_pass_temp_normal(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (s_analog.soc_temp >= 5.0 && s_analog.soc_temp <= 80.0) { |
|
|
|
|
if (s_analog.soc_temp >= 2.0 && s_analog.soc_temp <= 80.0) { |
|
|
|
|
app_safety_pass_soc_temp_ok(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -288,6 +334,11 @@ float app_temp_read_oven() |
|
|
|
|
return s_analog.oven_temp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float app_temp_read_oven_raw() |
|
|
|
|
{ |
|
|
|
|
return s_analog.oven_temp_raw; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float app_temp_read_soc() |
|
|
|
|
{ |
|
|
|
|
return s_analog.soc_temp; |
|
|
|
|