Compare commits

..

10 Commits

Author SHA1 Message Date
07c922a04a Fixed major bug with filter
* changed relay GPIO as a temporary measure
2020-02-22 23:26:08 +01:00
2125e4a2e8
Create LICENSE 2020-02-21 18:37:42 +01:00
4dc100dc18 Merge branch 'master' of https://github.com/Steins7/FanMonitor 2020-02-21 18:27:25 +01:00
3d254c5931 Added EasyEDA files 2020-02-21 18:26:53 +01:00
be7cceb0b5
Create README.md 2020-02-21 18:22:38 +01:00
9ee81f0024 Got th UI to work as intended
* fixed global variable not being initialized
* fixed fan control formulas
* inverted encoder counting
+ added 3D support for adapter
2020-02-21 17:50:45 +01:00
c7af2f2b59 First modeling of power supply support
* cleaned cad folder by creating subfolders
2020-02-17 22:03:04 +01:00
b563f08ecb Got all interactive menu entry to work
+ added tresholds
* kinda fixed encoder button trigger two times
2020-02-11 23:20:00 +01:00
9523dc8a78 Fixed non-blocking delays not working
* fixed ARR value
- removed reset function
2020-02-08 12:48:52 +01:00
3682d10a27 Got external interrupts to work
* fixed io driver
* fixed encoder 3D print
2020-02-04 19:50:01 +01:00
16 changed files with 769 additions and 151 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Steins7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

27
README.md Normal file
View File

@ -0,0 +1,27 @@
# FanMonitor
Advanced controller for industrial fan
This repository contains all the files used for the creation of a custom industrial fan controller.
## Context
__Two spaces__ have to be maintained at the lowest temperature possible (to a certain extent).
For that purpose, an __industrial fan__ (controlled by a 220V relay) is used. The fan is __physically moved__ from one space to the other depending on the needs (the air intake is outside).
The goal is to control the fan automatically with 3 temperature sensors, one in each space and one near the air intake. The 3 current tempratures have to be display for the user to check things if needed. The environnement is also very dusty so the system has to be contained in a closed box.
## System
The system is made off three main part :
- a generic usb charger for the voltage supply
- a main board build aroud a __STM32F103__ microprocessor
- a screen based on the __HD44780__ driver
The box's plans are not depicted here since they are very simple (a few holes, no more, no less).
Appart form that, you will find here all the code - created from scratch since I didn't want to use ST's HAL and anyways it's funnier this way - and the 3D models used. All the documentation is also there. You may also find (if I didnt forget to put it there) EasyEDA files for the main board PCB.
## How to compile
The code uses the __GNU toolchain__, whith __gcc__ and __gdb__ for AMR. __OpenOCD__ is used for the SWD handling, through a __STLinkv2__. Don't forget to install __arm-none-eabi-newlib__ if you want things to work.
Finaly, there is a RELEASE tag in the Makefile if you want to optimise and remove debug.

41
cad/adapter/adapter.scad Normal file
View File

@ -0,0 +1,41 @@
$fn = 100;
// element dimensions
w = 60;
d = 30;
h = 4;
// aditionnal parameters
e = 5;
// internal values
we = w + e;
de = d + e;
translate([0,0,e/2]);
cube([we,de,e/3], true);
module tab() {
translate([-e/4,0,(e/3+h)/2]) {
cube([e/2,2*e,h], true);
translate([-1.75*e,-e,h/2])
rotate([0,-90,-90])
linear_extrude(height = 2*e)
polygon([[0,1.2*e],[e/4,1.2*e],[0,2*e],[e/2,2*e]],
[[0,1,3,2]]);
}
}
translate([we/2,-de/2+e,0])
tab();
translate([-we/2,0,0])
rotate([0,0,180])
tab();
translate([8,de/2,0])
rotate([0,0,90])
tab();
translate([0,-de/2,0])
rotate([0,0,-90])
tab();

View File

