Slight bug fixes for ezo_orp_i2c component

Added: A new time_modifier for chlorine_pump,
Used to set maximums and stuff for chlorine pump pump
This commit is contained in:
Nicolas Bachschwell 2024-06-04 08:42:37 +02:00
parent f0be663618
commit 30db0802a0
Signed by: NBSgamesAT
GPG Key ID: 2D73288FF7AEED2F
4 changed files with 87 additions and 3 deletions

View File

@ -185,8 +185,12 @@ chlorine_pump:
id: chlorine_pump_component id: chlorine_pump_component
disable_clock: false disable_clock: false
proportional_band: 200 proportional_band: 200
cycle_time: 300
target: 700 target: 700
# get_target: !lambda return id(chlorine_target).state; # get_target: !lambda return id(chlorine_target).state;
cycle_modifiers:
min_on_time: 30
max_on_time: 240
on_pump_value: on_pump_value:
- lambda: |- - lambda: |-
if(pState != id(last_pump_state)){ if(pState != id(last_pump_state)){

View File

@ -23,6 +23,12 @@ CONF_DISABLE_CLOCK="disable_clock"
CONF_TARGET="target" CONF_TARGET="target"
CONF_TARGET_LAMBDA="get_target" CONF_TARGET_LAMBDA="get_target"
CONF_PUMP_TIME_DIVIDER = "pump_time_divider" CONF_PUMP_TIME_DIVIDER = "pump_time_divider"
CONF_CYCLE_MODIFIERS = "cycle_modifiers"
CONF_MIN_ON_TIME = "min_on_time"
CONF_MAX_ON_TIME = "max_on_time"
CONF_CYCLE_TIME_MULTIPLIER = "on_time_modifier"
CONF_CYCLE_TIME_OFFSET = "on_time_offset"
CONF_CYCLE_TIME_IGNORE_MAX_X_BELOW_TARGET = "ignore_max_x_below_target"
def to_proportional_band(value): def to_proportional_band(value):
try: try:
@ -48,6 +54,19 @@ ManualDoseAction = chlorine_pump_ns.class_("ChlorineDose", automation.Action)
def validate_config(config): def validate_config(config):
if (config.get(CONF_TARGET_LAMBDA, None) is not None) is not (config.get(CONF_TARGET, None) not in config): if (config.get(CONF_TARGET_LAMBDA, None) is not None) is not (config.get(CONF_TARGET, None) not in config):
raise cv.Invalid("Either a fixed target or an get_target lambda must be set to get a target") raise cv.Invalid("Either a fixed target or an get_target lambda must be set to get a target")
if CONF_CYCLE_MODIFIERS in config:
cycle_mod = config.get(CONF_CYCLE_MODIFIERS)
if cycle_mod[CONF_MIN_ON_TIME] >= config[CONF_PUMP_CYCLE_TIME]:
raise cv.Invalid("min_on_time must be smaller than cycle_time(default = 360)")
if cycle_mod.get(CONF_MAX_ON_TIME) in cycle_mod and config[CONF_PUMP_CYCLE_TIME] < cycle_mod[CONF_MAX_ON_TIME]:
raise cv.Invalid("max_on_time must be smaller or equal cycle_time(default = 360)")
if cycle_mod.get(CONF_MAX_ON_TIME) in cycle_mod and cycle_mod[CONF_MIN_ON_TIME] >= cycle_mod[CONF_MAX_ON_TIME]:
raise cv.Invalid("min_on_time must be smaller than max_on_time")
if cycle_mod.get(CONF_CYCLE_TIME_OFFSET) >= config[CONF_PUMP_CYCLE_TIME]:
raise cv.Invalid("cycle_time_offset must be smaller than cycle_time(default = 360)")
if cycle_mod.get(CONF_CYCLE_TIME_IGNORE_MAX_X_BELOW_TARGET) in cycle_mod and cycle_mod[CONF_CYCLE_TIME_IGNORE_MAX_X_BELOW_TARGET] <= config[CONF_PUMP_PROPORTIONAL_BAND]:
raise cv.Invalid("ignore_max_x_below_target must larger than proportional_band(default = 200)")
return config return config
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
@ -61,6 +80,14 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_TARGET): cv.int_range(300, 1400), cv.Optional(CONF_TARGET): cv.int_range(300, 1400),
cv.Optional(CONF_PUMP_TIME_DIVIDER, 2): cv.float_range(1, 5), cv.Optional(CONF_PUMP_TIME_DIVIDER, 2): cv.float_range(1, 5),
cv.Optional(CONF_TARGET_LAMBDA, 2): cv.templatable(cv.float_), cv.Optional(CONF_TARGET_LAMBDA, 2): cv.templatable(cv.float_),
cv.Optional(CONF_CYCLE_MODIFIERS): cv.All({
cv.Optional(CONF_MIN_ON_TIME, 0): cv.int_range(0, 1400),
cv.Optional(CONF_MAX_ON_TIME): cv.int_range(0, 1400),
cv.Optional(CONF_CYCLE_TIME_MULTIPLIER, 1): cv.float_range(0.01, 5.0),
cv.Optional(CONF_CYCLE_TIME_OFFSET, 0): cv.int_range(0, 1400),
cv.Optional(CONF_CYCLE_TIME_IGNORE_MAX_X_BELOW_TARGET): cv.int_range(100 - 1500),
}),
cv.Optional(CONF_PUMP_VALUE): automation.validate_automation({ cv.Optional(CONF_PUMP_VALUE): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorOutputTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorOutputTrigger),
} }
@ -69,6 +96,7 @@ CONFIG_SCHEMA = cv.All(
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorCycleTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorCycleTrigger),
} }
), ),
}), }),
validate_config validate_config
) )
@ -132,6 +160,16 @@ async def to_code(config):
#prop_band = yield cg.get_variable(config[CONF_PUMP_PROPORTIONAL_BAND]) #prop_band = yield cg.get_variable(config[CONF_PUMP_PROPORTIONAL_BAND])
cg.add(var.set_prop_band(config[CONF_PUMP_PROPORTIONAL_BAND])) cg.add(var.set_prop_band(config[CONF_PUMP_PROPORTIONAL_BAND]))
if CONF_CYCLE_MODIFIERS in config:
conf = config.get(CONF_CYCLE_MODIFIERS)
cg.add(var.set_min_on_time(conf[CONF_MIN_ON_TIME]))
cg.add(var.set_time_multiplier(conf[CONF_CYCLE_TIME_MULTIPLIER]))
cg.add(var.set_time_offset(conf[CONF_CYCLE_TIME_OFFSET]))
if CONF_MAX_ON_TIME in conf:
cg.add(var.set_max_on_time(conf[CONF_MAX_ON_TIME]))
if CONF_CYCLE_TIME_IGNORE_MAX_X_BELOW_TARGET in conf:
cg.add(var.set_ignore_max_x_below_target(conf[CONF_CYCLE_TIME_IGNORE_MAX_X_BELOW_TARGET]))
#cg.add(var.set_state(config[CONF_STATE])) #cg.add(var.set_state(config[CONF_STATE]))
if CONF_TARGET not in config: if CONF_TARGET not in config:
template_ = await cg.templatable(config[CONF_TARGET_LAMBDA], [], float) template_ = await cg.templatable(config[CONF_TARGET_LAMBDA], [], float)

