fix: 修复 DC OUT 控制信号输出抖动。Closed #4.

This commit is contained in:
Ivan Li 2022-09-10 17:35:10 +08:00
parent 13a1b99cb5
commit 7d7048b671
2 changed files with 53 additions and 51 deletions

View File

@ -1,4 +1,8 @@
use std::sync::{Arc, Mutex}; use std::{
sync::{
Arc, Mutex, MutexGuard,
},
};
use embedded_hal::digital::v2::{OutputPin, PinState}; use embedded_hal::digital::v2::{OutputPin, PinState};
use embedded_svc::event_bus::{EventBus, Postbox}; use embedded_svc::event_bus::{EventBus, Postbox};
@ -11,7 +15,7 @@ use esp_idf_sys::c_types;
use log::{info, warn}; use log::{info, warn};
use serde_json::json; use serde_json::json;
use crate::{voltage_detection::{VoltageDetectionWorker, VOLTAGE_EVENTLOOP}}; use crate::voltage_detection::{VoltageDetectionWorker, VOLTAGE_EVENTLOOP};
const WAITING_OFF_SECONDS: u8 = 60; const WAITING_OFF_SECONDS: u8 = 60;
@ -132,8 +136,7 @@ impl DcOutControllerState {
DcOutStatus::TurningOff(seconds) => seconds.into(), DcOutStatus::TurningOff(seconds) => seconds.into(),
_ => -1, _ => -1,
}; };
json!({ "status": status, "pin_state": pin_state, "seconds": seconds }) json!({ "status": status, "pin_state": pin_state, "seconds": seconds }).to_string()
.to_string()
} }
} }
@ -161,67 +164,67 @@ impl EspTypedEventDeserializer<DcOutControllerState> for DcOutControllerState {
} }
} }
type DcOutPin = Gpio6<Output>;
pub struct DcOutController { pub struct DcOutController {
pub state: DcOutControllerState, pub state: DcOutControllerState,
voltage_subscription: Option<EspSubscription<User<Background>>>, voltage_subscription: Option<EspSubscription<User<Background>>>,
pin: Arc<Mutex<DcOutPin>>,
} }
impl DcOutController { impl DcOutController {
fn new() -> Self { pub fn new() -> anyhow::Result<Self> {
Self { let mut pin = unsafe { Gpio6::<Output>::new() }
state: DcOutControllerState::new(), .into_output()
voltage_subscription: None, .map_err(|err| anyhow::anyhow!("Make Gpio6 Into output Failed. {}", err))?;
}
}
pub fn get_instance() -> anyhow::Result<Self> {
// if let Some(instance) = unsafe { &mut INSTANCE } {
// anyhow::Ok(*instance)
// } else {
let instance = Self::new();
// unsafe { INSTANCE = Some(instance) };
match EspBackgroundEventLoop::new(&Default::default()) { match EspBackgroundEventLoop::new(&Default::default()) {
Ok(eventloop) => unsafe { DC_OUT_STATE_EVENT_LOOP = Some(eventloop) }, Ok(eventloop) => unsafe { DC_OUT_STATE_EVENT_LOOP = Some(eventloop) },
Err(err) => anyhow::bail!("Init Event Loop failed. {:?}", err), Err(err) => anyhow::bail!("Init Event Loop failed. {:?}", err),
} }
anyhow::Ok(instance)
// } anyhow::Ok(Self {
state: DcOutControllerState::new(),
voltage_subscription: None,
pin: Arc::new(Mutex::new(pin)),
})
} }
pub fn watch(&mut self) -> anyhow::Result<()> { pub fn watch(&mut self) -> anyhow::Result<()> {
let state = Arc::new(Mutex::new(self.state)); let mut state = self.state.to_owned();
let pin = self.pin.to_owned();
if let Some(event_loop) = unsafe { VOLTAGE_EVENTLOOP.as_mut() } { if let Some(event_loop) = unsafe { VOLTAGE_EVENTLOOP.as_mut() } {
let voltage_subscription = event_loop let voltage_subscription = event_loop
.subscribe( .subscribe(move |obj: &VoltageDetectionWorker| {
move |obj: &VoltageDetectionWorker| match state.lock().as_mut() { if obj.adapter_voltage < 1000 {
Ok(state) => { if obj.battery_voltage < 1000 {
if obj.adapter_voltage < 1000 { state.turn_off();
if obj.battery_voltage < 1000 { } else {
state.turn_off(); state.handle_adapter_down();
} else { }
state.handle_adapter_down(); } else {
} state.turn_on();
} else { }
state.turn_on();
} match pin.lock() {
let ref state = **state; Ok(pin) => {
if let Err(err) = Self::output_ctl(*state) { if let Err(err) = Self::output_ctl(state, pin) {
warn!("Put Control Pin State Failed. {}", err); warn!("Put Control Pin State Failed. {}", err);
} }
if let Some(event_loop) = unsafe { DC_OUT_STATE_EVENT_LOOP.as_mut() } {
if let Err(err) = event_loop.post(state, None) {
warn!("Post DC Out Status Failed. {}", err);
}
} else {
warn!("DC_OUT_STATE_EVENT_LOOP is None");
}
info!("status: {:?}", state);
} }
Err(err) => warn!("Can not lock state. {}", err), Err(_) => todo!(),
}, }
)
if let Some(event_loop) = unsafe { DC_OUT_STATE_EVENT_LOOP.as_mut() } {
if let Err(err) = event_loop.post(&state, None) {
warn!("Post DC Out Status Failed. {}", err);
}
} else {
warn!("DC_OUT_STATE_EVENT_LOOP is None");
}
info!("status: {:?}", state);
})
.map_err(|err| anyhow::anyhow!("Subscribe Voltage Failed. {}", err))?; .map_err(|err| anyhow::anyhow!("Subscribe Voltage Failed. {}", err))?;
self.voltage_subscription = Some(voltage_subscription); self.voltage_subscription = Some(voltage_subscription);
} else { } else {
@ -229,11 +232,10 @@ impl DcOutController {
} }
anyhow::Ok(()) anyhow::Ok(())
} }
fn output_ctl(mut state: DcOutControllerState) -> anyhow::Result<()> { fn output_ctl(
let mut pin = unsafe { Gpio6::<Output>::new() } mut state: DcOutControllerState,
.into_output() mut pin: MutexGuard<DcOutPin>,
.map_err(|err| anyhow::anyhow!("Make Gpio6 Into output Failed. {}", err))?; ) -> anyhow::Result<()> {
if DcOutStatus::Off == state.status && state.pin_state == PinState::Low { if DcOutStatus::Off == state.status && state.pin_state == PinState::Low {
pin.set_high() pin.set_high()
.map_err(|err| anyhow::anyhow!("Set DC Output Control Pin High Failed. {}", err))?; .map_err(|err| anyhow::anyhow!("Set DC Output Control Pin High Failed. {}", err))?;

View File

@ -74,7 +74,7 @@ fn main() {
let mut beep = Beep::new().unwrap(); let mut beep = Beep::new().unwrap();
let mut dc_out_controller = let mut dc_out_controller =
DcOutController::get_instance().expect("Can not get DcOutController instance"); DcOutController::new().expect("Can not get DcOutController instance");
dc_out_controller dc_out_controller
.watch() .watch()
.expect("Can not watch for dc_out_controller"); .expect("Can not watch for dc_out_controller");