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_svc::event_bus::{EventBus, Postbox};
@ -11,7 +15,7 @@ use esp_idf_sys::c_types;
use log::{info, warn};
use serde_json::json;
use crate::{voltage_detection::{VoltageDetectionWorker, VOLTAGE_EVENTLOOP}};
use crate::voltage_detection::{VoltageDetectionWorker, VOLTAGE_EVENTLOOP};
const WAITING_OFF_SECONDS: u8 = 60;
@ -132,8 +136,7 @@ impl DcOutControllerState {
DcOutStatus::TurningOff(seconds) => seconds.into(),
_ => -1,
};
json!({ "status": status, "pin_state": pin_state, "seconds": seconds })
.to_string()
json!({ "status": status, "pin_state": pin_state, "seconds": seconds }).to_string()
}
}
@ -161,67 +164,67 @@ impl EspTypedEventDeserializer<DcOutControllerState> for DcOutControllerState {
}
}
type DcOutPin = Gpio6<Output>;
pub struct DcOutController {
pub state: DcOutControllerState,
voltage_subscription: Option<EspSubscription<User<Background>>>,
pin: Arc<Mutex<DcOutPin>>,
}
impl DcOutController {
fn new() -> Self {
Self {
state: DcOutControllerState::new(),
voltage_subscription: None,
}
}
pub fn new() -> anyhow::Result<Self> {
let mut pin = unsafe { Gpio6::<Output>::new() }
.into_output()
.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()) {
Ok(eventloop) => unsafe { DC_OUT_STATE_EVENT_LOOP = Some(eventloop) },
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<()> {
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() } {
let voltage_subscription = event_loop
.subscribe(
move |obj: &VoltageDetectionWorker| match state.lock().as_mut() {
Ok(state) => {
if obj.adapter_voltage < 1000 {
if obj.battery_voltage < 1000 {
state.turn_off();
} else {
state.handle_adapter_down();
}
} else {
state.turn_on();
}
let ref state = **state;
if let Err(err) = Self::output_ctl(*state) {
.subscribe(move |obj: &VoltageDetectionWorker| {
if obj.adapter_voltage < 1000 {
if obj.battery_voltage < 1000 {
state.turn_off();
} else {
state.handle_adapter_down();
}
} else {
state.turn_on();
}
match pin.lock() {
Ok(pin) => {
if let Err(err) = Self::output_ctl(state, pin) {
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))?;
self.voltage_subscription = Some(voltage_subscription);
} else {
@ -229,11 +232,10 @@ impl DcOutController {
}
anyhow::Ok(())
}
fn output_ctl(mut state: DcOutControllerState) -> anyhow::Result<()> {
let mut pin = unsafe { Gpio6::<Output>::new() }
.into_output()
.map_err(|err| anyhow::anyhow!("Make Gpio6 Into output Failed. {}", err))?;
fn output_ctl(
mut state: DcOutControllerState,
mut pin: MutexGuard<DcOutPin>,
) -> anyhow::Result<()> {
if DcOutStatus::Off == state.status && state.pin_state == PinState::Low {
pin.set_high()
.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 dc_out_controller =
DcOutController::get_instance().expect("Can not get DcOutController instance");
DcOutController::new().expect("Can not get DcOutController instance");
dc_out_controller
.watch()
.expect("Can not watch for dc_out_controller");