-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbattery.rs
69 lines (57 loc) · 1.96 KB
/
battery.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use super::{OsError, OsResult};
use esp_idf_svc::{
hal::{
adc::{
attenuation::DB_11,
oneshot::{
config::{AdcChannelConfig, Calibration},
AdcChannelDriver, AdcDriver,
},
Resolution, ADC1,
},
gpio::Gpio2,
},
sys::adc_atten_t,
};
use pwmp_client::pwmp_msg::{dec, Decimal};
use std::{rc::Rc, thread::sleep, time::Duration};
type BatteryGpio = Gpio2;
type BatteryAdc = ADC1;
type BatteryAdcDriver = AdcDriver<'static, BatteryAdc>;
type BatteryAdcChannelDriver = AdcChannelDriver<'static, BatteryGpio, Rc<BatteryAdcDriver>>;
const ATTEN: adc_atten_t = DB_11;
const R1: Decimal = dec!(20_000); // 20kOhm
const R2: Decimal = dec!(6_800); // 6.8kOhm
const CONFIG: AdcChannelConfig = AdcChannelConfig {
attenuation: ATTEN,
calibration: Calibration::Curve,
resolution: Resolution::Resolution12Bit,
};
pub const CRITICAL_VOLTAGE: Decimal = dec!(2.70);
pub struct Battery {
adc: Rc<BatteryAdcDriver>,
ch: BatteryAdcChannelDriver,
}
impl Battery {
pub fn new(adc: BatteryAdc, gpio: BatteryGpio) -> OsResult<Self> {
let adc = Rc::new(BatteryAdcDriver::new(adc)?);
let ch = BatteryAdcChannelDriver::new(Rc::clone(&adc), gpio, &CONFIG).unwrap();
Ok(Self { adc, ch })
}
pub fn read(&mut self, samples: u8) -> OsResult<Decimal> {
let raw = self.read_raw(samples)?;
let volts = Decimal::from(self.adc.raw_to_mv(&self.ch, raw)?) / dec!(1000);
let mut result = (volts * (R1 + R2)) / (R2);
result = result.trunc_with_scale(2);
Ok(result)
}
fn read_raw(&mut self, samples: u8) -> OsResult<u16> {
let mut avg = dec!(0);
for _ in 0..samples {
avg += Decimal::from(self.adc.read_raw(&mut self.ch)?);
sleep(Duration::from_millis(10));
}
avg /= Decimal::from(samples);
u16::try_from(avg).map_err(|_| OsError::DecimalConversion)
}
}