cleanups
This commit is contained in:
153
Software/MainBoard/rust/src/hal/water.rs
Normal file
153
Software/MainBoard/rust/src/hal/water.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
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, 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<Flex<'a>>,
|
||||
tank_channel: Adc<'a, ADC1<'a>, Blocking>,
|
||||
tank_power: Output<'a>,
|
||||
tank_pin: AdcPin<GPIO5<'a>, ADC1<'a>>,
|
||||
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<TankSensor<'a>, 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(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<f32, FatError> {
|
||||
//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<Device> = 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<f32, FatError> = 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<f32, FatError> {
|
||||
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<f32, FatError> {
|
||||
self.tank_power.set_high();
|
||||
//let stabilize
|
||||
Timer::after_millis(100).await;
|
||||
|
||||
let mut store = [0_u16; TANK_MULTI_SAMPLE];
|
||||
for multisample in 0..TANK_MULTI_SAMPLE {
|
||||
let value = self.tank_channel.read_oneshot(&mut self.tank_pin);
|
||||
//force yield
|
||||
Timer::after_millis(10).await;
|
||||
store[multisample] = value.unwrap();
|
||||
}
|
||||
self.tank_power.set_low();
|
||||
|
||||
store.sort();
|
||||
//TODO probably wrong? check!
|
||||
let median_mv = store[6] as f32 * 3300_f32 / 4096_f32;
|
||||
Ok(median_mv)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user