From b563f08ecbe949ea1dff416f2db08f549923417a Mon Sep 17 00:00:00 2001 From: Steins7 Date: Tue, 11 Feb 2020 23:20:00 +0100 Subject: [PATCH] Got all interactive menu entry to work + added tresholds * kinda fixed encoder button trigger two times --- src/drivers/lcd.c | 1 + src/main.c | 143 ++++++++++++++++----------- src/ui.c | 239 +++++++++++++++++++++++++++++++++++++++++++++- src/ui.h | 55 ++++++++++- 4 files changed, 375 insertions(+), 63 deletions(-) diff --git a/src/drivers/lcd.c b/src/drivers/lcd.c index 99abdca..35754fc 100644 --- a/src/drivers/lcd.c +++ b/src/drivers/lcd.c @@ -161,6 +161,7 @@ void lcd_print(const char* txt) { io_write(GPIOA, LCD_MODE_DATA, PIN_10); // send the caracters until end of string + // TODO implement '\n' while(*c != '\0') { wait_for_ready(); write_byte(*c); diff --git a/src/main.c b/src/main.c index 5e5a928..eecf62a 100644 --- a/src/main.c +++ b/src/main.c @@ -14,100 +14,133 @@ Clock_t sysclks; #include "ui.h" //------------------------------------------------------------------------------ -/* static variables */ -int val = 0; -int count = 0; -uint16_t data = 0; -int16_t voltage = 0; -int16_t temp = 0; +/* static variables */; +int val = 0; //debug led +int read_flag = 0; +int sensor_id = 0; + +// low_pass filter +#define FILTER_LENGTH 10 +int16_t temp_filter[3][FILTER_LENGTH] = {}; + +// adc channels +uint8_t channels[3][2] = { + {4, 5}, + {0, 1}, + {2, 3} +}; + +vars_t vars = { + {}, + 2, + 2, + {}, + 1, + 0 +}; //------------------------------------------------------------------------------ /* Timer IRQ */ static void timeout_cb(void) { - io_write(GPIOC, val, PIN_13); - io_write(GPIOB, val, PIN_12); + //io_write(GPIOC, val, PIN_13); val = !val; - data = adc_read(ADC1, 2); - data -= adc_read(ADC1, 3); -} -static void enc_button_cb(void) { - count = !count; + // set temp read flag + read_flag = 1; + } + +int16_t read_temp(uint8_t id) { + // get ADC values + uint32_t data = 0; + data = adc_read(ADC1, channels[id][0]); + data -= adc_read(ADC1, channels[id][1]); + + int16_t voltage = ((data*4) << 8)/4095 ; + + return ((voltage - 0x73) << 8)/0x9 + vars.facs[id][0]; } //------------------------------------------------------------------------------ /* main function */ int main(void) { + // configure clocks (necessary before using timers) rcc_config_clock(CLOCK_CONFIG_PERFORMANCE, &sysclks); // configure GPIO for LED if(io_configure(GPIOC, PIN_13, IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0)) - return 0; + return -1; if(io_configure(GPIOB, PIN_12, IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0)) - return 0; + return -1; io_write(GPIOC, 1, PIN_13); io_write(GPIOB, 1, PIN_12); // configure GPIOS for temperature sensors if(io_configure(GPIOA, PIN_0 | PIN_1 | PIN_2 | PIN_3 | PIN_4 | PIN_5, - IO_MODE_INPUT | IO_IN_ANALOG, 0)) return 0; - if(adc_init(ADC1)) return 0; + IO_MODE_INPUT | IO_IN_ANALOG, 0)) return -1; + if(adc_init(ADC1)) return -1; - // configure lcd - lcd_init(TIM1, 16, 2); - lcd_send_cmd(LCD_CUR_HOME); - lcd_print("SILO:1 Te: 18""\xDF""C"); - lcd_set_cursor(0,1); - lcd_print("1: 25""\xDF""C 2: 26""\xDF""C"); - lcd_send_cmd(LCD_DISP_CTRL | LCD_CTRL_DISP_ON | LCD_CTRL_CUR_OFF | - LCD_CTRL_BLINK_OFF); - - // configure encoder - io_configure(GPIOB, PIN_6 | PIN_7, IO_MODE_INPUT | IO_IN_FLOATING, 0); - timer_enc_init(TIM4); - - io_configure(GPIOB, PIN_8, IO_MODE_INPUT | IO_IN_PULL_UP | - IO_IRQ_EDGE_FALL, enc_button_cb); + // initilize filter + for(int i=0; i<3; ++i) { + int16_t tmp = read_temp(i); + for(int j=0; jCNT/2); + // calculate temp value + temp_filter[sensor_id][FILTER_LENGTH-1] = read_temp(sensor_id); - // update T2 - data = adc_read(ADC1, 2); - data -= adc_read(ADC1, 3); + // apply filter + sum += temp_filter[sensor_id][FILTER_LENGTH-1]; + vars.temps[sensor_id] = (sum/FILTER_LENGTH) >> 8; - voltage = ((data*4) << 8)/4095; - temp = ((voltage - 0x73) << 8)/0x9; + // print new value + ui_update_temp(sensor_id); - update_temp(T2, temp); + // switch to next sensor + sensor_id++; + sensor_id = sensor_id%3; - // update T_ext - data = adc_read(ADC1, 4); - data -= adc_read(ADC1, 5); - - voltage = ((data*4) << 8)/4095; - temp = ((voltage - 0x73) << 8)/0x9; - - update_temp(T_EXT, temp); + // set fan state + if((vars.temps[vars.silo] - vars.temps[T_EXT]) >= + vars.start_treshold) { + vars.fan = 1; + io_set(GPIOB, PIN_12); + io_clear(GPIOC, PIN_13); + } else if((vars.temps[T_EXT] - vars.temps[vars.silo]) >= + vars.stop_treshold) { + vars.fan = 0; + io_clear(GPIOB, PIN_12); + io_set(GPIOC, PIN_13); + } + } // update every 0.2 seconds - timer_wait_ms(TIM1, 200, 0); + ui_update(); + //timer_wait_ms(TIM1, 200, 0); } return 0; diff --git a/src/ui.c b/src/ui.c index 5a39df1..2cc0a8c 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1,21 +1,251 @@ #include "ui.h" +//------------------------------------------------------------------------------ +/* control variables */ +static int state; +static volatile int button_update; +static int sel, prev_sel; +static TIM_TypeDef* enc; +static TIM_TypeDef* tim; +static vars_t* vars; + +/* data variables */ +static const char* ui_default[] = { + "SILO: Te: ""\xDF""C", + "1: ""\xDF""C 2: ""\xDF""C" +}; +static const char* ui_menu[] = { + " 1-Retour", + " 2-Silo:", + " 3-Start:", + " 4-Stop:", + " 5-Calibrer Te", + " 6-Calibrer T1", + " 7-Calibrer T2", + " 8-Test ventil", + " 1-Retour" +}; + +//------------------------------------------------------------------------------ +/* internal functions */ +void show_bg(const char** bg) { + lcd_send_cmd(LCD_CLEAR); + lcd_send_cmd(LCD_CUR_HOME); + lcd_print(bg[0]); + lcd_set_cursor(0,1); + lcd_print(bg[1]); +} + +//------------------------------------------------------------------------------ +/* timeout timer cb */ +static void ui_sleep(void) { + state = UI_SLEEP; +} + +/* encoder button gpio cb */ +static void ui_button_cb(void) { + for(int i=0; i<10000; ++i); //avoid double trigger + timer_start(tim); + button_update = 1; +} + +//------------------------------------------------------------------------------ +/* main functions */ +int ui_init(TIM_TypeDef* encoder, TIM_TypeDef* timeout, vars_t* vars_p) { + // save parameters + enc = encoder; + tim = timeout; + vars = vars_p; + + // configure lcd + lcd_init(TIM1, 16, 2); + lcd_send_cmd(LCD_CUR_HOME); + lcd_print(ui_default[0]); + lcd_set_cursor(0, 1); + lcd_print(ui_default[1]); + lcd_send_cmd(LCD_DISP_CTRL | LCD_CTRL_DISP_ON | LCD_CTRL_CUR_OFF | + LCD_CTRL_BLINK_OFF); + + // configure encoder + io_configure(GPIOB, PIN_6 | PIN_7, IO_MODE_INPUT | IO_IN_FLOATING, 0); + timer_enc_init(enc); //TODO fix weird behaviour around 0 + + io_configure(GPIOB, PIN_8, IO_MODE_INPUT | IO_IN_PULL_UP | + IO_IRQ_EDGE_FALL, ui_button_cb); + + // setup state variables + state = UI_SLEEP; + sel = 0; + prev_sel = -1; + + return 0; +} + +void ui_update_entry(uint8_t prev_entry, uint8_t value) { + // get vlaue in str form + char str[8]; //too long to be sure + num2str(str, value, 10); + + // print value in the correct position + if(sel == prev_entry) lcd_set_cursor(14, 1); + else lcd_set_cursor(14, 0); + lcd_print(str); + +} + +void ui_change_value(uint8_t entry, uint8_t* entry_val, int max) { + int local_val = *entry_val; + lcd_set_cursor(14,0); + while(!button_update) { + local_val = ((enc->CNT/2)%max) + 1; + char str[8]; + num2str(str, local_val, 10); + lcd_print(str); + lcd_set_cursor(14,0); + timer_wait_ms(TIM1, 200, 0); + } + *entry_val = local_val; +} + + + +void ui_update(void) { + // manage button press + if(button_update) { + button_update = 0; + + switch(state) { + //------------------------- + case UI_DEFAULT: + // reset encoder and previous values + timer_start(enc); + sel = 0; + prev_sel = -1; + + // go to menu screen + state = UI_MENU; + break; + //------------------------- + case UI_MENU: + // go back to default screen whith return + if(sel == UI_RETURN) { + show_bg(ui_default); + lcd_set_cursor(5,0); + char str[4]; + num2str(str, vars->silo, 10); + lcd_print(str); + + state = UI_DEFAULT; + for(int i=0; i<3; ++i) ui_update_temp(i); + break; + } + + // otherwise interact with option + lcd_send_cmd(LCD_DISP_CTRL | LCD_CTRL_DISP_ON | + LCD_CTRL_CUR_ON | LCD_CTRL_BLINK_OFF); + timer_start(enc); + state = UI_INTERACT; + break; + //------------------------- + case UI_INTERACT: + state = UI_MENU; + lcd_send_cmd(LCD_DISP_CTRL | LCD_CTRL_DISP_ON | + LCD_CTRL_CUR_OFF | LCD_CTRL_BLINK_OFF); + break; + //------------------------- + case UI_SLEEP: + // re-enable screen + lcd_send_cmd(LCD_DISP_CTRL | LCD_CTRL_DISP_ON | LCD_CTRL_CUR_OFF + | LCD_CTRL_BLINK_OFF); + + + // re-enable timeout system + timer_wait_ms(tim, TIMEOUT_LENGHT, ui_sleep); + + // go back to default screen + show_bg(ui_default); + lcd_set_cursor(5,0); + char str[4]; + num2str(str, vars->silo, 10); + lcd_print(str); + + state = UI_DEFAULT; + for(int i=0; i<3; ++i) ui_update_temp(i); + break; + } + } + + // manage dynamic draw + switch(state) { + //--------------------- + case UI_MENU: + // get current encoder value + sel = (enc->CNT/2)%(MENU_LENGHT+1); + + // refresh menu if selected item changed + if(sel != prev_sel) { + prev_sel = sel; + timer_start(tim); //refresh timeout timer + show_bg(ui_menu + sel); + lcd_send_cmd(LCD_CUR_HOME); + lcd_print_c(0x7E); + + // show silo value if needed + if(sel == UI_RETURN || sel == UI_SILO) { + ui_update_entry(UI_RETURN, vars->silo); + } + // show start value if needed + if(sel == UI_SILO || sel == UI_START) { + ui_update_entry(UI_SILO, vars->start_treshold); + } + // show start value if needed + if(sel == UI_START || sel == UI_STOP) { + ui_update_entry(UI_START, vars->stop_treshold); + } + } + break; + //--------------------- + case UI_INTERACT: + switch(sel) { + case UI_SILO: + ui_change_value(UI_SILO, &vars->silo, 2); + break; + case UI_START: + ui_change_value(UI_START, &vars->start_treshold, 9); + break; + case UI_STOP: + ui_change_value(UI_STOP, &vars->stop_treshold, 9); + break; + + + } + //--------------------- + case UI_DEFAULT: + break; + //-------------------- + case UI_SLEEP: + //TODO implement backlight off + lcd_send_cmd(LCD_DISP_CTRL | LCD_CTRL_DISP_OFF | LCD_CTRL_CUR_OFF + | LCD_CTRL_BLINK_OFF); + } +} + static uint8_t temp_pos[][2] = { {11, 0}, { 2, 1}, {11, 1}}; -void update_temp(uint8_t id, int16_t t) { - +void ui_update_temp(uint8_t id) { + if(state != UI_DEFAULT) return; + if(id > 2) return; //protect from overflow uint8_t* pos = temp_pos[id]; // prepare data char str[16]; //longer, in case of error - //t = t >> 8; // convert int into str - uint32_t nb = num2str(str, t, 10); + uint32_t nb = num2str(str, (vars->temps[id]), 10); // clear previous text lcd_set_cursor(pos[0],pos[1]); @@ -41,3 +271,4 @@ void update_temp(uint8_t id, int16_t t) { // write value lcd_print(str); } + diff --git a/src/ui.h b/src/ui.h index fd40280..4bcc2a0 100644 --- a/src/ui.h +++ b/src/ui.h @@ -3,6 +3,7 @@ // drivers headers #include "drivers/lcd.h" +#include "drivers/timer.h" // standard headers #include @@ -10,20 +11,66 @@ // project headers #include "utils.h" -/** temp - * list of all the temperature ids on the sreen +//------------------------------------------------------------------------------ + +#define TIMEOUT_LENGHT 20000 + +/** vars_t + * structure that contains all the variables needed by the ui and used or + * created elsewhere */ +typedef struct { + int16_t temps[3]; + uint8_t start_treshold; + uint8_t stop_treshold; + uint8_t facs[3][2]; + uint8_t silo; + uint8_t fan; +} vars_t; + +// ui enums, created to improve readability enum temp { T_EXT = 0, T1 = 1, T2 = 2 }; +enum ui_state { + UI_DEFAULT, + UI_MENU, + UI_INTERACT, + UI_SLEEP +}; + +enum ui_menu { + UI_RETURN = 0, + UI_SILO = 1, + UI_START = 2, + UI_STOP = 3, + UI_CAL_T_EXT = 4, + UI_CAL_T1 = 5, + UI_CAL_T2 = 6, + UI_TEST = 7 +}; + +#define MENU_LENGHT 7 + +//------------------------------------------------------------------------------ +/** ui_init + * init ui, using a timer for the encoder and another for the timeout delay + */ +int ui_init(TIM_TypeDef* encoder, TIM_TypeDef* timeout, vars_t* vars_p); + +/** ui_update + * update the graphical elements and manages the button press + * should be called quite often for a smooth usage + */ +void ui_update(void); + /** update_temp * update on the lcd the given value for the corresponding id */ -void update_temp(uint8_t id, int16_t t_ext); - +void ui_update_temp(uint8_t id); #endif