calibration mostly working

This commit is contained in:
2023-04-09 19:34:32 +02:00
parent 6749bb5f52
commit 1331460ecb
7 changed files with 224 additions and 136 deletions
+1 -18
View File
@@ -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;
+91 -58
View File
@@ -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;
}
}
+3 -3
View File
@@ -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
View File
@@ -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();
}