All the code changes to the chlorine pump... More will follow
This commit is contained in:
parent
a96531dda9
commit
3d7e80154a
141
chlorPump.yaml
141
chlorPump.yaml
@ -3,6 +3,10 @@ esphome:
|
|||||||
project:
|
project:
|
||||||
name: nbsgamesat.chlorine-pump
|
name: nbsgamesat.chlorine-pump
|
||||||
version: "0.2"
|
version: "0.2"
|
||||||
|
on_boot:
|
||||||
|
priority: 600
|
||||||
|
then:
|
||||||
|
output.turn_on: whatever
|
||||||
|
|
||||||
esp8266:
|
esp8266:
|
||||||
board: nodemcuv2
|
board: nodemcuv2
|
||||||
@ -17,7 +21,15 @@ external_components:
|
|||||||
- source:
|
- source:
|
||||||
type: local
|
type: local
|
||||||
path: external_components/
|
path: external_components/
|
||||||
components: [ analog_orp ]
|
components: [ analog_orp, chlorine_pump ]
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: last_pump_state
|
||||||
|
type: bool
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "false"
|
||||||
|
- id: last_cycle_info
|
||||||
|
type: std::string
|
||||||
|
|
||||||
api:
|
api:
|
||||||
encryption:
|
encryption:
|
||||||
@ -27,31 +39,144 @@ wifi:
|
|||||||
ssid: !secret wifi_ssid
|
ssid: !secret wifi_ssid
|
||||||
password: !secret wifi_password
|
password: !secret wifi_password
|
||||||
fast_connect: true
|
fast_connect: true
|
||||||
|
on_connect:
|
||||||
|
output.turn_off: whatever
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
pin: D3
|
pin: D6
|
||||||
id: pump_switch
|
id: pump_switch
|
||||||
|
- platform: gpio
|
||||||
|
pin:
|
||||||
|
number: D0
|
||||||
|
inverted: true
|
||||||
|
id: whatever
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
id: pool_pump
|
id: pool_pump
|
||||||
pin: D2
|
pin:
|
||||||
|
number: D2
|
||||||
|
inverted: true
|
||||||
|
mode:
|
||||||
|
input: true
|
||||||
|
pullup: true
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: manage_power
|
||||||
|
switch_state: !lambda return id(power).state;
|
||||||
|
- platform: template
|
||||||
|
id: pump_state
|
||||||
|
name: Pump State
|
||||||
|
lambda: !lambda return id(last_pump_state);
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: manage_power
|
||||||
|
parameters:
|
||||||
|
switch_state: bool
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
return switch_state && id(pool_pump).state;
|
||||||
|
then:
|
||||||
|
- chlorine_pump.start: {}
|
||||||
|
- text_sensor.template.publish:
|
||||||
|
id: cycle_text_info
|
||||||
|
state: !lambda 'return "ON... ";'
|
||||||
|
else:
|
||||||
|
- chlorine_pump.stop: {}
|
||||||
|
- text_sensor.template.publish:
|
||||||
|
id: cycle_text_info
|
||||||
|
state: !lambda 'return "PUMP: OFF";'
|
||||||
|
|
||||||
|
switch:
|
||||||
|
- platform: template
|
||||||
|
name: Chlorine Pump Power
|
||||||
|
id: power
|
||||||
|
optimistic: true
|
||||||
|
inverted: off
|
||||||
|
restore_mode: RESTORE_DEFAULT_ON
|
||||||
|
turn_on_action:
|
||||||
|
- script.execute:
|
||||||
|
id: manage_power
|
||||||
|
switch_state: true
|
||||||
|
turn_off_action:
|
||||||
|
- script.execute:
|
||||||
|
id: manage_power
|
||||||
|
switch_state: false
|
||||||
|
|
||||||
|
button:
|
||||||
|
- platform: template
|
||||||
|
name: Prime
|
||||||
|
id: prime
|
||||||
|
on_press:
|
||||||
|
- chlorine_pump.prime: {}
|
||||||
|
- text_sensor.template.publish:
|
||||||
|
id: cycle_text_info
|
||||||
|
state: !lambda 'return "PRIMING??";'
|
||||||
|
|
||||||
|
number:
|
||||||
|
- platform: template
|
||||||
|
name: Chlorine Target
|
||||||
|
id: chlorine_target
|
||||||
|
initial_value: 700
|
||||||
|
restore_value: true
|
||||||
|
min_value: 300
|
||||||
|
max_value: 1400
|
||||||
|
optimistic: true
|
||||||
|
step: 1.0
|
||||||
|
set_action:
|
||||||
|
then:
|
||||||
|
- chlorine_pump.set_target:
|
||||||
|
target: !lambda return x;
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
- platform: template
|
||||||
|
name: Cycle Info
|
||||||
|
id: cycle_text_info
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: analog_orp
|
- platform: analog_orp
|
||||||
name: Chlorine
|
name: Chlorine
|
||||||
id: chlorine_sensor
|
id: chlorine_sensor
|
||||||
pin: A0
|
pin: A0
|
||||||
zero_point: 640
|
zero_point: 673
|
||||||
inverted: true
|
inverted: true
|
||||||
update_interval: 1s
|
update_interval: 1s
|
||||||
|
# print_raw: true
|
||||||
average:
|
average:
|
||||||
mesurements: 5
|
mesurements: 15
|
||||||
send_state_every: 10
|
send_state_every: 10
|
||||||
on_completely_new_value:
|
# on_value_read:
|
||||||
|
# - lambda: |-
|
||||||
|
# ESP_LOGD("WHAT", "Chlorine_value, %.1f", x);
|
||||||
|
- platform: hx711
|
||||||
|
name: "Chlorine Canister Levels"
|
||||||
|
dout_pin: D5
|
||||||
|
clk_pin: D1
|
||||||
|
gain: 128
|
||||||
|
update_interval: 20s
|
||||||
|
accuracy_decimals: 1
|
||||||
|
filters:
|
||||||
|
- calibrate_linear:
|
||||||
|
- 47608 -> 0
|
||||||
|
- 590566 -> 100
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
|
||||||
|
chlorine_pump:
|
||||||
|
pump: pump_switch
|
||||||
|
sensor: chlorine_sensor
|
||||||
|
id: chlorine_pump_component
|
||||||
|
target: 700
|
||||||
|
disable_clock: true
|
||||||
|
on_pump_value:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
ESP_LOGD("WHAT", "Just a test %.1f", value);
|
if(pState != id(last_pump_state)){
|
||||||
# GPIO A0 to acd
|
id(last_pump_state) = pState;
|
||||||
|
}
|
||||||
|
on_cycle_start:
|
||||||
|
- lambda: |-
|
||||||
|
id(cycle_text_info).publish_state("tOn: " + std::to_string(tOn) + "s\n tOff: " + std::to_string(tOff) + "s");
|
||||||
|
|
||||||
# Here is space for any display implementation that could possibliy be. Have fun OK
|
# Here is space for any display implementation that could possibliy be. Have fun OK
|
@ -0,0 +1 @@
|
|||||||
|
CODEOWNERS = ["@nbsgames"]
|
@ -109,6 +109,9 @@ void ChlorineSensor::dump_config(){
|
|||||||
ESP_LOGCONFIG(TAG, " Inverted: %s", inverted_ ? "true" : "false");
|
ESP_LOGCONFIG(TAG, " Inverted: %s", inverted_ ? "true" : "false");
|
||||||
ESP_LOGCONFIG(TAG, " Print Raw: %s", print_raw_ ? "true" : "false");
|
ESP_LOGCONFIG(TAG, " Print Raw: %s", print_raw_ ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
bool ChlorineSensor::has_averager(){
|
||||||
|
return averager_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Nullwert : 680
|
Nullwert : 680
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esphome.h"
|
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/gpio.h"
|
#include "esphome/core/gpio.h"
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace analog_orp {
|
namespace analog_orp {
|
||||||
@ -33,6 +33,7 @@ class ChlorineSensor: public PollingComponent, public sensor::Sensor {
|
|||||||
void add_average_change_callback(std::function<void(float)> &&callback);
|
void add_average_change_callback(std::function<void(float)> &&callback);
|
||||||
void add_new_value_callback(std::function<void(float)> &&callback);
|
void add_new_value_callback(std::function<void(float)> &&callback);
|
||||||
void init_averager(int mesurements, int send_average_every);
|
void init_averager(int mesurements, int send_average_every);
|
||||||
|
bool has_averager();
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
float sample();
|
float sample();
|
||||||
|
@ -26,7 +26,7 @@ CONF_AVERAGE_NEW = "on_completely_new_value"
|
|||||||
|
|
||||||
UNIT_MILLI_VOLT = "mV"
|
UNIT_MILLI_VOLT = "mV"
|
||||||
|
|
||||||
ICON_LIGHTNING_BOLT="mdi:lightning-bolt"
|
ICON_TEST_TUBE="mdi:test-tube"
|
||||||
|
|
||||||
ChlorineValueRead = chlorine_sensor_ns.class_(
|
ChlorineValueRead = chlorine_sensor_ns.class_(
|
||||||
"ChlorineValueReadTrigger", automation.Trigger.template(cg.float_)
|
"ChlorineValueReadTrigger", automation.Trigger.template(cg.float_)
|
||||||
@ -45,7 +45,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
accuracy_decimals=2,
|
accuracy_decimals=2,
|
||||||
device_class=DEVICE_CLASS_VOLTAGE,
|
device_class=DEVICE_CLASS_VOLTAGE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
icon=ICON_LIGHTNING_BOLT
|
icon=ICON_TEST_TUBE
|
||||||
).extend({
|
).extend({
|
||||||
cv.Required(CONF_SENSOR_PIN): adc.validate_adc_pin,
|
cv.Required(CONF_SENSOR_PIN): adc.validate_adc_pin,
|
||||||
cv.Required(CONF_ZERO_POINT): cv.Range(min=0, max=1023),
|
cv.Required(CONF_ZERO_POINT): cv.Range(min=0, max=1023),
|
||||||
@ -88,12 +88,12 @@ async def to_code(config):
|
|||||||
|
|
||||||
for conf in averager_config.get(CONF_ON_READ_VALUE, []):
|
for conf in averager_config.get(CONF_ON_READ_VALUE, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
await automation.build_automation(trigger, [(float, "value")], conf)
|
await automation.build_automation(trigger, [(float, "x")], conf)
|
||||||
|
|
||||||
for conf in averager_config.get(CONF_AVERAGE_ON_VALUE, []):
|
for conf in averager_config.get(CONF_AVERAGE_ON_VALUE, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
await automation.build_automation(trigger, [(float, "value")], conf)
|
await automation.build_automation(trigger, [(float, "x")], conf)
|
||||||
|
|
||||||
for conf in averager_config.get(CONF_AVERAGE_NEW, []):
|
for conf in averager_config.get(CONF_AVERAGE_NEW, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
await automation.build_automation(trigger, [(float, "value")], conf)
|
await automation.build_automation(trigger, [(float, "x")], conf)
|
128
external_components/chlorine_pump/__init__.py
Normal file
128
external_components/chlorine_pump/__init__.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome import automation
|
||||||
|
from esphome.components import output
|
||||||
|
from esphome.components.analog_orp.sensor import ChlorineSensor
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
CONF_TRIGGER_ID
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
DEPENDENCIES=["sensor"]
|
||||||
|
|
||||||
|
chlorine_pump_ns = cg.esphome_ns.namespace('chlorine_pump')
|
||||||
|
ChlorinePump = chlorine_pump_ns.class_('ChlorinePump', cg.Component)
|
||||||
|
|
||||||
|
CONF_SENSOR = "sensor"
|
||||||
|
CONF_PUMP_OUT = "pump"
|
||||||
|
CONF_PUMP_CYCLE_TIME = "cycle_time"
|
||||||
|
CONF_PUMP_PROPORTIONAL_BAND = "proportional_band"
|
||||||
|
CONF_PUMP_VALUE = "on_pump_value"
|
||||||
|
CONF_CYCLE_START = "on_cycle_start"
|
||||||
|
CONF_DISABLE_CLOCK="disable_clock"
|
||||||
|
CONF_TARGET="target"
|
||||||
|
|
||||||
|
def to_proportional_band(value):
|
||||||
|
try:
|
||||||
|
value = int(value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
# pylint: disable=raise-missing-from
|
||||||
|
raise cv.Invalid(f"")
|
||||||
|
return cv.one_of(20, 50, 100, 150, 200, 250)(value)
|
||||||
|
|
||||||
|
ChlorSensorOutputTrigger = chlorine_pump_ns.class_(
|
||||||
|
"ChlorSensorOutputTrigger", automation.Trigger.template(cg.bool_, cg.int_)
|
||||||
|
)
|
||||||
|
ChlorSensorCycleTrigger = chlorine_pump_ns.class_(
|
||||||
|
"ChlorSensorCycleTrigger", automation.Trigger.template(cg.int_, cg.int_)
|
||||||
|
)
|
||||||
|
|
||||||
|
PrimeAction = chlorine_pump_ns.class_("ChlorinePrime", automation.Action)
|
||||||
|
StartAction = chlorine_pump_ns.class_("ChlorineStart", automation.Action)
|
||||||
|
StopAction = chlorine_pump_ns.class_("ChlorineStop", automation.Action)
|
||||||
|
SetTargetAction = chlorine_pump_ns.class_("ChlorineSetTarget", automation.Action)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.COMPONENT_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_id(ChlorinePump),
|
||||||
|
cv.Required(CONF_PUMP_OUT): cv.use_id(output.BinaryOutput),
|
||||||
|
cv.Optional(CONF_SENSOR): cv.use_id(ChlorineSensor),
|
||||||
|
cv.Optional(CONF_PUMP_CYCLE_TIME, default=360): cv.int_range(min=30, max=1400),
|
||||||
|
cv.Optional(CONF_PUMP_PROPORTIONAL_BAND, default=200): to_proportional_band,
|
||||||
|
cv.Optional(CONF_DISABLE_CLOCK, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_TARGET, 700): cv.int_range(300, 1400),
|
||||||
|
cv.Optional(CONF_PUMP_VALUE): automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorOutputTrigger),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CYCLE_START): automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorCycleTrigger),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ACTION_SCHEMA = cv.Schema({
|
||||||
|
cv.GenerateID(): cv.use_id(ChlorinePump)
|
||||||
|
})
|
||||||
|
|
||||||
|
@automation.register_action("chlorine_pump.prime", PrimeAction, ACTION_SCHEMA)
|
||||||
|
async def prime_action_to_code(config, action_id, template_arg, args):
|
||||||
|
paren = await cg.get_variable(config[CONF_ID])
|
||||||
|
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||||
|
|
||||||
|
@automation.register_action("chlorine_pump.start", StartAction, ACTION_SCHEMA)
|
||||||
|
async def start_action_to_code(config, action_id, template_arg, args):
|
||||||
|
paren = await cg.get_variable(config[CONF_ID])
|
||||||
|
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||||
|
|
||||||
|
@automation.register_action("chlorine_pump.stop", StopAction, ACTION_SCHEMA)
|
||||||
|
async def stop_action_to_code(config, action_id, template_arg, args):
|
||||||
|
paren = await cg.get_variable(config[CONF_ID])
|
||||||
|
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||||
|
|
||||||
|
@automation.register_action("chlorine_pump.set_target", SetTargetAction, ACTION_SCHEMA.extend({
|
||||||
|
cv.Required(CONF_TARGET): cv.templatable(cv.float_),
|
||||||
|
}))
|
||||||
|
async def number_set_to_code(config, action_id, template_arg, args):
|
||||||
|
paren = await cg.get_variable(config[CONF_ID])
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||||
|
template_ = await cg.templatable(config[CONF_TARGET], args, float)
|
||||||
|
cg.add(var.set_value(template_))
|
||||||
|
return var
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
#yield mqtt.register_mqtt_component(var, config)
|
||||||
|
|
||||||
|
#btnReset = yield cg.gpio_pin_expression(config[CONF_SENSOR_PIN])
|
||||||
|
#cg.add(var.set_input_pin(btnReset))
|
||||||
|
|
||||||
|
|
||||||
|
sensor = await cg.get_variable(config[CONF_SENSOR])
|
||||||
|
cg.add(var.set_sensor(sensor))
|
||||||
|
|
||||||
|
pump_out = await cg.get_variable(config[CONF_PUMP_OUT])
|
||||||
|
cg.add(var.set_pump_out(pump_out))
|
||||||
|
|
||||||
|
cg.add(var.set_cycle_time(config[CONF_PUMP_CYCLE_TIME])) # Needs be configured before sensor
|
||||||
|
|
||||||
|
cg.add(var.disable_clock(config[CONF_DISABLE_CLOCK]))
|
||||||
|
#cycle_time = yield cg.get_variable(config[CONF_PUMP_CYCLE_TIME])
|
||||||
|
|
||||||
|
#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_state(config[CONF_STATE]))
|
||||||
|
|
||||||
|
|
||||||
|
if CONF_PUMP_VALUE in config:
|
||||||
|
for conf in config.get(CONF_PUMP_VALUE, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(trigger, [(bool, "pState"), (int, "pTime")], conf)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_CYCLE_START, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(trigger, [(int, "tOn"), (int, "tOff")], conf)
|
216
external_components/chlorine_pump/pump_cycle.h
Normal file
216
external_components/chlorine_pump/pump_cycle.h
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
|
#include "esphome/components/gpio/output/gpio_binary_output.h"
|
||||||
|
#include "esphome/components/analog_orp/analog_orp.h"
|
||||||
|
|
||||||
|
static const char *const TAG = "chlorine_pump";
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace chlorine_pump {
|
||||||
|
|
||||||
|
class ChlorinePump : public Component {
|
||||||
|
protected:
|
||||||
|
|
||||||
|
analog_orp::ChlorineSensor *sensor_;
|
||||||
|
gpio::GPIOBinaryOutput *pump_out;
|
||||||
|
int cycle_time;
|
||||||
|
int prop_band;
|
||||||
|
bool state = true;
|
||||||
|
unsigned long last_action;
|
||||||
|
bool disable_clock_ = false;
|
||||||
|
CallbackManager<void(bool, int)> callback_pump_;
|
||||||
|
CallbackManager<void(int, int)> callback_cycle_;
|
||||||
|
int tOn = 0;
|
||||||
|
int tOff = 0;
|
||||||
|
float target_ = 700.0f;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ChlorinePump(){
|
||||||
|
last_action = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void disable_clock(bool disable_clock){
|
||||||
|
this->disable_clock_ = disable_clock;
|
||||||
|
}
|
||||||
|
void set_sensor(analog_orp::ChlorineSensor *sensor){
|
||||||
|
this->sensor_ = sensor;
|
||||||
|
}
|
||||||
|
void set_pump_out(gpio::GPIOBinaryOutput *pump_out){
|
||||||
|
this->pump_out = pump_out;
|
||||||
|
}
|
||||||
|
void set_cycle_time(int time_in_sec){
|
||||||
|
this->cycle_time = time_in_sec;
|
||||||
|
}
|
||||||
|
void set_prop_band(int prop_band){
|
||||||
|
this->prop_band = prop_band;
|
||||||
|
}
|
||||||
|
void set_target(int target){
|
||||||
|
this->target_ = (float) target;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() override {
|
||||||
|
last_action = millis();
|
||||||
|
if(disable_clock_ && sensor_ != nullptr){
|
||||||
|
if(!sensor_->has_averager()) sensor_->add_on_state_callback([=](float val) -> void {
|
||||||
|
this->tick_time(val);
|
||||||
|
});
|
||||||
|
if(sensor_->has_averager()) sensor_->add_average_change_callback([=](float val) -> void {
|
||||||
|
this->tick_time(val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void prime() {
|
||||||
|
tOn = 30;
|
||||||
|
tOff = 2;
|
||||||
|
this->pump_out->turn_on();
|
||||||
|
}
|
||||||
|
void start() {
|
||||||
|
this->state = true;
|
||||||
|
}
|
||||||
|
void stop() {
|
||||||
|
this->state = false;
|
||||||
|
tOn = 0;
|
||||||
|
tOff = 0;
|
||||||
|
this->pump_out->turn_off();
|
||||||
|
}
|
||||||
|
bool get_state(){
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setMillisPrecies(unsigned long waitPeriod){
|
||||||
|
|
||||||
|
if(last_action + waitPeriod + waitPeriod > millis()){
|
||||||
|
last_action += waitPeriod;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ESP_LOGW(TAG, "Reset millis(). Did the system experience a halt for some reason?");
|
||||||
|
last_action = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int calculatePumpTimeSeconds(float last_mesurement){
|
||||||
|
|
||||||
|
if(last_mesurement >= target_) return 0;
|
||||||
|
|
||||||
|
float currentVal = target_ - last_mesurement;
|
||||||
|
float proportionalValue = (currentVal / (float) prop_band);
|
||||||
|
float timeInSeconds = proportionalValue * (float) cycle_time;
|
||||||
|
|
||||||
|
if(timeInSeconds > cycle_time) timeInSeconds = cycle_time;
|
||||||
|
|
||||||
|
return (int) timeInSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void add_on_pump_callback(std::function<void(bool, int)> &&callback){
|
||||||
|
this->callback_pump_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
void add_on_cycle_callback(std::function<void(int, int)> &&callback){
|
||||||
|
this->callback_cycle_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tick_time(float last_mesurement){
|
||||||
|
|
||||||
|
if(tOn == 0 && tOff == 0 && state){
|
||||||
|
int seconds = calculatePumpTimeSeconds(last_mesurement);
|
||||||
|
|
||||||
|
if(seconds == 0){
|
||||||
|
tOn = 0;
|
||||||
|
tOff = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
tOn = seconds;
|
||||||
|
tOff = cycle_time - tOn;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Time => tOn: %d, tOff: %d", tOn, tOff);
|
||||||
|
|
||||||
|
this->callback_cycle_.call(tOn, tOff);
|
||||||
|
}
|
||||||
|
else if(tOn > 0) {
|
||||||
|
this->callback_pump_.call(true, tOn);
|
||||||
|
--tOn;
|
||||||
|
pump_out->turn_on();
|
||||||
|
}
|
||||||
|
else if(tOff > 0) {
|
||||||
|
this->callback_pump_.call(false, tOff);
|
||||||
|
--tOff;
|
||||||
|
pump_out->turn_off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() override{
|
||||||
|
|
||||||
|
if(disable_clock_) return;
|
||||||
|
|
||||||
|
if(millis() - last_action > 1000){
|
||||||
|
|
||||||
|
tick_time(sensor_->get_state());
|
||||||
|
|
||||||
|
setMillisPrecies(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ChlorSensorOutputTrigger : public Trigger<bool, int> {
|
||||||
|
public:
|
||||||
|
explicit ChlorSensorOutputTrigger(ChlorinePump *parent) {
|
||||||
|
parent->add_on_pump_callback([this](bool output_state, int value) { this->trigger(output_state, value); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class ChlorSensorCycleTrigger : public Trigger<int, int> {
|
||||||
|
public:
|
||||||
|
explicit ChlorSensorCycleTrigger(ChlorinePump *parent) {
|
||||||
|
parent->add_on_cycle_callback([this](int on_time, int off_time) { this->trigger(on_time, off_time); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class ChlorinePrime : public Action<Ts...> {
|
||||||
|
public:
|
||||||
|
ChlorinePrime(ChlorinePump *pump) : pump_(pump) {}
|
||||||
|
|
||||||
|
void play(Ts... x) override { this->pump_->prime(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ChlorinePump *pump_;
|
||||||
|
};
|
||||||
|
template<typename... Ts> class ChlorineStart : public Action<Ts...> {
|
||||||
|
public:
|
||||||
|
ChlorineStart(ChlorinePump *pump) : pump_(pump) {}
|
||||||
|
|
||||||
|
void play(Ts... x) override { this->pump_->start(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ChlorinePump *pump_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class ChlorineStop : public Action<Ts...> {
|
||||||
|
public:
|
||||||
|
ChlorineStop(ChlorinePump *pump) : pump_(pump) {}
|
||||||
|
|
||||||
|
void play(Ts... x) override { this->pump_->stop(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ChlorinePump *pump_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class ChlorineSetTarget : public Action<Ts...> {
|
||||||
|
public:
|
||||||
|
ChlorineSetTarget(ChlorinePump *pump) : pump_(pump) {}
|
||||||
|
TEMPLATABLE_VALUE(float, value)
|
||||||
|
|
||||||
|
void play(Ts... x) override {
|
||||||
|
this->pump_->set_target((int) this->value_.value(x...));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ChlorinePump *pump_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user