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)]
|
||||
pub fn load() -> Result<ConfigError, SystemConfig> {
|
||||
unimplemented!();
|
||||
pub fn load() -> Result<SystemConfig, ConfigError> {
|
||||
Err(ConfigError::LoadError)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
@ -21,6 +21,12 @@ use crate::{
|
||||
config::{Menu, SystemConfig, FanOutput},
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* GUI config */
|
||||
|
||||
pub const GUI_TICK_SEC: f32 = 0.2;
|
||||
const GUI_ERROR_SEC: f32 = 0.8;
|
||||
|
||||
//---Temp Enum--------------------------------------------------------------------------------------
|
||||
/// 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
|
||||
@ -75,6 +81,7 @@ pub enum GUIState {
|
||||
Off,
|
||||
Idle,
|
||||
Menu,
|
||||
Error (&'static str),
|
||||
}
|
||||
|
||||
/// Manages the lcd screen and inputs (encoder + button) and display relevant information. Can also
|
||||
@ -97,6 +104,7 @@ where
|
||||
p1_deg: Temp,
|
||||
p2_deg: Temp,
|
||||
should_refresh: bool,
|
||||
blink_counter: i32,
|
||||
}
|
||||
|
||||
impl<L, Q, B> LCDGui<L, Q, B>
|
||||
@ -126,6 +134,7 @@ where
|
||||
p1_deg: Temp::Invalid,
|
||||
p2_deg: Temp::Invalid,
|
||||
should_refresh: true,
|
||||
blink_counter: 0,
|
||||
};
|
||||
|
||||
if let Some(bl) = &mut gui.backlight { let _ = bl.set_high(); };
|
||||
@ -179,6 +188,11 @@ where
|
||||
state.update_config(config);
|
||||
self.menu.display(&mut self.lcd);
|
||||
}
|
||||
},
|
||||
GUIState::Error (_) => {
|
||||
self.state = GUIState::Idle;
|
||||
self.lcd.clear();
|
||||
self.should_refresh = true;
|
||||
}}}
|
||||
|
||||
// manage encoder movement
|
||||
@ -211,6 +225,18 @@ where
|
||||
self.menu.movement_update(diff);
|
||||
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
|
||||
@ -239,6 +265,11 @@ where
|
||||
//TODO set display off ?
|
||||
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,
|
||||
|
||||
91
src/main.rs
91
src/main.rs
@ -27,7 +27,7 @@ use stm32f1xx_hal::{
|
||||
};
|
||||
|
||||
mod lcd_gui;
|
||||
use lcd_gui::LCDGui;
|
||||
use lcd_gui::{LCDGui, GUI_TICK_SEC};
|
||||
|
||||
mod utils;
|
||||
use utils::{
|
||||
@ -43,7 +43,6 @@ use state::SystemState;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* system config */
|
||||
|
||||
const GUI_TICK_SEC: f32 = 0.2;
|
||||
const AWAKE_TIMEOUT_SEC: f32 = 20.0;
|
||||
const HEARTBEAT_SEC: f32 = 1.0;
|
||||
|
||||
@ -75,6 +74,14 @@ enum PowerState {
|
||||
Sleeping,
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* error management */
|
||||
enum ErrorState {
|
||||
NoError,
|
||||
NewError (&'static str),
|
||||
HandlingError,
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* interrupt service routines */
|
||||
#[interrupt]
|
||||
@ -178,7 +185,13 @@ fn main() -> ! {
|
||||
let mut afio = dp.AFIO.constrain();
|
||||
|
||||
// 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));
|
||||
|
||||
// Setup display
|
||||
@ -289,38 +302,56 @@ fn main() -> ! {
|
||||
|
||||
loop {
|
||||
|
||||
if TEMP_FLAG.swap(false, Ordering::AcqRel) {
|
||||
match error_state {
|
||||
ErrorState::NoError => {
|
||||
if TEMP_FLAG.swap(false, Ordering::AcqRel) {
|
||||
|
||||
// compute temps
|
||||
let ext_temp = ext_probe.read().ok();
|
||||
let p1_temp = p1_probe.read().ok();
|
||||
let p2_temp = p2_probe.read().ok();
|
||||
// compute temps
|
||||
let ext_temp = ext_probe.read().ok();
|
||||
let p1_temp = p1_probe.read().ok();
|
||||
let p2_temp = p2_probe.read().ok();
|
||||
|
||||
state.update(ext_temp, p1_temp, p2_temp);
|
||||
gui.update_temps(&mut state);
|
||||
state.update(ext_temp, p1_temp, p2_temp);
|
||||
gui.update_temps(&mut state);
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
match gui.update(&mut state) {
|
||||
true => timeout = 0,
|
||||
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();
|
||||
match gui.update(&mut state) {
|
||||
true => timeout = 0,
|
||||
false => timeout += 1,
|
||||
}
|
||||
},
|
||||
PowerState::Sleeping => { // button was pressed during sleep
|
||||
// wake up
|
||||
power_state = PowerState::Awake;
|
||||
cp.SCB.clear_sleepdeep();
|
||||
}}}
|
||||
|
||||
// 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
|
||||
// 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)
|
||||
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 {
|
||||
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