@ -1,4 +1,4 @@
//$fn = 100;
$fn = 100;
r = 12;
h = 12;
@ -25,9 +25,9 @@ difference() {
cube([3,2*center_r,h], center=true);
}
difference() {
translate([0,0,0.7])
translate([0,0,3])
cylinder(h=h, r=0.8*r, center=true);
translate([0,0,0.7])
translate([0,0,3])
cylinder(h=h, r=1.4*center_r, center=true);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,6 +1,5 @@
/****************************************************************************
* IRQ Priority
****************************************************************************/
//------------------------------------------------------------------------------
/* priorities */
#define EXTI0_IRQ_PRIORITY 8
#define EXTI1_IRQ_PRIORITY 8
#define EXTI2_IRQ_PRIORITY 8
@ -28,63 +27,3 @@
#define ADC1_2_IRQ_PRIORITY 5
/****************************************************************************
* USART Pin and use configuration
****************************************************************************/
//#define USE_USART1
//#define USART1_GPIO_PORT
//#define USART1_GPIO_PINS
// USART2: Tx --> PA2, Rx --> PA3
//#define USE_USART2
//#define USART2_GPIO_PORT _GPIOA
//#define USART2_GPIO_PINS PIN_2|PIN_3
//#define USE_USART6
//#define USART6_GPIO_PORT
//#define USART6_GPIO_PINS
/****************************************************************************
* I2C Pin and use configuration
****************************************************************************/
// I2C1 : SCL --> PB8, SDA --> PB9
//#define USE_I2C1
//#define I2C1_GPIO_PORT _GPIOB
//#define I2C1_GPIO_PINS PIN_8|PIN_9
//#define USE_I2C2
//#define I2C2_GPIO_PORT
//#define I2C2_GPIO_PINS
//#define USE_I2C3
//#define I2C3_GPIO_PORT
//#define I2C3_GPIO_PINS
/****************************************************************************
* SPI pin and use configuration
****************************************************************************/
// SPI1 pins : LCD_SCK --> D13 --> PA5 : SPI1_SCK
// LCD_MOSI --> D11 --> PA7 : SPI1_MOSI
//#define USE_SPI1
//#define SPI1_GPIO_PORT _GPIOA
//#define SPI1_GPIO_PINS PIN_5|PIN_7
//#define USE_SPI2
//#define SPI2_GPIO_PORT
//#define SPI2_GPIO_PINS
//#define USE_SPI3
//#define SPI3_GPIO_PORT
//#define SPI3_GPIO_PINS
//#define USE_SPI4
//#define SPI4_GPIO_PORT
//#define SPI4_GPIO_PINS
//#define USE_SPI5
//#define SPI5_GPIO_PORT
//#define SPI5_GPIO_PINS

View File

@ -17,31 +17,26 @@ static OnIO io_cb[16]={
void EXTI0_IRQHandler() {
if (io_cb[0]) (io_cb[0])();
EXTI->PR = 1<<0;
}
void EXTI1_IRQHandler() {
if (io_cb[1]) (io_cb[1])();
EXTI->PR = 1<<1;
}
void EXTI2_IRQHandler() {
if (io_cb[2]) (io_cb[2])();
EXTI->PR = 1<<2;
}
void EXTI3_IRQHandler() {
if (io_cb[3]) (io_cb[3])();
EXTI->PR = 1<<3;
}
void EXTI4_IRQHandler() {
if (io_cb[4]) (io_cb[4])();
EXTI->PR = 1<<4;
}
@ -143,9 +138,9 @@ int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint16_t pin_cfg, OnIO cb) {
else if (gpio == GPIOE) port_mask = SYSCFG_EXTI_PE_MASK;
// setup external IRQ lines
uint16_t afio_mask;
uint64_t afio_mask;
for(int i=0; i<4; ++i) {
afio_mask = ((pin_mask & (0xFFFF << i)) >> i) * port_mask;
afio_mask = ((pin_mask & (0xFFFFll << (i*16))) >> (i*16)) * port_mask;
if(afio_mask) AFIO->EXTICR[i] |= afio_mask;
}
@ -204,7 +199,6 @@ int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint16_t pin_cfg, OnIO cb) {
break;
default:
return -1; //impossible to get there
}
}
}

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

