Add flowsensor prototype, add canbus to backplane

This commit is contained in:
2025-07-27 13:38:53 +02:00
parent 9f113adf7e
commit d650358bab
18 changed files with 4294 additions and 3553 deletions

View File

@@ -58,6 +58,7 @@ pub struct TankConfig {
pub tank_warn_percent: u8,
pub tank_empty_percent: u8,
pub tank_full_percent: u8,
pub ml_per_pulse: f32
}
impl Default for TankConfig {
fn default() -> Self {
@@ -68,6 +69,7 @@ impl Default for TankConfig {
tank_warn_percent: 40,
tank_empty_percent: 5,
tank_full_percent: 95,
ml_per_pulse: 0.0,
}
}
}
@@ -110,6 +112,7 @@ pub struct PlantConfig {
pub mode: PlantWateringMode,
pub target_moisture: f32,
pub pump_time_s: u16,
pub pump_limit_ml: u16,
pub pump_cooldown_min: u16,
pub pump_hour_start: u8,
pub pump_hour_end: u8,
@@ -129,6 +132,7 @@ impl Default for PlantConfig {
mode: PlantWateringMode::OFF,
target_moisture: 40.,
pump_time_s: 30,
pump_limit_ml: 5000,
pump_cooldown_min: 60,
pump_hour_start: 9,
pump_hour_end: 20,

View File

@@ -47,6 +47,7 @@ use once_cell::sync::Lazy;
use std::result::Result::Ok as OkStd;
use std::sync::Mutex;
use std::time::Duration;
use esp_idf_hal::pcnt::PCNT1;
//Only support for 8 right now!
pub const PLANT_COUNT: usize = 8;
@@ -154,6 +155,7 @@ pub struct FreePeripherals {
pub gpio29: Gpio29,
pub gpio30: Gpio30,
pub pcnt0: PCNT0,
pub pcnt1: PCNT1,
pub adc1: ADC1,
}
@@ -186,6 +188,7 @@ impl PlantHal {
let free_pins = FreePeripherals {
adc1: peripherals.adc1,
pcnt0: peripherals.pcnt0,
pcnt1: peripherals.pcnt1,
gpio0: peripherals.pins.gpio0,
gpio1: peripherals.pins.gpio1,
gpio2: peripherals.pins.gpio2,

View File

@@ -124,12 +124,16 @@ pub(crate) fn create_v3(
let one_wire_pin = peripherals.gpio18.downgrade();
let tank_power_pin = peripherals.gpio11.downgrade();
let flow_sensor_pin = peripherals.gpio4.downgrade();
let tank_sensor = TankSensor::create(
one_wire_pin,
peripherals.adc1,
peripherals.gpio5,
tank_power_pin,
);
flow_sensor_pin,
peripherals.pcnt1
)?;
let mut signal_counter = PcntDriver::new(
peripherals.pcnt0,

View File

@@ -152,13 +152,16 @@ pub(crate) fn create_v4(
let one_wire_pin = peripherals.gpio18.downgrade();
let tank_power_pin = peripherals.gpio11.downgrade();
let flow_sensor_pin = peripherals.gpio4.downgrade();
let tank_sensor = TankSensor::create(
one_wire_pin,
peripherals.adc1,
peripherals.gpio5,
tank_power_pin,
);
flow_sensor_pin,
peripherals.pcnt1
)?;
let mut signal_counter = PcntDriver::new(
peripherals.pcnt0,

View File

@@ -5,7 +5,8 @@ use esp_idf_hal::adc::oneshot::config::AdcChannelConfig;
use esp_idf_hal::adc::oneshot::{AdcChannelDriver, AdcDriver};
use esp_idf_hal::adc::{attenuation, Resolution, ADC1};
use esp_idf_hal::delay::Delay;
use esp_idf_hal::gpio::{AnyIOPin, Gpio5, InputOutput, PinDriver, Pull};
use esp_idf_hal::gpio::{AnyIOPin, AnyInputPin, Gpio5, InputOutput, PinDriver, Pull};
use esp_idf_hal::pcnt::{PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex, PCNT1};
use esp_idf_sys::EspError;
use one_wire_bus::OneWire;
@@ -13,6 +14,7 @@ pub struct TankSensor<'a> {
one_wire_bus: OneWire<PinDriver<'a, AnyIOPin, InputOutput>>,
tank_channel: AdcChannelDriver<'a, Gpio5, AdcDriver<'a, ADC1>>,
tank_power: PinDriver<'a, AnyIOPin, InputOutput>,
flow_counter: PcntDriver<'a>,
delay: Delay,
}
@@ -22,7 +24,9 @@ impl<'a> TankSensor<'a> {
adc1: ADC1,
gpio5: Gpio5,
tank_power_pin: AnyIOPin,
) -> TankSensor<'a> {
flow_sensor_pin: AnyIOPin,
pcnt1: PCNT1
) -> anyhow::Result<TankSensor<'a>> {
let mut one_wire_pin =
PinDriver::input_output_od(one_wire_pin).expect("Failed to configure pin");
one_wire_pin
@@ -47,12 +51,54 @@ impl<'a> TankSensor<'a> {
let one_wire_bus =
OneWire::new(one_wire_pin).expect("OneWire bus did not pull up after release");
TankSensor {
let mut flow_counter = PcntDriver::new(
pcnt1,
Some(flow_sensor_pin),
Option::<AnyInputPin>::None,
Option::<AnyInputPin>::None,
Option::<AnyInputPin>::None,
)?;
flow_counter.channel_config(
PcntChannel::Channel1,
PinIndex::Pin0,
PinIndex::Pin1,
&PcntChannelConfig {
lctrl_mode: PcntControlMode::Keep,
hctrl_mode: PcntControlMode::Keep,
pos_mode: PcntCountMode::Increment,
neg_mode: PcntCountMode::Hold,
counter_h_lim: i16::MAX,
counter_l_lim: 0,
},
)?;
Ok(TankSensor {
one_wire_bus,
tank_channel,
tank_power,
flow_counter,
delay: Default::default(),
}
})
}
pub fn reset_flow_meter(&mut self) {
self.flow_counter.counter_pause().unwrap();
self.flow_counter.counter_clear().unwrap();
}
pub fn start_flow_meter(&mut self) {
self.flow_counter.counter_resume().unwrap();
}
pub fn get_flow_meter_value(&mut self) -> i16 {
self.flow_counter.get_counter_value().unwrap()
}
pub fn stop_flow_meter(&mut self) -> i16 {
self.flow_counter.counter_pause().unwrap();
self.get_flow_meter_value()
}
pub fn water_temperature_c(&mut self) -> anyhow::Result<f32> {

View File

@@ -88,6 +88,9 @@ pub struct PumpResult {
max_current_ma: u16,
min_current_ma: u16,
error: bool,
flow_value_ml: f32,
flow_value_count: i16,
pump_time_s: u16,
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
@@ -583,12 +586,26 @@ pub fn do_secure_pump(
dry_run: bool,
) -> anyhow::Result<PumpResult> {
let mut current_collector = vec![0_u16; plant_config.pump_time_s.into()];
let mut flow_collector = vec![0_i16; plant_config.pump_time_s.into()];
let mut error = false;
let mut first_error = true;
let mut pump_time_s = 0;
if !dry_run {
board.board_hal.get_tank_sensor().unwrap().reset_flow_meter();
board.board_hal.get_tank_sensor().unwrap().start_flow_meter();
board.board_hal.pump(plant_id, true)?;
Delay::new_default().delay_ms(2);
Delay::new_default().delay_ms(10);
for step in 0..plant_config.pump_time_s as usize {
let flow_value = board.board_hal.get_tank_sensor().unwrap().get_flow_meter_value();
flow_collector[step] = flow_value;
let flow_value_ml = flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
println!("Flow value is {} ml, limit is {} ml raw sensor {}", flow_value_ml, plant_config.pump_limit_ml, flow_value);
if flow_value_ml > plant_config.pump_limit_ml as f32 {
println!("Flow value is reached, stopping");
break;
}
let current = board.board_hal.pump_current(plant_id);
match current {
Ok(current) => {
@@ -651,13 +668,21 @@ pub fn do_secure_pump(
}
}
Delay::new_default().delay_ms(1000);
pump_time_s += 1;
}
}
board.board_hal.get_tank_sensor().unwrap().stop_flow_meter();
let final_flow_value = board.board_hal.get_tank_sensor().unwrap().get_flow_meter_value();
let flow_value_ml = final_flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
println!("Final flow value is {} with {} ml", final_flow_value, flow_value_ml);
current_collector.sort();
Ok(PumpResult {
median_current_ma: current_collector[current_collector.len() / 2],
max_current_ma: current_collector[current_collector.len() - 1],
min_current_ma: current_collector[0],
flow_value_ml,
flow_value_count: final_flow_value,
pump_time_s,
error,
})
}