View File

@ -2,6 +2,7 @@
#include "esphome/core/automation.h" #include "esphome/core/automation.h"
#include "esphome/components/output/binary_output.h" #include "esphome/components/output/binary_output.h"
#include "Arduino.h"
static const char *const TAG = "chlorine_pump"; static const char *const TAG = "chlorine_pump";
@ -26,13 +27,18 @@ class ChlorinePump : public Component {
float tOn_divider_; float tOn_divider_;
std::function<float()> target_lambda_ = nullptr; std::function<float()> target_lambda_ = nullptr;
int min_on_time_ = 0;
int max_on_time_ = -1;
float on_time_multiplier_ = 1;
int on_time_offset_ = 0;
int ignore_max_x_below_target_ = -1;
public: public:
ChlorinePump(){ ChlorinePump(){
last_action = 0; last_action = 0;
} }
void disable_clock(bool disable_clock){ void disable_clock(bool disable_clock){
this->disable_clock_ = disable_clock; this->disable_clock_ = disable_clock;
} }
@ -55,6 +61,23 @@ class ChlorinePump : public Component {
this->target_ = target; this->target_ = target;
} }
// Cycle Time Modifiers
void set_min_on_time(int min_on_time){
this->min_on_time_ = min_on_time;
}
void set_max_on_time(int max_on_time){
this->max_on_time_ = max_on_time;
}
void set_time_multiplier(float time_multi){
this->on_time_multiplier_ = time_multi;
}
void set_time_offset(int offset){
this->on_time_offset_ = offset;
}
void set_ignore_max_x_below_target(int set_below){
this->ignore_max_x_below_target_ = set_below;
}
void setup() override { void setup() override {
last_action = millis(); last_action = millis();
if(disable_clock_ && sensor_ != nullptr){ if(disable_clock_ && sensor_ != nullptr){
@ -120,7 +143,19 @@ class ChlorinePump : public Component {
return (int) timeInSeconds; return (int) timeInSeconds;
} }
int calculate_changed_on_time(int tOn, float last_mesurement){
if(ignore_max_x_below_target_ != -1 && (float)(target_ - ignore_max_x_below_target_) >= last_mesurement){
return cycle_time;
}
tOn = (int)((float) tOn * on_time_multiplier_);
tOn += on_time_offset_;
if(tOn < min_on_time_) tOn = min_on_time_;
if(max_on_time_ != -1 && tOn > max_on_time_) tOn = max_on_time_;
return tOn;
}
void add_on_pump_callback(std::function<void(bool, int)> &&callback){ void add_on_pump_callback(std::function<void(bool, int)> &&callback){
this->callback_pump_.add(std::move(callback)); this->callback_pump_.add(std::move(callback));
@ -134,7 +169,10 @@ class ChlorinePump : public Component {
if(tOn == 0 && tOff == 0 && state){ if(tOn == 0 && tOff == 0 && state){
int seconds = calculatePumpTimeSeconds(last_mesurement); int seconds = calculatePumpTimeSeconds(last_mesurement);
tOn = seconds; if(seconds != 0)
tOn = calculate_changed_on_time(seconds, last_mesurement);
else
tOn = 0;
tOff = cycle_time - tOn; tOff = cycle_time - tOn;
if(seconds == 0){ if(seconds == 0){

View File

@ -42,11 +42,15 @@ void EzoOrpSensor::read_response(int maxLength, SensorAction action) {
if(i2c::ERROR_OK != this->read(data, maxLength)){ if(i2c::ERROR_OK != this->read(data, maxLength)){
ESP_LOGW(TAG, "Error Occured while reading respnse!"); ESP_LOGW(TAG, "Error Occured while reading respnse!");
busy_ = false;
runScheduledAction();
return; return;
} }
if(data[0] != 1 && data[0] != 255){ if(data[0] != 1 && data[0] != 255){
ESP_LOGW(TAG, "Read status code of %d, (Operation: %d)", data[0], action); ESP_LOGW(TAG, "Read status code of %d, (Operation: %d)", data[0], action);
busy_ = false;
runScheduledAction();
return; return;
} }