From 475dffe6b2df08e13a38c35ab5af10a76ed53056 Mon Sep 17 00:00:00 2001 From: soffee Date: Sat, 8 Mar 2025 14:48:54 +0300 Subject: [PATCH] use Instant instead of SystemTime; implement button debounce --- firmware/src/hid.rs | 7 +++++-- firmware/src/main.rs | 32 +++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/firmware/src/hid.rs b/firmware/src/hid.rs index 0ee01e0..fa2ac6c 100644 --- a/firmware/src/hid.rs +++ b/firmware/src/hid.rs @@ -33,8 +33,11 @@ impl<'d, P: InputPin> GPIOButton<'d, P> { } pub fn enable_interrupt(&mut self) -> Result<(), EspError>{ - self.pin.enable_interrupt()?; - return Ok(()); + return self.pin.enable_interrupt(); + } + + pub fn disable_interrupt(&mut self) -> Result<(), EspError>{ + return self.pin.disable_interrupt(); } } diff --git a/firmware/src/main.rs b/firmware/src/main.rs index f90958e..4f021bc 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -1,6 +1,6 @@ mod hid; -use std::{thread, time::{Duration, SystemTime}}; +use std::{thread, time::{Duration, Instant}}; use anyhow::Result; use embedded_graphics::{ mono_font::{ascii::FONT_6X10, MonoTextStyleBuilder}, @@ -73,16 +73,17 @@ fn main() -> Result<()> { let mut temperature = 0_f32; let mut i = 0_u32; - let mut blink_time: SystemTime = SystemTime::now(); - let mut measure_time: SystemTime = SystemTime::now(); + let mut blink_time = Instant::now(); + let mut measure_time = Instant::now(); + let mut input_time = Option::from(Instant::now()); loop { - // #FIXME button handler needs debounce. + // when we receive button event, button interrupt will be automatically disabled until we enable it manually + // so we use this feature to "debounce" our button by enabling interrupt only after some time passes let not = btn1.button.wait_event(esp_idf_svc::hal::delay::NON_BLOCK); match not { Some(n) => { println!("Button 1 pressed!"); - btn1.button.enable_interrupt()?; if heater_drv_pin.is_set_high() { heater_drv_pin.set_low()?; @@ -91,11 +92,24 @@ fn main() -> Result<()> { heater_drv_pin.set_high()?; btn1.indicator.set_state(true)?; } + + input_time = Option::from(Instant::now()); }, None => (), } - if measure_time.elapsed()?.as_millis() >= 10 { + // enable button interrupt again after 300ms from last click + match input_time { + Some(time) => { + if time.elapsed().as_millis() >= 300 { + btn1.button.enable_interrupt()?; + input_time.take(); + } + }, + None => (), + } + + if measure_time.elapsed().as_millis() >= 10 { if i < 64 { let v = adc.read(&mut therm_pin)? as f32 / 1000_f32; let r = R1 / (V1 / v - 1_f32); @@ -108,10 +122,10 @@ fn main() -> Result<()> { samples_sum = 0_f32; i = 0; } - measure_time = SystemTime::now(); + measure_time = Instant::now(); } - if blink_time.elapsed()?.as_millis() >= 1000 { + if blink_time.elapsed().as_millis() >= 1000 { if led_pin.is_set_high() { led_pin.set_low().unwrap(); } else { @@ -132,7 +146,7 @@ fn main() -> Result<()> { // display.flush().unwrap(); - blink_time = SystemTime::now(); + blink_time = Instant::now(); } thread::sleep(Duration::from_millis(10));