feat: 避免重复初始化 ADC 管脚。
This commit is contained in:
		| @@ -13,9 +13,9 @@ | |||||||
|  |  | ||||||
| ## GPIO 定义 | ## GPIO 定义 | ||||||
|  |  | ||||||
| - `GPIO 1`:UPS 输入电压检测,使用 `ADC 0`; | - `GPIO 1`:UPS 输入电压检测,使用 `ADC 1`; | ||||||
| - `GPIO 2`:电池电芯电压检测,使用 `ADC 0`; | - `GPIO 2`:电池电芯电压检测,使用 `ADC 1`; | ||||||
| - `GPIO 3`:UPS 输出电压检测,使用 `ADC 0`; | - `GPIO 3`:UPS 输出电压检测,使用 `ADC 1`; | ||||||
| - `GPIO 4`:蜂鸣器模拟信号输出,使用 `CHANNEL 0`, `TIMER 0`; | - `GPIO 4`:蜂鸣器模拟信号输出,使用 `CHANNEL 0`, `TIMER 0`; | ||||||
| - `GPIO 5`:工作状态指示灯信号输出; | - `GPIO 5`:工作状态指示灯信号输出; | ||||||
| - `GPIO 6`:UPS 输出控制信号,适用于 P-MOS 开关; | - `GPIO 6`:UPS 输出控制信号,适用于 P-MOS 开关; | ||||||
							
								
								
									
										249
									
								
								src/charge_controller.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/charge_controller.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | |||||||
