added solar ina handling, adjusted website

This commit is contained in:
2025-06-20 23:29:44 +02:00
parent 34b20b1f8f
commit 04849162cd
16 changed files with 301 additions and 42 deletions

View File

@@ -23,12 +23,14 @@ use esp_idf_hal::pcnt::{
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
};
use esp_idf_sys::{gpio_hold_dis, gpio_hold_en, vTaskDelay, EspError};
use ina219::address::Address;
use ina219::address::{Address, Pin};
use ina219::calibration::{Calibration, UnCalibrated};
use ina219::SyncIna219;
use measurements::{Current, Resistance, Voltage};
use one_wire_bus::OneWire;
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
use std::result::Result::Ok as OkStd;
use ina219::configuration::{Configuration, OperatingMode};
const MS0: u8 = 1_u8;
const MS1: u8 = 0_u8;
@@ -37,15 +39,78 @@ const MS3: u8 = 4_u8;
const MS4: u8 = 2_u8;
const SENSOR_ON: u8 = 5_u8;
pub enum Charger<'a> {
SolarMpptV1 {
mppt_ina: SyncIna219<MutexDevice<'a, I2cDriver<'a>>, UnCalibrated>,
solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
charge_indicator: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
},
}
impl<'a> Charger<'a> {
pub(crate) fn powersave(&mut self) {
match self { Charger::SolarMpptV1 { mppt_ina, .. } => {
let _ = mppt_ina.set_configuration(Configuration {
reset: Default::default(),
bus_voltage_range: Default::default(),
shunt_voltage_range: Default::default(),
bus_resolution: Default::default(),
shunt_resolution: Default::default(),
operating_mode: OperatingMode::PowerDown,
}).map_err(|e| {
println!(
"Error setting ina mppt configuration during deepsleep preparation{:?}",
e
);
});
} }
}
fn set_charge_indicator(&mut self, charging: bool) -> anyhow::Result<()> {
match self {
Self::SolarMpptV1 {
charge_indicator, ..
} => {
charge_indicator.set_state(charging.into())?;
}
}
Ok(())
}
fn is_day(&self) -> bool {
match self {
Charger::SolarMpptV1 { solar_is_day, .. } => solar_is_day.get_level().into(),
}
}
fn get_mptt_voltage(&mut self) -> anyhow::Result<Voltage> {
let voltage = match self {
Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina
.bus_voltage()
.map(|v| Voltage::from_millivolts(v.voltage_mv() as f64))?,
};
Ok(voltage)
}
fn get_mptt_current(&mut self) -> anyhow::Result<Current> {
let current = match self {
Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina.shunt_voltage().map(|v| {
let shunt_voltage = Voltage::from_microvolts(v.shunt_voltage_uv().abs() as f64);
let shut_value = Resistance::from_ohms(0.05_f64);
let current = shunt_voltage.as_volts() / shut_value.as_ohms();
Current::from_amperes(current)
})?,
};
Ok(current)
}
}
pub struct V4<'a> {
mppt_ina: SyncIna219<MutexDevice<'a, I2cDriver<'a>>, UnCalibrated>,
esp: ESP<'a>,
charger: Charger<'a>,
battery_monitor: Box<dyn BatteryInteraction + Send>,
config: PlantControllerConfig,
tank_channel: AdcChannelDriver<'a, Gpio5, AdcDriver<'a, esp_idf_hal::adc::ADC1>>,
solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
signal_counter: PcntDriver<'a>,
charge_indicator: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
awake: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
light: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
tank_power: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
@@ -173,7 +238,21 @@ pub(crate) fn create_v4(
let _ = sensor_expander.pin_set_low(GPIOBank::Bank1, pin);
}
let mut mppt_ina = SyncIna219::new(MutexDevice::new(&I2C_DRIVER), Address::from_byte(68)?)?;
//TODO error handling is not done nicely here, should not break if ina is not responsive
let mut mppt_ina = SyncIna219::new(
MutexDevice::new(&I2C_DRIVER),
Address::from_pins(Pin::Vcc, Pin::Gnd),
)?;
mppt_ina.set_configuration(Configuration{
reset: Default::default(),
bus_voltage_range: Default::default(),
shunt_voltage_range: Default::default(),
bus_resolution: Default::default(),
shunt_resolution: ina219::configuration::Resolution::Avg128,
operating_mode: Default::default(),
})?;
//TODO this is probably laready done untill we are ready first time?, maybee add startup time comparison on access?
esp.delay.delay_ms(
mppt_ina
.configuration()?
@@ -181,18 +260,17 @@ pub(crate) fn create_v4(
.unwrap()
.as_millis() as u32,
);
println!("Bus Voltage: {}", mppt_ina.bus_voltage()?);
println!("Shunt Voltage: {}", mppt_ina.shunt_voltage()?);
let volt = (mppt_ina.shunt_voltage()?.shunt_voltage_mv()) as f32 / 1000_f32;
let current = volt / 0.05;
println!("Shunt Current: {}", current);
let charger = Charger::SolarMpptV1 {
mppt_ina,
solar_is_day,
charge_indicator,
};
let v = V4 {
mppt_ina,
esp,
awake,
tank_channel,
solar_is_day,
signal_counter,
light,
tank_power,
@@ -202,9 +280,9 @@ pub(crate) fn create_v4(
general_fault,
pump_expander,
sensor_expander,
charge_indicator,
config,
battery_monitor,
charger,
};
Ok(Box::new(v))
}
@@ -223,14 +301,12 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
}
fn set_charge_indicator(&mut self, charging: bool) -> anyhow::Result<()> {
self.charge_indicator
.set_state(charging.into())
.expect("cannot fail");
Ok(())
self.charger.set_charge_indicator(charging)
}
fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
self.awake.set_low().unwrap();
self.charger.powersave();
deep_sleep(duration_in_ms);
}
@@ -331,7 +407,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
}
fn is_day(&self) -> bool {
self.solar_is_day.get_level().into()
self.charger.is_day()
}
fn water_temperature_c(&mut self) -> anyhow::Result<f32> {
@@ -568,4 +644,12 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
self.esp.save_config(&self.config)?;
anyhow::Ok(())
}
fn get_mptt_voltage(&mut self) -> anyhow::Result<Voltage> {
self.charger.get_mptt_voltage()
}
fn get_mptt_current(&mut self) -> anyhow::Result<Current> {
self.charger.get_mptt_current()
}
}