Added config error screen
+ added error management + added config error when failing to load
This commit is contained in:
parent
a3a2386dc2
commit
3fc3dbaae8
@ -52,8 +52,8 @@ impl SystemConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn load() -> Result<ConfigError, SystemConfig> {
|
pub fn load() -> Result<SystemConfig, ConfigError> {
|
||||||
unimplemented!();
|
Err(ConfigError::LoadError)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|||||||
@ -21,6 +21,12 @@ use crate::{
|
|||||||
config::{Menu, SystemConfig, FanOutput},
|
config::{Menu, SystemConfig, FanOutput},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/* GUI config */
|
||||||
|
|
||||||
|
pub const GUI_TICK_SEC: f32 = 0.2;
|
||||||
|
const GUI_ERROR_SEC: f32 = 0.8;
|
||||||
|
|
||||||
//---Temp Enum--------------------------------------------------------------------------------------
|
//---Temp Enum--------------------------------------------------------------------------------------
|
||||||
/// A simple enum to handle displaying temps on the GUI. Temperatures can be valid or not. An
|
/// A simple enum to handle displaying temps on the GUI. Temperatures can be valid or not. An
|
||||||
/// invalid temperature is displayed as "inval°C" whereas a valid temperature is displayed as
|
/// invalid temperature is displayed as "inval°C" whereas a valid temperature is displayed as
|
||||||
@ -75,6 +81,7 @@ pub enum GUIState {
|
|||||||
Off,
|
Off,
|
||||||
Idle,
|
Idle,
|
||||||
Menu,
|
Menu,
|
||||||
|
Error (&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Manages the lcd screen and inputs (encoder + button) and display relevant information. Can also
|
/// Manages the lcd screen and inputs (encoder + button) and display relevant information. Can also
|
||||||
@ -97,6 +104,7 @@ where
|
|||||||
p1_deg: Temp,
|
p1_deg: Temp,
|
||||||
p2_deg: Temp,
|
p2_deg: Temp,
|
||||||
should_refresh: bool,
|
should_refresh: bool,
|
||||||
|
blink_counter: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, Q, B> LCDGui<L, Q, B>
|
impl<L, Q, B> LCDGui<L, Q, B>
|
||||||
@ -126,6 +134,7 @@ where
|
|||||||
p1_deg: Temp::Invalid,
|
p1_deg: Temp::Invalid,
|
||||||
p2_deg: Temp::Invalid,
|
p2_deg: Temp::Invalid,
|
||||||
should_refresh: true,
|
should_refresh: true,
|
||||||
|
blink_counter: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(bl) = &mut gui.backlight { let _ = bl.set_high(); };
|
if let Some(bl) = &mut gui.backlight { let _ = bl.set_high(); };
|
||||||
@ -179,6 +188,11 @@ where
|
|||||||
state.update_config(config);
|
state.update_config(config);
|
||||||
self.menu.display(&mut self.lcd);
|
self.menu.display(&mut self.lcd);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
GUIState::Error (_) => {
|
||||||
|
self.state = GUIState::Idle;
|
||||||
|
self.lcd.clear();
|
||||||
|
self.should_refresh = true;
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
// manage encoder movement
|
// manage encoder movement
|
||||||
@ -211,6 +225,18 @@ where
|
|||||||
self.menu.movement_update(diff);
|
self.menu.movement_update(diff);
|
||||||
self.menu.display(&mut self.lcd);
|
self.menu.display(&mut self.lcd);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
GUIState::Error (err)=> {
|
||||||
|
self.blink_counter += 1;
|
||||||
|
|
||||||
|
if self.blink_counter as f32 * GUI_TICK_SEC >= 2.0*GUI_ERROR_SEC {
|
||||||
|
let _ = write!(self.lcd, "Erreur: ");
|
||||||
|
self.lcd.set_cursor_pos(0x40);
|
||||||
|
let _ = write!(self.lcd, "{}", err);
|
||||||
|
self.blink_counter = 0;
|
||||||
|
} else if self.blink_counter as f32 * GUI_TICK_SEC >= GUI_ERROR_SEC {
|
||||||
|
self.lcd.clear();
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
input_update
|
input_update
|
||||||
@ -239,6 +265,11 @@ where
|
|||||||
//TODO set display off ?
|
//TODO set display off ?
|
||||||
if let Some(bl) = &mut self.backlight { let _ = bl.set_low(); };
|
if let Some(bl) = &mut self.backlight { let _ = bl.set_low(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn display_error(&mut self, error: &'static str) {
|
||||||
|
self.state = GUIState::Error (error);
|
||||||
|
self.blink_counter = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_idle_screen<L: LCDScreen>(screen: &mut L, ext_deg: &Temp, p1_deg: &Temp, p2_deg: &Temp,
|
fn display_idle_screen<L: LCDScreen>(screen: &mut L, ext_deg: &Temp, p1_deg: &Temp, p2_deg: &Temp,
|
||||||
|
|||||||
97
src/main.rs
97
src/main.rs
@ -27,7 +27,7 @@ use stm32f1xx_hal::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
mod lcd_gui;
|
mod lcd_gui;
|
||||||
use lcd_gui::LCDGui;
|
use lcd_gui::{LCDGui, GUI_TICK_SEC};
|
||||||
|
|
||||||
mod utils;
|
mod utils;
|
||||||
use utils::{
|
use utils::{
|
||||||
@ -43,7 +43,6 @@ use state::SystemState;
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
/* system config */
|
/* system config */
|
||||||
|
|
||||||
const GUI_TICK_SEC: f32 = 0.2;
|
|
||||||
const AWAKE_TIMEOUT_SEC: f32 = 20.0;
|
const AWAKE_TIMEOUT_SEC: f32 = 20.0;
|
||||||
const HEARTBEAT_SEC: f32 = 1.0;
|
const HEARTBEAT_SEC: f32 = 1.0;
|
||||||
|
|
||||||
@ -75,6 +74,14 @@ enum PowerState {
|
|||||||
Sleeping,
|
Sleeping,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/* error management */
|
||||||
|
enum ErrorState {
|
||||||
|
NoError,
|
||||||
|
NewError (&'static str),
|
||||||
|
HandlingError,
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
/* interrupt service routines */
|
/* interrupt service routines */
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
@ -178,7 +185,13 @@ fn main() -> ! {
|
|||||||
let mut afio = dp.AFIO.constrain();
|
let mut afio = dp.AFIO.constrain();
|
||||||
|
|
||||||
// initialize system state
|
// initialize system state
|
||||||
let config = SystemConfig::new();
|
let mut error_state = ErrorState::NoError;
|
||||||
|
let config = match SystemConfig::load() {
|
||||||
|
Ok(conf) => conf,
|
||||||
|
Err(_) => {
|
||||||
|
error_state = ErrorState::NewError("config invalide");
|
||||||
|
SystemConfig::new()
|
||||||
|
}};
|
||||||
let mut state = SystemState::new(config, gpiob.pb12.into_push_pull_output(&mut gpiob.crh));
|
let mut state = SystemState::new(config, gpiob.pb12.into_push_pull_output(&mut gpiob.crh));
|
||||||
|
|
||||||
// Setup display
|
// Setup display
|
||||||
@ -265,7 +278,7 @@ fn main() -> ! {
|
|||||||
// configure stop mode (not working yet, probably due to fake chip)
|
// configure stop mode (not working yet, probably due to fake chip)
|
||||||
//dp.PWR.cr.write(|w| w.pdds().stop_mode());
|
//dp.PWR.cr.write(|w| w.pdds().stop_mode());
|
||||||
//dp.PWR.cr.write(|w| w.lpds().set_bit());
|
//dp.PWR.cr.write(|w| w.lpds().set_bit());
|
||||||
|
|
||||||
// setup adc
|
// setup adc
|
||||||
let mut adc = Adc::adc1(dp.ADC1, clocks);
|
let mut adc = Adc::adc1(dp.ADC1, clocks);
|
||||||
adc.set_sample_time(SampleTime::T_71);
|
adc.set_sample_time(SampleTime::T_71);
|
||||||
@ -283,45 +296,63 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let mut power_state = PowerState::Awake;
|
let mut power_state = PowerState::Awake;
|
||||||
let mut timeout = 0;
|
let mut timeout = 0;
|
||||||
|
|
||||||
/* run */
|
/* run */
|
||||||
let _ = TEMP_FLAG.swap(true, Ordering::Release);
|
let _ = TEMP_FLAG.swap(true, Ordering::Release);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
||||||
if TEMP_FLAG.swap(false, Ordering::AcqRel) {
|
match error_state {
|
||||||
|
ErrorState::NoError => {
|
||||||
|
if TEMP_FLAG.swap(false, Ordering::AcqRel) {
|
||||||
|
|
||||||
// compute temps
|
// compute temps
|
||||||
let ext_temp = ext_probe.read().ok();
|
let ext_temp = ext_probe.read().ok();
|
||||||
let p1_temp = p1_probe.read().ok();
|
let p1_temp = p1_probe.read().ok();
|
||||||
let p2_temp = p2_probe.read().ok();
|
let p2_temp = p2_probe.read().ok();
|
||||||
|
|
||||||
state.update(ext_temp, p1_temp, p2_temp);
|
state.update(ext_temp, p1_temp, p2_temp);
|
||||||
gui.update_temps(&mut state);
|
gui.update_temps(&mut state);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
match gui.update(&mut state) {
|
match gui.update(&mut state) {
|
||||||
true => timeout = 0,
|
true => timeout = 0,
|
||||||
false => timeout += 1,
|
false => timeout += 1,
|
||||||
}
|
|
||||||
|
|
||||||
// manage power state
|
|
||||||
match power_state {
|
|
||||||
PowerState::Awake => { // normal gui update
|
|
||||||
if timeout as f32 * GUI_TICK_SEC >= AWAKE_TIMEOUT_SEC {
|
|
||||||
// go to sleep
|
|
||||||
power_state = PowerState::Sleeping;
|
|
||||||
gui.sleep();
|
|
||||||
cp.SCB.set_sleepdeep();
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
PowerState::Sleeping => { // button was pressed during sleep
|
// manage power state
|
||||||
// wake up
|
match power_state {
|
||||||
power_state = PowerState::Awake;
|
PowerState::Awake => { // normal gui update
|
||||||
cp.SCB.clear_sleepdeep();
|
if timeout as f32 * GUI_TICK_SEC >= AWAKE_TIMEOUT_SEC {
|
||||||
}}}
|
// go to sleep
|
||||||
|
power_state = PowerState::Sleeping;
|
||||||
|
gui.sleep();
|
||||||
|
cp.SCB.set_sleepdeep();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PowerState::Sleeping => { // button was pressed during sleep
|
||||||
|
// wake up
|
||||||
|
power_state = PowerState::Awake;
|
||||||
|
cp.SCB.clear_sleepdeep();
|
||||||
|
}}}
|
||||||
|
},
|
||||||
|
ErrorState::NewError (err) => {
|
||||||
|
gui.display_error(err);
|
||||||
|
state.stop();
|
||||||
|
error_state = ErrorState::HandlingError;
|
||||||
|
},
|
||||||
|
ErrorState::HandlingError => {
|
||||||
|
if gui.update(&mut state) {
|
||||||
|
error_state = ErrorState::NoError;
|
||||||
|
state.reset();
|
||||||
|
ext_probe.reset().unwrap();
|
||||||
|
p1_probe.reset().unwrap();
|
||||||
|
p2_probe.reset().unwrap();
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
// put device in sleep mode until next interrupt (button or timer)
|
// put device in sleep mode until next interrupt (button or timer)
|
||||||
cortex_m::asm::wfi();
|
cortex_m::asm::wfi();
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/state.rs
14
src/state.rs
@ -126,7 +126,17 @@ impl<O: OutputPin> SystemState<O> {
|
|||||||
if (p - ext) > self.config.max_temp_diff {
|
if (p - ext) > self.config.max_temp_diff {
|
||||||
self.fan.on();
|
self.fan.on();
|
||||||
}
|
}
|
||||||
},
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stop(&mut self) {
|
||||||
|
self.fan.off();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.ext_temp = None;
|
||||||
|
self.p1_temp = None;
|
||||||
|
self.p2_temp = None;
|
||||||
|
self.fan.off();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/utils.rs
15
src/utils.rs
@ -121,5 +121,20 @@ where
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) -> Result<(), ProbeError>{
|
||||||
|
|
||||||
|
// re-compute first temp approximation to speed up stabilization
|
||||||
|
let mut temp = 0.0;
|
||||||
|
for _ in 0..10 {
|
||||||
|
temp += read_temp(self.adc, &mut self.pos_pin, &mut self.neg_pin)?;
|
||||||
|
}
|
||||||
|
temp /= 10.0;
|
||||||
|
|
||||||
|
self.filtered_temp = temp;
|
||||||
|
self.stabilized = false;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user