Got all interactive menu entry to work

+ added tresholds
* kinda fixed encoder button trigger two times
This commit is contained in:
Steins7 2020-02-11 23:20:00 +01:00
parent 9523dc8a78
commit b563f08ecb
4 changed files with 375 additions and 63 deletions

View File

@ -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);

View File

@ -14,62 +14,83 @@ 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);
// set temp read flag
read_flag = 1;
}
static void enc_button_cb(void) {
count = !count;
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);
// initilize filter
for(int i=0; i<3; ++i) {
int16_t tmp = read_temp(i);
for(int j=0; j<FILTER_LENGTH; ++j) {
temp_filter[i][j] = tmp;
}
}
// 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);
// setup ui
if(ui_init(TIM4, TIM3, &vars)) return -1;
// start timed interruption
timer_tick_init(TIM2, 1000, timeout_cb);
@ -77,37 +98,49 @@ int main(void) {
// main loop
while(1){
// update T1
//data = adc_read(ADC1, 0);
//data -= adc_read(ADC1, 1);
// process sensor values
if(read_flag) {
// clear flag
read_flag = 0;
//voltage = ((data*4) << 8)/4095;
//temp = ((voltage - 0x73) << 8)/0x9;
// shift filter queue
int32_t sum = 0;
for(int i=0; i<(FILTER_LENGTH-1); ++i) {
temp_filter[sensor_id][i] = temp_filter[sensor_id][i+1];
sum += temp_filter[sensor_id][i];
}
//uint32_t pin = io_read(GPIOB, PIN_8);
//if(!pin) count = !count;
if(count) update_temp(T1, (int16_t)TIM4->CNT/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;

237
src/ui.c
View File

@ -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);
}

View File

@ -3,6 +3,7 @@
// drivers headers
#include "drivers/lcd.h"
#include "drivers/timer.h"
// standard headers
#include <stdint.h>
@ -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