From 3fc3dbaae85f5f494a1ae3a6ce1aece823fc7f46 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Tue, 25 Jan 2022 14:09:16 +0100 Subject: [PATCH] Added config error screen + added error management + added config error when failing to load --- src/config.rs | 4 +-- src/lcd_gui.rs | 31 ++++++++++++++++ src/main.rs | 97 +++++++++++++++++++++++++++++++++----------------- src/state.rs | 14 ++++++-- src/utils.rs | 15 ++++++++ 5 files changed, 124 insertions(+), 37 deletions(-) diff --git a/src/config.rs b/src/config.rs index 36c9866..b7d0d72 100644 --- a/src/config.rs +++ b/src/config.rs @@ -52,8 +52,8 @@ impl SystemConfig { } #[allow(dead_code)] - pub fn load() -> Result { - unimplemented!(); + pub fn load() -> Result { + Err(ConfigError::LoadError) } #[allow(dead_code)] diff --git a/src/lcd_gui.rs b/src/lcd_gui.rs index d0e7a52..27e44ba 100644 --- a/src/lcd_gui.rs +++ b/src/lcd_gui.rs @@ -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 LCDGui @@ -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(screen: &mut L, ext_deg: &Temp, p1_deg: &Temp, p2_deg: &Temp, diff --git a/src/main.rs b/src/main.rs index a1c8ad9..1c9674f 100644 --- a/src/main.rs +++ b/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 @@ -265,7 +278,7 @@ fn main() -> ! { // 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.lpds().set_bit()); - + // setup adc let mut adc = Adc::adc1(dp.ADC1, clocks); adc.set_sample_time(SampleTime::T_71); @@ -283,45 +296,63 @@ fn main() -> ! { let mut power_state = PowerState::Awake; let mut timeout = 0; - + /* run */ let _ = TEMP_FLAG.swap(true, Ordering::Release); 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(); } diff --git a/src/state.rs b/src/state.rs index 9186545..3c2fd95 100644 --- a/src/state.rs +++ b/src/state.rs @@ -126,7 +126,17 @@ impl SystemState { 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(); } } diff --git a/src/utils.rs b/src/utils.rs index 0a8d5a3..2550770 100644 --- a/src/utils.rs +++ b/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(()) + } }