use crate::bail; use crate::fat_error::FatError; use crate::hal::{ADC1, TANK_MULTI_SAMPLE}; use embassy_time::Timer; use esp_hal::analog::adc::{Adc, AdcCalLine, AdcConfig, AdcPin, Attenuation}; use esp_hal::delay::Delay; use esp_hal::gpio::{Flex, Input, Output, OutputConfig, Pull}; use esp_hal::pcnt::channel::CtrlMode::Keep; use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment}; use esp_hal::pcnt::unit::Unit; use esp_hal::peripherals::GPIO5; use esp_hal::Blocking; use esp_println::println; use onewire::{ds18b20, Device, DeviceSearch, OneWire, DS18B20}; pub struct TankSensor<'a> { one_wire_bus: OneWire>, tank_channel: Adc<'a, ADC1<'a>, Blocking>, tank_power: Output<'a>, tank_pin: AdcPin, ADC1<'a>, AdcCalLine>>, flow_counter: Unit<'a, 1>, } impl<'a> TankSensor<'a> { pub(crate) fn create( mut one_wire_pin: Flex<'a>, adc1: ADC1<'a>, gpio5: GPIO5<'a>, tank_power: Output<'a>, flow_sensor: Input, pcnt1: Unit<'a, 1>, ) -> Result, FatError> { one_wire_pin.apply_output_config(&OutputConfig::default().with_pull(Pull::None)); let mut adc1_config = AdcConfig::new(); let tank_pin = adc1_config.enable_pin_with_cal::<_, AdcCalLine<_>>(gpio5, Attenuation::_11dB); let tank_channel = Adc::new(adc1, adc1_config); let one_wire_bus = OneWire::new(one_wire_pin, false); pcnt1.set_high_limit(Some(i16::MAX))?; let ch0 = &pcnt1.channel0; ch0.set_edge_signal(flow_sensor.peripheral_input()); ch0.set_input_mode(Hold, Increment); ch0.set_ctrl_mode(Keep, Keep); pcnt1.listen(); Ok(TankSensor { one_wire_bus, tank_channel, tank_power, tank_pin, flow_counter: pcnt1, }) } pub fn reset_flow_meter(&mut self) { self.flow_counter.pause(); self.flow_counter.clear(); } pub fn start_flow_meter(&mut self) { self.flow_counter.resume(); } pub fn get_flow_meter_value(&mut self) -> i16 { self.flow_counter.value() } pub fn stop_flow_meter(&mut self) -> i16 { self.flow_counter.pause(); self.get_flow_meter_value() } pub async fn water_temperature_c(&mut self) -> Result { //multisample should be moved to water_temperature_c let mut attempt = 1; let mut delay = Delay::new(); self.one_wire_bus.reset(&mut delay)?; let mut search = DeviceSearch::new(); let mut water_temp_sensor: Option = None; while let Some(device) = self.one_wire_bus.search_next(&mut search, &mut delay)? { if device.address[0] == ds18b20::FAMILY_CODE { water_temp_sensor = Some(device); break; } } match water_temp_sensor { Some(device) => { println!("Found one wire device: {:?}", device); let mut water_temp_sensor = DS18B20::new(device)?; let water_temp: Result = loop { let temp = self .single_temperature_c(&mut water_temp_sensor, &mut delay) .await; match &temp { Ok(res) => { println!("Water temp is {}", res); break temp; } Err(err) => { println!("Could not get water temp {} attempt {}", err, attempt) } } if attempt == 5 { break temp; } attempt += 1; }; water_temp } None => { bail!("Not found any one wire Ds18b20"); } } } async fn single_temperature_c( &mut self, sensor: &mut DS18B20, delay: &mut Delay, ) -> Result { let resolution = sensor.measure_temperature(&mut self.one_wire_bus, delay)?; Timer::after_millis(resolution.time_ms() as u64).await; let temperature = sensor.read_temperature(&mut self.one_wire_bus, delay)? as f32; if temperature == 85_f32 { bail!("Ds18b20 dummy temperature returned"); } Ok(temperature / 10_f32) } pub async fn tank_sensor_voltage(&mut self) -> Result { self.tank_power.set_high(); //let stabilize Timer::after_millis(100).await; let mut store = [0_u16; TANK_MULTI_SAMPLE]; for sample in store.iter_mut() { let value = self.tank_channel.read_oneshot(&mut self.tank_pin); //force yield Timer::after_millis(10).await; *sample = value.unwrap(); } self.tank_power.set_low(); store.sort(); let median_mv = store[TANK_MULTI_SAMPLE / 2] as f32; Ok(median_mv/1000.0) } }