Skip to content

Commit

Permalink
Add config.boost_mode.start/stop_slot_min_diff
Browse files Browse the repository at this point in the history
Add hot water slot parameter to find_working_temp_action
  • Loading branch information
leoleo73 committed Mar 5, 2024
1 parent 54c8f5a commit 599dbf3
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/brain/modes/circulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl Mode for CirculateMode {
&range,
&config.hp_circulation,
CurrentHeatDirection::Falling,
None,
None, None,
) {
Ok(WorkingTempAction::Cool { circulate: true }) => Ok(Intention::YieldHeatUps),
Ok(WorkingTempAction::Cool { circulate: false }) => {
Expand Down
3 changes: 2 additions & 1 deletion src/brain/modes/dhw_only.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl Mode for DhwOnlyMode {
&config.hp_circulation,
CurrentHeatDirection::Falling,
None,
Some(slot),
) {
Ok(WorkingTempAction::Cool { .. }) => {
debug!("Continuing to heat hot water as we would be circulating.");
Expand Down Expand Up @@ -180,7 +181,7 @@ mod test {
use crate::time_util::mytime::DummyTimeProvider;
use crate::time_util::test_utils::{date, time, utc_datetime, utc_time_slot};
use chrono::{TimeZone, Utc};
use crate::brain::python_like::config::overrun_config::{DhwBap, DhwTemps};
use crate::brain::python_like::config::overrun_config::DhwBap;

#[test]
fn test_results() {
Expand Down
2 changes: 1 addition & 1 deletion src/brain/modes/equalise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl Mode for EqualiseMode {
&working_temp,
&config.hp_circulation,
CurrentHeatDirection::Falling,
None,
None, None,
) {
Ok(WorkingTempAction::Cool { circulate: true }) => Ok(Intention::SwitchForce(
HeatingMode::TryCirculate(TryCirculateMode::new(Instant::now())),
Expand Down
3 changes: 2 additions & 1 deletion src/brain/modes/heating_mode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ pub fn handle_finish_mode(
&config.hp_circulation,
CurrentHeatDirection::Climbing,
mixed_mode,
None,
);

let heating_mode = match working_temp_action {
Expand Down Expand Up @@ -538,7 +539,7 @@ pub fn handle_finish_mode(
&info_cache.get_working_temp_range(),
&config.hp_circulation,
CurrentHeatDirection::None,
None,
None, None,
) {
Ok(WorkingTempAction::Heat { .. }) => {
info!("Call for heat: turning on");
Expand Down
3 changes: 2 additions & 1 deletion src/brain/modes/mixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ impl Mode for MixedMode {
&config.hp_circulation,
CurrentHeatDirection::Climbing,
Some(MixedState::MixedHeating),
Some(slot),
) {
Ok(WorkingTempAction::Heat { mixed_state }) => {
match allow_dhw_mixed {
Expand Down Expand Up @@ -116,7 +117,7 @@ mod tests {
use crate::brain::modes::{HeatingState, InfoCache, Mode};
use crate::brain::python_like::config::PythonBrainConfig;
use crate::brain::BrainFailure;
use crate::brain::python_like::config::overrun_config::{DhwTemps, DhwBap};
use crate::brain::python_like::config::overrun_config::DhwBap;
use crate::io::dummy_io_bundle::new_dummy_io;
use crate::io::temperatures::Sensor;
use crate::time_util::mytime::DummyTimeProvider;
Expand Down
1 change: 1 addition & 0 deletions src/brain/modes/on.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl Mode for OnMode {
&config.hp_circulation,
CurrentHeatDirection::Climbing,
Some(if heating.try_get_heat_pump()? == HeatPumpMode::BoostedHeating { MixedState::BoostedHeating } else { MixedState::NotMixed }),
None,
) {
Ok(WorkingTempAction::Heat { mixed_state: MixedState::MixedHeating }) => {
debug!("Finishing On mode to check for mixed mode.");
Expand Down
2 changes: 2 additions & 0 deletions src/brain/modes/try_circulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl Mode for TryCirculateMode {
&config.hp_circulation,
CurrentHeatDirection::Falling,
Some(MixedState::NotMixed),
None,
) {
Ok(WorkingTempAction::Heat { .. }) => {
info!("End of try period, heating is recommended.");
Expand Down Expand Up @@ -113,6 +114,7 @@ impl Mode for TryCirculateMode {
&config.hp_circulation,
CurrentHeatDirection::None,
Some(MixedState::NotMixed),
None,
) {
Ok(WorkingTempAction::Heat { .. }) => {
info!("Decided we should heat instead while trying circulation.");
Expand Down
1 change: 1 addition & 0 deletions src/brain/modes/turning_on.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl Mode for TurningOnMode {
&config.hp_circulation,
CurrentHeatDirection::None,
Some(if heating.try_get_heat_pump()? == HeatPumpMode::BoostedHeating { MixedState::BoostedHeating } else { MixedState::NotMixed }),
None,
) {
Ok(WorkingTempAction::Heat { mixed_state: MixedState::BoostedHeating }) => {
heating.set_heat_pump(HeatPumpMode::BoostedHeating, Some("Enabling boost from hot water tank"))?;
Expand Down
49 changes: 36 additions & 13 deletions src/brain/modes/working_temp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::brain::modes::heating_mode::PossibleTemperatureContainer;
use crate::brain::{modes::heating_mode::PossibleTemperatureContainer, python_like::config::overrun_config::DhwBap};
use crate::brain::python_like::config::heat_pump_circulation::HeatPumpCirculationConfig;
use crate::brain::python_like::config::working_temp_model::WorkingTempModelConfig;
use crate::io::temperatures::Sensor;
Expand Down Expand Up @@ -233,6 +233,7 @@ pub fn find_working_temp_action(
config: &HeatPumpCirculationConfig,
heat_direction: CurrentHeatDirection,
mixed_state: Option<MixedState>,
dhw_slot: Option<&DhwBap>,
) -> Result<WorkingTempAction, Sensor> {
let hx_pct = forecast_hx_pct(temps, config, &heat_direction, range)?;

Expand Down Expand Up @@ -275,7 +276,7 @@ pub fn find_working_temp_action(
}

if !should_cool {
return Ok(WorkingTempAction::Heat { mixed_state: get_mixed_state(temps, config, mixed_state, hx_pct)? });
return Ok(WorkingTempAction::Heat { mixed_state: get_mixed_state(temps, config, mixed_state, hx_pct, dhw_slot)? });
}

Ok(WorkingTempAction::Cool {
Expand All @@ -287,7 +288,8 @@ fn get_mixed_state(
temps: &impl PossibleTemperatureContainer,
config: &HeatPumpCirculationConfig,
mixed_state: Option<MixedState>,
hx_pct: f32
hx_pct: f32,
dhw_slot: Option<&DhwBap>,
) -> Result<MixedState, Sensor> {
if let Some(mixed_state) = mixed_state {
// Possible candidate for boosting. This is where the heat pump is on, but the values and pump speeds
Expand All @@ -313,18 +315,31 @@ fn get_mixed_state(
let tkfl = temps.get_sensor_temp(&Sensor::TKFL).ok_or(Sensor::TKFL)?;
let hpfl = temps.get_sensor_temp(&Sensor::HPFL).ok_or(Sensor::HPFL)?;

let slot_margin = if let Some(dhw_slot) = dhw_slot {
let temp = temps.get_sensor_temp(&dhw_slot.temps.sensor).ok_or(dhw_slot.temps.sensor.clone())?;
*temp - dhw_slot.temps.min
}
else {
0.0
};


match mixed_state {
MixedState::BoostedHeating => {
if hx_pct < config.boost_mode.stop_heat_pct && tkfl - hpfl >= config.boost_mode.stop_tkfl_hpfl_diff {
return Ok(MixedState::BoostedHeating)
if hx_pct < config.boost_mode.stop_heat_pct &&
tkfl - hpfl >= config.boost_mode.stop_tkfl_hpfl_diff &&
slot_margin > config.boost_mode.stop_slot_min_diff {
return Ok(MixedState::BoostedHeating)
}
}
MixedState::NotMixed | MixedState::MixedHeating => {
if hx_pct < config.boost_mode.start_heat_pct && tkfl - hpfl >= config.boost_mode.start_tkfl_hpfl_diff {
return Ok(MixedState::BoostedHeating)
if hx_pct < config.boost_mode.start_heat_pct &&
tkfl - hpfl >= config.boost_mode.start_tkfl_hpfl_diff &&
slot_margin > config.boost_mode.start_slot_min_diff {
return Ok(MixedState::BoostedHeating)
}
}
}
}

match mixed_state {
MixedState::MixedHeating =>
Expand Down Expand Up @@ -521,6 +536,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::None,
mixed_state,
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::NotMixed }, action);
Expand All @@ -545,7 +561,7 @@ mod test {
&range,
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::None,
None,
None, None,
)?;

assert_eq!(WorkingTempAction::Cool { circulate: true }, action);
Expand All @@ -570,7 +586,7 @@ mod test {
&range,
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::None,
None,
None, None,
)?;

assert_eq!(WorkingTempAction::Cool { circulate: false }, action);
Expand All @@ -595,7 +611,7 @@ mod test {
&range,
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::None,
None,
None, None,
)?;

assert_eq!(WorkingTempAction::Cool { circulate: false }, action);
Expand All @@ -620,7 +636,7 @@ mod test {
&range,
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Climbing,
None,
None, None,
)?;

assert_eq!(WorkingTempAction::Cool { circulate: false }, action);
Expand Down Expand Up @@ -648,6 +664,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Climbing,
Some(MixedState::NotMixed),
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::MixedHeating }, action);
Expand Down Expand Up @@ -675,6 +692,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Climbing,
Some(MixedState::MixedHeating),
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::MixedHeating }, action);
Expand Down Expand Up @@ -702,6 +720,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Climbing,
Some(MixedState::NotMixed),
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::NotMixed }, action);
Expand Down Expand Up @@ -729,6 +748,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Climbing,
Some(MixedState::MixedHeating),
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::MixedHeating }, action);
Expand Down Expand Up @@ -756,6 +776,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Climbing,
Some(MixedState::MixedHeating),
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::NotMixed }, action);
Expand All @@ -780,7 +801,7 @@ mod test {
&range,
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Climbing,
None,
None, None,
)?;

assert_eq!(WorkingTempAction::Cool { circulate: true }, action);
Expand Down Expand Up @@ -809,6 +830,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Falling,
Some(MixedState::MixedHeating),
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::NotMixed }, action);
Expand Down Expand Up @@ -837,6 +859,7 @@ mod test {
&PythonBrainConfig::default().hp_circulation,
CurrentHeatDirection::Falling,
Some(MixedState::NotMixed),
None,
)?;

assert_eq!(WorkingTempAction::Heat { mixed_state: MixedState::NotMixed }, action);
Expand Down
25 changes: 25 additions & 0 deletions src/brain/python_like/config/heat_pump_circulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,33 @@ pub struct MixedModeConfig {
#[serde_as]
#[derive(Clone, Deserialize, Debug, PartialEq)]
pub struct BoostModeConfig {
/// The maximum percentage within the heating range to start boosting
/// Lower than this the rooms will heat up sufficiently quickly without boosting
pub start_heat_pct: f32,

/// The maximum percentage within the heating range to continue boosting once started
/// If too close to start_heat_pct then this will result in excessive valve movement
/// to little effect.
pub stop_heat_pct: f32,

/// The minimum difference between the TKFL and HPFL to start boosting
/// Lower than this would achieve very little.
pub start_tkfl_hpfl_diff: f32,

/// The minimum difference between the TKFL and HPFL to continue boosting once started
/// If too close to start_tkfl_hpfl_diff then this will result in excessive valve movement
/// to little effect.
pub stop_tkfl_hpfl_diff: f32,

/// The minimum difference between the configured minimum tank temperature for the current
/// slot to start boosting
pub start_slot_min_diff: f32,

/// The minimum difference between the configured minimum tank temperature for the current
/// slot to continue boosting once started
/// If too close to start_slot_min_diff then this will result in excessive valve movement
/// to little effect.
pub stop_slot_min_diff: f32,
}

impl Default for HeatPumpCirculationConfig {
Expand All @@ -85,6 +108,8 @@ impl Default for HeatPumpCirculationConfig {
stop_heat_pct: 0.10,
start_tkfl_hpfl_diff: 2.0,
stop_tkfl_hpfl_diff: 1.0,
start_slot_min_diff: 3.5,
stop_slot_min_diff: 1.5,
},
sample_tank_time: Duration::from_secs(30),
}
Expand Down
2 changes: 1 addition & 1 deletion test/python_brain/test_brain_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ offset = 31.2
hp_pump_on_time = 70
hp_pump_off_time = 30
initial_hp_sleep = 300
boost_mode = { start_heat_pct = 0.00, stop_heat_pct = 0.10, start_tkfl_hpfl_diff = 10.0, stop_tkfl_hpfl_diff = 5.0 }
boost_mode = { start_heat_pct = 0.00, stop_heat_pct = 0.10, start_tkfl_hpfl_diff = 10.0, stop_tkfl_hpfl_diff = 5.0, start_slot_min_diff = 3.5, stop_slot_min_diff = 1.5 }

[[immersion_heater_model.parts]]
start = { time = "00:30:00", temp = 35.0 }
Expand Down

0 comments on commit 599dbf3

Please sign in to comment.