|  | use std::{ | ||||||
|  |     sync::{ | ||||||
|  |         Arc, Mutex, MutexGuard, | ||||||
|  |     }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | use embedded_hal::digital::v2::{OutputPin, PinState}; | ||||||
|  | use embedded_svc::event_bus::{EventBus, Postbox}; | ||||||
|  | use esp_idf_hal::gpio::{Gpio6, Output}; | ||||||
|  | use esp_idf_svc::eventloop::{ | ||||||
|  |     Background, EspBackgroundEventLoop, EspEventFetchData, EspEventLoop, EspEventPostData, | ||||||
|  |     EspSubscription, EspTypedEventDeserializer, EspTypedEventSerializer, EspTypedEventSource, User, | ||||||
|  | }; | ||||||
|  | use esp_idf_sys::c_types; | ||||||
|  | use log::{info, warn, debug}; | ||||||
|  | use serde_json::json; | ||||||
|  |  | ||||||
|  | use crate::voltage_detection::{VoltageDetectionWorker, VOLTAGE_EVENTLOOP}; | ||||||
|  |  | ||||||
|  | const WAITING_OFF_SECONDS: u8 = 60; | ||||||
|  |  | ||||||
|  | pub static mut DC_OUT_STATE_EVENT_LOOP: Option< | ||||||
|  |     EspEventLoop<esp_idf_svc::eventloop::User<Background>>, | ||||||
|  | > = None; | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Copy, PartialEq)] | ||||||
|  | pub enum DcOutStatus { | ||||||
|  |     WaitingOn(u8), | ||||||
|  |     On, | ||||||
|  |     Off, | ||||||
|  |     WaitingOff, | ||||||
|  |     TurningOff(u8), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Copy)] | ||||||
|  | pub struct DcOutControllerState { | ||||||
|  |     pub status: DcOutStatus, | ||||||
|  |     pub pin_state: PinState, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl DcOutControllerState { | ||||||
|  |     pub fn new() -> Self { | ||||||
|  |         Self { | ||||||
|  |             status: DcOutStatus::On, | ||||||
|  |             pin_state: PinState::Low, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn handle_adapter_down(&mut self) { | ||||||
|  |         info!("status: {:?}", self); | ||||||
|  |         match self.status { | ||||||
|  |             DcOutStatus::On => { | ||||||
|  |                 self.status = DcOutStatus::WaitingOff; | ||||||
|  |             } | ||||||
|  |             DcOutStatus::WaitingOn(_) => { | ||||||
|  |                 self.status = DcOutStatus::Off; | ||||||
|  |             } | ||||||
|  |             DcOutStatus::TurningOff(seconds) => { | ||||||
|  |                 let seconds = seconds - 1; | ||||||
|  |                 if seconds > 0 { | ||||||
|  |                     self.status = DcOutStatus::TurningOff(seconds); | ||||||
|  |                 } else { | ||||||
|  |                     self.status = DcOutStatus::Off; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => {} | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn turn_off(&mut self) { | ||||||
|  |         match self.status { | ||||||
|  |             DcOutStatus::On => { | ||||||
|  |                 self.status = DcOutStatus::TurningOff(WAITING_OFF_SECONDS); | ||||||
|  |             } | ||||||
|  |             DcOutStatus::WaitingOff => { | ||||||
|  |                 self.status = DcOutStatus::TurningOff(WAITING_OFF_SECONDS); | ||||||
|  |             } | ||||||
|  |             DcOutStatus::WaitingOn(_) => { | ||||||
|  |                 self.status = DcOutStatus::Off; | ||||||
|  |             } | ||||||
|  |             DcOutStatus::TurningOff(seconds) => { | ||||||
|  |                 let seconds = seconds - 1; | ||||||
|  |                 if seconds > 0 { | ||||||
|  |                     self.status = DcOutStatus::TurningOff(seconds); | ||||||
|  |                 } else { | ||||||
|  |                     self.status = DcOutStatus::Off; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => {} | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn turn_on(&mut self) { | ||||||
|  |         match self.status { | ||||||
|  |             DcOutStatus::WaitingOff => { | ||||||
|  |                 self.status = DcOutStatus::On; | ||||||
|  |             } | ||||||
|  |             DcOutStatus::Off => { | ||||||
|  |                 self.status = DcOutStatus::WaitingOn(WAITING_OFF_SECONDS); | ||||||
|  |             } | ||||||
|  |             DcOutStatus::WaitingOn(seconds) => { | ||||||
|  |                 let seconds = seconds - 1; | ||||||
|  |                 if seconds > 0 { | ||||||
|  |                     self.status = DcOutStatus::WaitingOn(seconds); | ||||||
|  |                 } else { | ||||||
|  |                     self.status = DcOutStatus::On; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             DcOutStatus::TurningOff(seconds) => { | ||||||
|  |                 let seconds = seconds - 1; | ||||||
|  |                 if seconds > 0 { | ||||||
|  |                     self.status = DcOutStatus::TurningOff(seconds); | ||||||
|  |                 } else { | ||||||
|  |                     self.status = DcOutStatus::On; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => {} | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn to_json(&self) -> String { | ||||||
|  |         let status = match self.status { | ||||||
|  |             DcOutStatus::WaitingOn(_) => "WaitingOn", | ||||||
|  |             DcOutStatus::On => "On", | ||||||
|  |             DcOutStatus::Off => "Off", | ||||||
|  |             DcOutStatus::WaitingOff => "WaitingOff", | ||||||
|  |             DcOutStatus::TurningOff(_) => "TurningOff", | ||||||
|  |         }; | ||||||
|  |         let pin_state = match self.pin_state { | ||||||
|  |             PinState::Low => "Low", | ||||||
|  |             PinState::High => "High", | ||||||
|  |         }; | ||||||
|  |         let seconds: i16 = match self.status { | ||||||
|  |             DcOutStatus::WaitingOn(seconds) => seconds.into(), | ||||||
|  |             DcOutStatus::TurningOff(seconds) => seconds.into(), | ||||||
|  |             _ => -1, | ||||||
|  |         }; | ||||||
|  |         json!({ "status": status, "pin_state": pin_state, "seconds": seconds }).to_string() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl EspTypedEventSource for DcOutControllerState { | ||||||
|  |     fn source() -> *const c_types::c_char { | ||||||
|  |         b"Charge\0".as_ptr() as *const _ | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl EspTypedEventSerializer<DcOutControllerState> for DcOutControllerState { | ||||||
|  |     fn serialize<R>( | ||||||
|  |         event: &DcOutControllerState, | ||||||
|  |         f: impl for<'a> FnOnce(&'a EspEventPostData) -> R, | ||||||
|  |     ) -> R { | ||||||
|  |         f(&unsafe { EspEventPostData::new(Self::source(), Self::event_id(), event) }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl EspTypedEventDeserializer<DcOutControllerState> for DcOutControllerState { | ||||||
|  |     fn deserialize<R>( | ||||||
|  |         data: &EspEventFetchData, | ||||||
|  |         f: &mut impl for<'a> FnMut(&'a DcOutControllerState) -> R, | ||||||
|  |     ) -> R { | ||||||
|  |         f(unsafe { data.as_payload() }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type DcOutPin = Gpio6<Output>; | ||||||
|  |  | ||||||
|  | pub struct DcOutController { | ||||||
|  |     pub state: DcOutControllerState, | ||||||
|  |     voltage_subscription: Option<EspSubscription<User<Background>>>, | ||||||
|  |     pin: Arc<Mutex<DcOutPin>>, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl DcOutController { | ||||||
|  |     pub fn new() -> anyhow::Result<Self> { | ||||||
|  |         let pin = unsafe { Gpio6::<Output>::new() } | ||||||
|  |             .into_output() | ||||||
|  |             .map_err(|err| anyhow::anyhow!("Make Gpio6 Into output Failed. {}", err))?; | ||||||
|  |  | ||||||
|  |         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(Self { | ||||||
|  |             state: DcOutControllerState::new(), | ||||||
|  |             voltage_subscription: None, | ||||||
|  |             pin: Arc::new(Mutex::new(pin)), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn watch(&mut self) -> anyhow::Result<()> { | ||||||
|  |         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| { | ||||||
|  |                     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); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         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"); | ||||||
|  |                     } | ||||||
|  |                     debug!("status: {:?}", state); | ||||||
|  |                 }) | ||||||
|  |                 .map_err(|err| anyhow::anyhow!("Subscribe Voltage Failed. {}", err))?; | ||||||
|  |             self.voltage_subscription = Some(voltage_subscription); | ||||||
|  |         } else { | ||||||
|  |             anyhow::bail!("Voltage Event Loop is None"); | ||||||
|  |         } | ||||||
|  |         anyhow::Ok(()) | ||||||
|  |     } | ||||||
|  |     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))?; | ||||||
|  |             state.pin_state = PinState::High; | ||||||
|  |         } else if DcOutStatus::On == state.status && state.pin_state == PinState::High { | ||||||
|  |             pin.set_low() | ||||||
|  |                 .map_err(|err| anyhow::anyhow!("Set DC Output Control Pin Low Failed. {}", err))?; | ||||||
|  |             state.pin_state = PinState::Low; | ||||||
|  |         } | ||||||
|  |         return anyhow::Ok(()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -141,7 +141,7 @@ impl DcOutControllerState { | |||||||
|  |  | ||||||
| impl EspTypedEventSource for DcOutControllerState { | impl EspTypedEventSource for DcOutControllerState { | ||||||
|     fn source() -> *const c_types::c_char { |     fn source() -> *const c_types::c_char { | ||||||
|         b"VOLTAGES\0".as_ptr() as *const _ |         b"DcOut\0".as_ptr() as *const _ | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ fn main() { | |||||||
|  |  | ||||||
|     let mut voltage_detection = VoltageDetection::new(); |     let mut voltage_detection = VoltageDetection::new(); | ||||||
|  |  | ||||||
|     voltage_detection |     voltage_detection.unwrap() | ||||||
|         .watching() |         .watching() | ||||||
|         .expect("Can not watch voltages."); |         .expect("Can not watch voltages."); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -95,11 +95,12 @@ impl MessageQueue { | |||||||
|         let rx = self.rx.to_owned(); |         let rx = self.rx.to_owned(); | ||||||
|         // let (tx, rx) = mpsc::channel::<MqDto>(); |         // let (tx, rx) = mpsc::channel::<MqDto>(); | ||||||
|         spawn(move || loop { |         spawn(move || loop { | ||||||
|             if let Ok(dto) = rx.lock().unwrap().recv_timeout(Duration::from_secs(1)) { |             if let Ok(dto) = rx.lock().unwrap().recv_timeout(Duration::from_millis(400)) { | ||||||
|                 if let Err(err) = watcher.publish(dto.topic.as_str(), dto.message.as_bytes()) { |                 if let Err(err) = watcher.publish(dto.topic.as_str(), dto.message.as_bytes()) { | ||||||
|                     warn!("Can not publish message to MQTT. {}", err); |                     warn!("Can not publish message to MQTT. {}", err); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             thread::sleep(Duration::from_millis(100)) | ||||||
|         }); |         }); | ||||||
|         anyhow::Ok(()) |         anyhow::Ok(()) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,32 +1,32 @@ | |||||||
| use std::{ | use std::{ | ||||||
|     sync::{Arc, Mutex}, |     sync::{Arc, Mutex}, | ||||||
|  |     thread::{sleep, spawn}, | ||||||
|     time::Duration, |     time::Duration, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| use embedded_hal::{adc::Channel, prelude::_embedded_hal_adc_OneShot}; | use embedded_hal::{adc::Channel, prelude::_embedded_hal_adc_OneShot}; | ||||||
| use embedded_svc::{ | use embedded_svc::{event_bus::Postbox}; | ||||||
|     event_bus::Postbox, |  | ||||||
|     timer::{PeriodicTimer, TimerService}, |  | ||||||
| }; |  | ||||||
| use esp_idf_hal::{ | use esp_idf_hal::{ | ||||||
|     adc::{ |     adc::{ | ||||||
|         config::{self}, |         config::{self}, | ||||||
|         Analog, PoweredAdc, ADC1, |         Analog, Atten6dB, PoweredAdc, ADC1, | ||||||
|     }, |     }, | ||||||
|     gpio::{Gpio1, Gpio2, Gpio3, Input}, |     gpio::{Gpio1, Gpio2, Gpio3, Input}, | ||||||
| }; | }; | ||||||
| use esp_idf_svc::{ | use esp_idf_svc::{ | ||||||
|     eventloop::{ |     eventloop::{ | ||||||
|         EspEventFetchData, EspEventPostData, EspTypedEventDeserializer, EspTypedEventSerializer, |         Background, EspBackgroundEventLoop, EspEventFetchData, EspEventLoop, EspEventPostData, | ||||||
|         EspTypedEventSource, EspEventLoop, Background, EspBackgroundEventLoop, |         EspTypedEventDeserializer, EspTypedEventSerializer, EspTypedEventSource, | ||||||
|     }, |     }, | ||||||
|     timer::{EspTimer, EspTimerService}, |  | ||||||
| }; | }; | ||||||
| use esp_idf_sys::c_types; | use esp_idf_sys::c_types; | ||||||
| use log::{warn, debug}; | use log::{debug, warn}; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  |  | ||||||
| pub static mut VOLTAGE_EVENTLOOP: Option<EspEventLoop<esp_idf_svc::eventloop::User<Background>>> = None; | use crate::time::Time; | ||||||
|  |  | ||||||
|  | pub static mut VOLTAGE_EVENTLOOP: Option<EspEventLoop<esp_idf_svc::eventloop::User<Background>>> = | ||||||
|  |     None; | ||||||
|  |  | ||||||
| const ADAPTER_OFFSET: f32 = 12002f32 / 900f32; | const ADAPTER_OFFSET: f32 = 12002f32 / 900f32; | ||||||
| const BATTERY_OFFSET: f32 = 12002f32 / 900f32; | const BATTERY_OFFSET: f32 = 12002f32 / 900f32; | ||||||
| @@ -34,7 +34,6 @@ const OUTPUT_OFFSET: f32 = 12002f32 / 900f32; | |||||||
|  |  | ||||||
| pub struct VoltageDetection { | pub struct VoltageDetection { | ||||||
|     pub worker: VoltageDetectionWorker, |     pub worker: VoltageDetectionWorker, | ||||||
|     watch_timer: Option<EspTimer>, |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Clone, Copy, Serialize, Deserialize)] | #[derive(Clone, Copy, Serialize, Deserialize)] | ||||||
| @@ -45,11 +44,10 @@ pub struct VoltageDetectionWorker { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl VoltageDetection { | impl VoltageDetection { | ||||||
|     pub fn new() -> Self { |     pub fn new() -> anyhow::Result<Self> { | ||||||
|         return Self { |         return anyhow::Ok(Self { | ||||||
|             worker: VoltageDetectionWorker::new(), |             worker: VoltageDetectionWorker::new(), | ||||||
|             watch_timer: None, |         }); | ||||||
|         }; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn watching(&mut self) -> anyhow::Result<()> { |     pub fn watching(&mut self) -> anyhow::Result<()> { | ||||||
| @@ -58,16 +56,41 @@ impl VoltageDetection { | |||||||
|             Err(err) => anyhow::bail!("Init Event Loop failed. {:?}", err), |             Err(err) => anyhow::bail!("Init Event Loop failed. {:?}", err), | ||||||
|         } |         } | ||||||
|         let worker = Arc::new(Mutex::new(self.worker)); |         let worker = Arc::new(Mutex::new(self.worker)); | ||||||
|         let mut timer = EspTimerService::new()?.timer(move || { |  | ||||||
|             match worker.lock().as_mut() { |         spawn(move || { | ||||||
|                 Ok(worker) => { |             let handler = || -> anyhow::Result<()> { | ||||||
|                     if let Err(err) = worker.read_once() { |                 let mut adapter_pin = unsafe { Gpio1::<Input>::new() } | ||||||
|                         warn!("Read Failed. {}", err); |                     .into_analog_atten_6db() | ||||||
|  |                     .map_err(|err| { | ||||||
|  |                         anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err) | ||||||
|  |                     })?; | ||||||
|  |                 let mut battery_pin = unsafe { Gpio2::<Input>::new() } | ||||||
|  |                     .into_analog_atten_6db() | ||||||
|  |                     .map_err(|err| { | ||||||
|  |                         anyhow::anyhow!("Failed to set GPIO 2 as analog input. {}", err) | ||||||
|  |                     })?; | ||||||
|  |                 let mut output_pin = unsafe { Gpio3::<Input>::new() } | ||||||
|  |                     .into_analog_atten_6db() | ||||||
|  |                     .map_err(|err| { | ||||||
|  |                         anyhow::anyhow!("Failed to set GPIO 3 as analog input. {}", err) | ||||||
|  |                     })?; | ||||||
|  |  | ||||||
|  |                 let mut worker = worker.lock().map_err(|err| { | ||||||
|  |                     anyhow::anyhow!("Lock VoltageDetection Worker Failed. {}", err) | ||||||
|  |                 })?; | ||||||
|  |  | ||||||
|  |                 let mut last_runing_at; | ||||||
|  |  | ||||||
|  |                 loop { | ||||||
|  |                     last_runing_at = Time::new().get_time(); | ||||||
|  |                     match worker.read_once(&mut adapter_pin, &mut battery_pin, &mut output_pin) { | ||||||
|  |                         Ok(_) => debug!( | ||||||
|  |                             "Adapter: {},\tBattery: {},\t Output: {}", | ||||||
|  |                             worker.adapter_voltage, worker.battery_voltage, worker.output_voltage | ||||||
|  |                         ), | ||||||
|  |                         Err(err) => warn!("Read Failed. {}", err), | ||||||
|                     } |                     } | ||||||
|                     debug!( |  | ||||||
|                         "Adapter: {},\tBattery: {},\t Output: {}", |  | ||||||
|                         worker.adapter_voltage, worker.battery_voltage, worker.output_voltage |  | ||||||
|                     ); |  | ||||||
|                     if let Some(eventloop) = unsafe { VOLTAGE_EVENTLOOP.as_mut() } { |                     if let Some(eventloop) = unsafe { VOLTAGE_EVENTLOOP.as_mut() } { | ||||||
|                         if let Err(err) = eventloop.post( |                         if let Err(err) = eventloop.post( | ||||||
|                             &mut VoltageDetectionWorker { |                             &mut VoltageDetectionWorker { | ||||||
| @@ -82,15 +105,20 @@ impl VoltageDetection { | |||||||
|                     } else { |                     } else { | ||||||
|                         warn!("EVENTLOOP IS NONE"); |                         warn!("EVENTLOOP IS NONE"); | ||||||
|                     } |                     } | ||||||
|                 } |                     let mut delta = Time::new().get_time() - last_runing_at; | ||||||
|                 Err(err) => { |  | ||||||
|                     warn!("Lock VoltageDetection Worker Failed. {}", err) |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         })?; |  | ||||||
|         timer.every(Duration::from_secs(1))?; |  | ||||||
|  |  | ||||||
|         self.watch_timer = Some(timer); |                     if delta >= Duration::from_millis(1000) { | ||||||
|  |                         delta = Duration::ZERO | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     sleep(Duration::from_millis(1000) - delta); | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             if let Err(err) = handler() { | ||||||
|  |                 warn!("init failed. {}", err) | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|         return anyhow::Ok(()); |         return anyhow::Ok(()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -104,10 +132,12 @@ impl VoltageDetectionWorker { | |||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn read_once(&mut self) -> anyhow::Result<()> { |     pub fn read_once( | ||||||
|         let adapter_pin = unsafe { Gpio1::<Input>::new() } |         &mut self, | ||||||
|             .into_analog_atten_6db() |         adapter_pin: &mut Gpio1<Atten6dB<ADC1>>, | ||||||
|             .map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?; |         battery_pin: &mut Gpio2<Atten6dB<ADC1>>, | ||||||
|  |         output_pin: &mut Gpio3<Atten6dB<ADC1>>, | ||||||
|  |     ) -> anyhow::Result<()> { | ||||||
|         match self.read_pin_once(adapter_pin) { |         match self.read_pin_once(adapter_pin) { | ||||||
|             Ok(voltage) => { |             Ok(voltage) => { | ||||||
|                 self.adapter_voltage = ((voltage as f32) * ADAPTER_OFFSET) as u16; |                 self.adapter_voltage = ((voltage as f32) * ADAPTER_OFFSET) as u16; | ||||||
| @@ -117,9 +147,6 @@ impl VoltageDetectionWorker { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         let battery_pin = unsafe { Gpio2::<Input>::new() } |  | ||||||
|             .into_analog_atten_6db() |  | ||||||
|             .map_err(|err| anyhow::anyhow!("Failed to set GPIO 2 as analog input. {}", err))?; |  | ||||||
|         match self.read_pin_once(battery_pin) { |         match self.read_pin_once(battery_pin) { | ||||||
|             Ok(voltage) => { |             Ok(voltage) => { | ||||||
|                 self.battery_voltage = ((voltage as f32) * BATTERY_OFFSET) as u16; |                 self.battery_voltage = ((voltage as f32) * BATTERY_OFFSET) as u16; | ||||||
| @@ -128,10 +155,6 @@ impl VoltageDetectionWorker { | |||||||
|                 warn!("Adapter Voltage read failed: {:?}", err); |                 warn!("Adapter Voltage read failed: {:?}", err); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         let output_pin = unsafe { Gpio3::<Input>::new() } |  | ||||||
|             .into_analog_atten_6db() |  | ||||||
|             .map_err(|err| anyhow::anyhow!("Failed to set GPIO 3 as analog input. {}", err))?; |  | ||||||
|         match self.read_pin_once(output_pin) { |         match self.read_pin_once(output_pin) { | ||||||
|             Ok(voltage) => { |             Ok(voltage) => { | ||||||
|                 self.output_voltage = ((voltage as f32) * OUTPUT_OFFSET) as u16; |                 self.output_voltage = ((voltage as f32) * OUTPUT_OFFSET) as u16; | ||||||
| @@ -145,10 +168,10 @@ impl VoltageDetectionWorker { | |||||||
|     } |     } | ||||||
|     pub fn read_pin_once<AN: Analog<ADC1>, PIN: Channel<AN, ID = u8>>( |     pub fn read_pin_once<AN: Analog<ADC1>, PIN: Channel<AN, ID = u8>>( | ||||||
|         &mut self, |         &mut self, | ||||||
|         mut pin: PIN, |         pin: &mut PIN, | ||||||
|     ) -> anyhow::Result<u16> { |     ) -> anyhow::Result<u16> { | ||||||
|         let mut adc = PoweredAdc::new(unsafe { ADC1::new() }, config::Config::new())?; |         let mut adc = PoweredAdc::new(unsafe { ADC1::new() }, config::Config::new())?; | ||||||
|         let voltage = adc.read(&mut pin); |         let voltage = adc.read(pin); | ||||||
|         match voltage { |         match voltage { | ||||||
|             Ok(voltage) => anyhow::Ok(voltage), |             Ok(voltage) => anyhow::Ok(voltage), | ||||||
|             Err(err) => { |             Err(err) => { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user