calibration mostly working
This commit is contained in:
+1
-18
@@ -41,6 +41,7 @@ uint32_t push_time();
|
||||
void screen_home(GuiEvent event);
|
||||
void screen_manual(GuiEvent event);
|
||||
void screen_manual_menu(GuiEvent event);
|
||||
void screen_calibration(GuiEvent event);
|
||||
|
||||
struct State {
|
||||
/// Latest oven temp readout
|
||||
@@ -78,24 +79,6 @@ struct State {
|
||||
|
||||
/// Pointer to the currently active screen func
|
||||
screen_t screen;
|
||||
|
||||
/// Generic menu
|
||||
struct menu_state {
|
||||
int pos;
|
||||
int len;
|
||||
uint32_t change_time;
|
||||
uint32_t slide_end_time;
|
||||
uint16_t text_slide;
|
||||
uint8_t tick_counter;
|
||||
} menu;
|
||||
|
||||
struct calib_state {
|
||||
int phase;
|
||||
float sample1;
|
||||
float sample2;
|
||||
int temp1;
|
||||
int temp2;
|
||||
} calib;
|
||||
};
|
||||
|
||||
extern struct State s_app;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "app_gui.h"
|
||||
#include "app_heater.h"
|
||||
#include "screen_menu.h"
|
||||
@@ -12,6 +13,28 @@
|
||||
#include "snprintf.h"
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
struct calib_state {
|
||||
int phase;
|
||||
float sample1;
|
||||
float sample2;
|
||||
int temp1;
|
||||
int temp2;
|
||||
} s_calib;
|
||||
|
||||
enum Phase {
|
||||
PH_HELLO = 0,
|
||||
PH_SAMPLE1,
|
||||
PH_TEMP1,
|
||||
PH_SAMPLE2,
|
||||
PH_TEMP2,
|
||||
PH_DONE,
|
||||
};
|
||||
|
||||
static void next_phase() {
|
||||
PUTS("Phase++\r\n");
|
||||
s_calib.phase++;
|
||||
}
|
||||
|
||||
static const char* calib0_opts[] = {
|
||||
"Pokračovat",
|
||||
"Zrušit",
|
||||
@@ -22,7 +45,7 @@ static void calib0_cb(int opt) {
|
||||
switch (opt) {
|
||||
case 0:
|
||||
// Continue
|
||||
s_app.calib.phase++;
|
||||
next_phase();
|
||||
request_paint();
|
||||
app_heater_manual_override(100);
|
||||
break;
|
||||
@@ -41,13 +64,15 @@ static const char* calib1_opts[] = {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static void calib1_cb(int opt) {
|
||||
switch (opt) {
|
||||
case 0:
|
||||
// Continue
|
||||
s_app.calib.phase++;
|
||||
next_phase();
|
||||
request_paint();
|
||||
s_app.calib.sample1 = app_temp_read_oven_raw();
|
||||
s_calib.sample1 = app_temp_read_oven_raw();
|
||||
app_heater_manual_override(0);
|
||||
break;
|
||||
|
||||
@@ -69,9 +94,9 @@ static void calib3_cb(int opt) {
|
||||
switch (opt) {
|
||||
case 0:
|
||||
// Continue
|
||||
s_app.calib.phase++;
|
||||
next_phase();
|
||||
request_paint();
|
||||
s_app.calib.sample2 = app_temp_read_oven_raw();
|
||||
s_calib.sample2 = app_temp_read_oven_raw();
|
||||
app_heater_manual_override(0);
|
||||
break;
|
||||
|
||||
@@ -82,54 +107,41 @@ static void calib3_cb(int opt) {
|
||||
}
|
||||
}
|
||||
|
||||
void screen_manual_menu(GuiEvent event)
|
||||
void screen_calibration(GuiEvent event)
|
||||
{
|
||||
if (event == GUI_EVENT_SCREEN_INIT) {
|
||||
s_app.calib.phase = 0;
|
||||
s_app.calib.sample1 = s_app.calib.sample2 = 0.0f;
|
||||
s_app.calib.temp1 = s_app.calib.temp2 = 0;
|
||||
memset(&s_calib, 0, sizeof(s_calib));
|
||||
// continue to the rest - so the menu can be inited
|
||||
}
|
||||
|
||||
int phase = s_app.calib.phase;
|
||||
int *pT;
|
||||
switch (phase) {
|
||||
case 0:
|
||||
switch (s_calib.phase) {
|
||||
case PH_HELLO:
|
||||
if (event == GUI_EVENT_PAINT) {
|
||||
fb_text(FBW/2, 14, "Vychlaďte", TEXT_CENTER, 1);
|
||||
fb_text(FBW/2, 14, "Vychlaď", TEXT_CENTER, 1);
|
||||
fb_text(FBW/2, 24, "troubu", TEXT_CENTER, 1);
|
||||
}
|
||||
screen_menu(event, calib1_opts, calib1_cb);
|
||||
screen_menu(event, calib0_opts, calib0_cb);
|
||||
break;
|
||||
|
||||
case 1: // Heater is active, waiting for mark
|
||||
case 3:
|
||||
case PH_SAMPLE1: // Heater is active, waiting for mark
|
||||
case PH_SAMPLE2:
|
||||
if (event == GUI_EVENT_PAINT) {
|
||||
fb_text(FBW/2, 14, "Zapiš teplotu", TEXT_CENTER, 1);
|
||||
}
|
||||
if (phase == 1) {
|
||||
if (s_calib.phase == PH_SAMPLE1) {
|
||||
screen_menu(event, calib1_opts, calib1_cb);
|
||||
} else {
|
||||
screen_menu(event, calib3_opts, calib3_cb);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 4:
|
||||
if (phase == 2) {
|
||||
pT = &s_app.calib.temp1;
|
||||
case PH_TEMP1:
|
||||
case PH_TEMP2:
|
||||
if (s_calib.phase == PH_TEMP1) {
|
||||
pT = &s_calib.temp1;
|
||||
} else {
|
||||
pT = &s_app.calib.temp2;
|
||||
}
|
||||
|
||||
if (event == GUI_EVENT_PAINT) {
|
||||
fb_text(FBW/2, 14, phase == 2 ? "Teplota 1" : "Teplota 2", TEXT_CENTER, 1);
|
||||
SPRINTF(stmp, "%d°C", *pT);
|
||||
fb_text(FBW/2, 30, stmp, TEXT_CENTER | FONT_DOUBLE, 1);
|
||||
|
||||
fb_text(2, FBH - 8 * 3, "←→Nastav", 0, 1);
|
||||
fb_text(2, FBH - 8 * 2, "> Potvrdit", 0, 1);
|
||||
fb_text(2, FBH - 8 * 1, "» Zrušit", 0, 1);
|
||||
return;
|
||||
pT = &s_calib.temp2;
|
||||
}
|
||||
|
||||
if (push_time() > pdMS_TO_TICKS(500)) {
|
||||
@@ -139,40 +151,62 @@ void screen_manual_menu(GuiEvent event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (event == GUI_EVENT_KNOB_PLUS) {
|
||||
if (*pT < 500) {
|
||||
*pT += 1;
|
||||
input_sound_effect();
|
||||
request_paint();
|
||||
switch (event) {
|
||||
case GUI_EVENT_PAINT: {
|
||||
fb_text(FBW/2, 14, s_calib.phase == PH_TEMP1 ? "Teplota 1" : "Teplota 2", TEXT_CENTER, 1);
|
||||
SPRINTF(stmp, "%d°C", *pT);
|
||||
fb_text(FBW/2, 30, stmp, TEXT_CENTER | FONT_DOUBLE, 1);
|
||||
|
||||
fb_text(2, FBH - 8 * 3, "←→Nastav", 0, 1);
|
||||
fb_text(2, FBH - 8 * 2, "> Potvrdit", 0, 1);
|
||||
fb_text(2, FBH - 8 * 1, "» Zrušit", 0, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (event == GUI_EVENT_KNOB_MINUS) {
|
||||
if (*pT > 0) {
|
||||
input_sound_effect();
|
||||
*pT -= 1;
|
||||
request_paint();
|
||||
|
||||
case GUI_EVENT_KNOB_PLUS: {
|
||||
if (*pT < 500) {
|
||||
*pT += 1;
|
||||
input_sound_effect();
|
||||
request_paint();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (event == GUI_EVENT_KNOB_RELEASE) {
|
||||
s_app.calib.phase++;
|
||||
request_paint();
|
||||
|
||||
if (s_app.calib.phase == 5) {
|
||||
// TODO do the math
|
||||
PRINTF("Sample 1 %f, T1 %d\r\n", s_app.calib.sample1, s_app.calib.temp1);
|
||||
PRINTF("Sample 2 %f, T2 %d\r\n", s_app.calib.sample2, s_app.calib.temp2);
|
||||
case GUI_EVENT_KNOB_MINUS: {
|
||||
if (*pT > 0) {
|
||||
input_sound_effect();
|
||||
*pT -= 1;
|
||||
request_paint();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
float corrected1 = c_to_val((float) s_app.calib.temp1);
|
||||
float corrected2 = c_to_val((float) s_app.calib.temp2);
|
||||
case GUI_EVENT_KNOB_RELEASE: {
|
||||
next_phase();
|
||||
request_paint();
|
||||
|
||||
float a = ;
|
||||
float b = ;
|
||||
if (s_calib.phase == PH_DONE) {
|
||||
app_heater_manual_override(-1);
|
||||
// TODO do the math
|
||||
PRINTF("Sample 1 %f, T1 %d\r\n", s_calib.sample1, s_calib.temp1);
|
||||
PRINTF("Sample 2 %f, T2 %d\r\n", s_calib.sample2, s_calib.temp2);
|
||||
|
||||
// TODO set and persist calibration
|
||||
float corrected1 = c_to_val((float) s_calib.temp1);
|
||||
float corrected2 = c_to_val((float) s_calib.temp2);
|
||||
|
||||
float a = (corrected1 - corrected2) / (s_calib.sample1 - s_calib.sample2);
|
||||
float b = corrected1 - a * s_calib.sample1;
|
||||
|
||||
app_temp_set_calib(a, b);
|
||||
} else {
|
||||
app_heater_manual_override(100);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case PH_DONE:
|
||||
if (event == GUI_EVENT_PAINT) {
|
||||
fb_text(FBW/2, 14, "Hotovo", TEXT_CENTER, 1);
|
||||
fb_text(FBW/2, 36, "→Hlavní menu", TEXT_CENTER, 1);
|
||||
@@ -182,5 +216,4 @@ void screen_manual_menu(GuiEvent event)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
static const char* main_menu_opts[] = {
|
||||
"Ruční režim",
|
||||
"Kalibrace",
|
||||
"Programy",
|
||||
"Diagnostika",
|
||||
// "Programy",
|
||||
// "Diagnostika",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ static void main_menu_cb(int opt) {
|
||||
switch_screen(screen_manual, true);
|
||||
break;
|
||||
case 1:
|
||||
// TODO
|
||||
switch_screen(screen_calibration, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+42
-28
@@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "screen_menu.h"
|
||||
#include "app_gui.h"
|
||||
#include "FreeRTOS.h"
|
||||
@@ -12,40 +13,53 @@
|
||||
#include "ufb/framebuffer.h"
|
||||
#include "ufb/fb_text.h"
|
||||
|
||||
struct menu_state {
|
||||
int pos;
|
||||
int len;
|
||||
uint32_t change_time;
|
||||
uint32_t slide_end_time;
|
||||
uint16_t text_slide;
|
||||
void * last_opts;
|
||||
} s_menu;
|
||||
|
||||
void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) {
|
||||
if (event != GUI_EVENT_SCREEN_INIT && s_menu.last_opts != (void*) options) {
|
||||
// ensure the menu is properly inited when the options list changes.
|
||||
screen_menu(GUI_EVENT_SCREEN_INIT, options, cb);
|
||||
}
|
||||
|
||||
bool menu_changed = false;
|
||||
const uint32_t tickNow = xTaskGetTickCount();
|
||||
|
||||
struct menu_state *menu = &s_app.menu;
|
||||
|
||||
switch (event) {
|
||||
case GUI_EVENT_SCREEN_INIT:
|
||||
menu->pos = 0;
|
||||
menu->len = 0;
|
||||
menu->change_time = tickNow;
|
||||
menu->text_slide = 0;
|
||||
memset(&s_menu, 0, sizeof(s_menu));
|
||||
s_menu.last_opts = (void*) options;
|
||||
|
||||
s_menu.change_time = tickNow;
|
||||
|
||||
// count options
|
||||
const char **opt = options;
|
||||
while (*opt) {
|
||||
menu->len++;
|
||||
s_menu.len++;
|
||||
opt++;
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_EVENT_SCREEN_TICK:
|
||||
// long text sliding animation
|
||||
if (tickNow - menu->change_time >= pdMS_TO_TICKS(500)) {
|
||||
const uint32_t textlen = utf8_strlen(options[menu->pos]) * 6;
|
||||
if (tickNow - s_menu.change_time >= pdMS_TO_TICKS(500)) {
|
||||
const uint32_t textlen = utf8_strlen(options[s_menu.pos]) * 6;
|
||||
if (textlen >= FBW - 2) {
|
||||
if (textlen - menu->text_slide > FBW - 1) {
|
||||
menu->text_slide += 1;
|
||||
if (textlen - menu->text_slide >= FBW - 1) {
|
||||
menu->slide_end_time = tickNow;
|
||||
if (textlen - s_menu.text_slide > FBW - 1) {
|
||||
s_menu.text_slide += 1;
|
||||
if (textlen - s_menu.text_slide >= FBW - 1) {
|
||||
s_menu.slide_end_time = tickNow;
|
||||
}
|
||||
} else if (tickNow - menu->slide_end_time >= pdMS_TO_TICKS(500)) {
|
||||
menu->change_time = tickNow;
|
||||
menu->slide_end_time = 0;
|
||||
menu->text_slide = 0;
|
||||
} else if (tickNow - s_menu.slide_end_time >= pdMS_TO_TICKS(500)) {
|
||||
s_menu.change_time = tickNow;
|
||||
s_menu.slide_end_time = 0;
|
||||
s_menu.text_slide = 0;
|
||||
}
|
||||
request_paint();
|
||||
}
|
||||
@@ -53,13 +67,13 @@ void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) {
|
||||
break;
|
||||
|
||||
case GUI_EVENT_PAINT:
|
||||
for (int i = 0; i < menu->len; i++) {
|
||||
for (int i = 0; i < s_menu.len; i++) {
|
||||
// is the row currently rendered the selected row?
|
||||
const bool is_selected = menu->pos == i;
|
||||
const bool is_selected = s_menu.pos == i;
|
||||
const fbcolor_t color = !is_selected; // text color - black if selected, because it's inverted
|
||||
const fbpos_t y = 27 + i * 10;
|
||||
fb_rect(0, y, FBW, 10, !color);
|
||||
fb_text(1 - (is_selected ? menu->text_slide : 0), y + 1, options[i], FONT_5X7, color);
|
||||
fb_text(1 - (is_selected ? s_menu.text_slide : 0), y + 1, options[i], FONT_5X7, color);
|
||||
// ensure the text doesn't touch the edge (looks ugly)
|
||||
fb_vline(FBW - 1, y, 10, !color);
|
||||
fb_vline(0, y, 10, !color);
|
||||
@@ -69,28 +83,28 @@ void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) {
|
||||
// the button is held! release is what activates the button
|
||||
case GUI_EVENT_KNOB_RELEASE:
|
||||
input_sound_effect();
|
||||
cb(menu->pos);
|
||||
cb(s_menu.pos);
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KNOB_PLUS:
|
||||
if (menu->pos < menu->len - 1) {
|
||||
menu->pos++;
|
||||
if (s_menu.pos < s_menu.len - 1) {
|
||||
s_menu.pos++;
|
||||
menu_changed = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KNOB_MINUS:
|
||||
if (menu->pos > 0) {
|
||||
menu->pos--;
|
||||
if (s_menu.pos > 0) {
|
||||
s_menu.pos--;
|
||||
menu_changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (menu_changed) {
|
||||
menu->change_time = tickNow;
|
||||
menu->text_slide = 0;
|
||||
menu->slide_end_time = 0;
|
||||
s_menu.change_time = tickNow;
|
||||
s_menu.text_slide = 0;
|
||||
s_menu.slide_end_time = 0;
|
||||
input_sound_effect();
|
||||
request_paint();
|
||||
}
|
||||
|
||||
@@ -66,6 +66,8 @@ static inline void heaterExitCritical() {
|
||||
}
|
||||
|
||||
void app_heater_manual_override(int percent) {
|
||||
PRINTF("Set manual override: %d\r\n", percent);
|
||||
|
||||
heaterEnterCritical();
|
||||
PID_SetCtlMode(&state.pid, PID_MANUAL);
|
||||
state.manual_override = percent;
|
||||
|
||||
+80
-29
@@ -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;
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
|
||||
void app_analog_init();
|
||||
|
||||
float val_to_c(float val);
|
||||
float c_to_val(float c);
|
||||
|
||||
void app_temp_set_calib(float a, float b);
|
||||
|
||||
/**
|
||||
* Update temperature measurement.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user