@ -108,19 +108,22 @@ int timer_wait_ms(TIM_TypeDef* tmr, uint16_t ms, OnTick cb) {
else if (tmr == TIM4) RCC->APB1ENR |= 1<<2;
else return -1; // no such timer
}
// set period
tmr->ARR = 0xFFFFFFFF;
} else { //non-blocking
if(timer_config_cb(tmr, &clk, cb)) return -1;
// set period
tmr->ARR = ms-1;
}
// set mode
tmr->CR1 |= (1<<7); //buffering
tmr->CR1 = (1<<7) | (1<<2); //buffering and update settings
tmr->CR1 |= (1<<3); //one pulse mode
// set period
tmr->ARR = 0xFFFFFFFF;
// set prescaler 1us
// set prescaler 1ms
tmr->PSC = 8*(clk/1000)-1; //PSC = clk/f - 1 | don't know why 8 times..
timer_start(tmr);
@ -149,17 +152,20 @@ int timer_wait_us(TIM_TypeDef* tmr, uint16_t us, OnTick cb) {
else return -1; // no such timer
}
// set period
tmr->ARR = 0xFFFFFFFF;
} else { //non-blocking
if(timer_config_cb(tmr, &clk, cb)) return -1;
// set period
tmr->ARR = us-1;
}
// set mode
tmr->CR1 |= (1<<7); //buffering
tmr->CR1 = (1<<7) | (1<<2); //buffering and update settings
tmr->CR1 |= (1<<3); //one pulse mode
// set period
tmr->ARR = 0xFFFFFFFF;
// set prescaler 1us
tmr->PSC = 8*(clk/1000000)-1; //PSC = clk/f - 1 | don't know why 8 times..
@ -229,8 +235,8 @@ int timer_tick_init(TIM_TypeDef *tmr, uint16_t tick_ms, OnTick cb) {
tmr->SR &= !1;
// set mode
tmr->CR1 = (1<<7); //buffering
tmr->DIER = (1<<0); //Enable interrupts
tmr->CR1 = (1<<7) | (1<<2); //buffering and update settings
tmr->DIER = (1<<0); //Enable interrupts
// set prescaler 1ms
tmr->PSC = 8*(clk/1000)-1; //PSC = clk/f - 1 | don't know why 8 times...
@ -294,9 +300,9 @@ int timer_enc_init(TIM_TypeDef* tmr) {
tmr->CCMR1 |= 0x9;
tmr->CCMR1 |= 0x9 << 8;
// enable input channels
tmr->CCER |= 0x1;
tmr->CCER |= 0x1 << 4;
// enable input channels and invert them //TODO add an otpion for that
tmr->CCER |= 0x3;
tmr->CCER |= 0x3 << 4;
tmr->CR1 |= 0x1; //enable timer

View File

@ -42,6 +42,10 @@ void timer_start(TIM_TypeDef *tmr);
void timer_stop(TIM_TypeDef *tmr);
//------------------------------------------------------------------------------
/** timer_enc_init
* setup timer to read encoder output and keep track of it's position in the
* CNT register whithout using CPU time
*/
int timer_enc_init(TIM_TypeDef* tmr);
//------------------------------------------------------------------------------

View File

@ -14,100 +14,143 @@ 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 = {
{},
5,
2,
{},
1,
0
};
//------------------------------------------------------------------------------
/* Timer IRQ */
static void timeout_cb(void) {
io_write(GPIOC, val, PIN_13);
io_write(GPIOB, val, PIN_12);
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) {
//initialize variables
val = 0; //debug led
read_flag = 0;
sensor_id = 0;
// 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;
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 GPIO for relay
if(io_configure(GPIOB, PIN_11, IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0))
return -1;
io_write(GPIOB, 1, PIN_11);
// 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; j<FILTER_LENGTH; ++j) {
temp_filter[i][j] = tmp;
}
}
// setup ui
if(ui_init(TIM4, TIM3, &vars)) return -1;
// start timed interruption
timer_tick_init(TIM2, 1000, timeout_cb);
timer_start(TIM2);
// main loop
while(1){
// update T1
//data = adc_read(ADC1, 0);
//data -= adc_read(ADC1, 1);
//voltage = ((data*4) << 8)/4095;
//temp = ((voltage - 0x73) << 8)/0x9;
// process sensor values
if(read_flag) {
uint32_t pin = io_read(GPIOB, PIN_8);
if(!pin) count = !count;
if(count) update_temp(T1, (int16_t)TIM4->CNT/2);
// clear flag
read_flag = 0;
// update T2
data = adc_read(ADC1, 2);
data -= adc_read(ADC1, 3);
// 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];
}
voltage = ((data*4) << 8)/4095;
temp = ((voltage - 0x73) << 8)/0x9;
// calculate temp value
temp_filter[sensor_id][FILTER_LENGTH-1] = read_temp(sensor_id);
update_temp(T2, temp);
// apply filter
sum += temp_filter[sensor_id][FILTER_LENGTH-1];
vars.temps[sensor_id] = (sum/FILTER_LENGTH) >> 8;
// update T_ext
data = adc_read(ADC1, 4);
data -= adc_read(ADC1, 5);
// print new value
ui_update_temp(sensor_id);
voltage = ((data*4) << 8)/4095;
temp = ((voltage - 0x73) << 8)/0x9;
// switch to next sensor
sensor_id++;
sensor_id = sensor_id%3;
update_temp(T_EXT, temp);
// set fan state
if((vars.temps[vars.silo] - vars.temps[T_EXT]) >=
vars.start_treshold) {
if(!vars.fan) {
io_set(GPIOB, PIN_11);
vars.fan = 1;
}
} else if((vars.temps[vars.silo] - vars.temps[T_EXT]) <=
vars.stop_treshold) {
if(vars.fan) {
io_clear(GPIOB, PIN_11);
vars.fan = 0;
}
}
}
// update every 0.2 seconds
timer_wait_ms(TIM1, 200, 0);
ui_update();
//timer_wait_ms(TIM1, 200, 0);
}
return 0;

255
src/ui.c
View File

@ -1,21 +1,267 @@
#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"
};
static const char* ui_interact[] = {
" lue: ""\xDF""C",
" reelle: ""\xDF""C"
};
//------------------------------------------------------------------------------
/* 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]);
}
void 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 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 interact(uint8_t entry, uint8_t* entry_val) {
while(!button_update) {
lcd_set_cursor(10,0);
lcd_print(" ");
lcd_set_cursor(10,0);
lcd_set_cursor(10,0);
lcd_print(" ");
}
}
//------------------------------------------------------------------------------
/* 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<1000000; ++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(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
if(sel == UI_CAL_T_EXT || sel == UI_CAL_T1
|| sel == UI_CAL_T2) {
show_bg(ui_interact);
}
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) {
update_entry(UI_RETURN, vars->silo);
}
// show start value if needed
if(sel == UI_SILO || sel == UI_START) {
update_entry(UI_SILO, vars->start_treshold);
}
// show start value if needed
if(sel == UI_START || sel == UI_STOP) {
update_entry(UI_START, vars->stop_treshold);
}
}
break;
//---------------------
case UI_INTERACT:
switch(sel) {
case UI_SILO:
change_value(UI_SILO, &vars->silo, 2);
break;
case UI_START:
change_value(UI_START, &vars->start_treshold, 9);
break;
case UI_STOP:
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 +287,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 3
//------------------------------------------------------------------------------
/** 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

View File

@ -6,5 +6,7 @@
uint32_t num2str(char *s, int number, uint8_t base);
//void print_num(int number,
#endif