esphome-fan-controller
esphome-fan-controller copied to clipboard
Two Sensors
Hey Patrick
I used yours as an example to build a fan temperature control for my network cabinet. Used a WT32-ETH01.
I was thinking of using two temperature sensors. One inside and another outside. Use the one outside + x °C as the set-point. Thus doesn't matter what the room temperature it will only be a few degrees more inside the cabinet. Any thoughts?
My config at the moment based on yours:
#https://github.com/patrickcollins12/esphome-fan-controller/blob/master/console-fan.yaml
substitutions: device_name: networkcabinet friendly_name: "Network Cabinet" device_ip: !secret networkcabinet_ip
###############################################################################
esphome: name: ${device_name} platform: ESP32 board: esp-wrover-kit
###############################################################################
preferences: flash_write_interval: 15min
###############################################################################
ethernet: type: LAN8720 mdc_pin: GPIO23 mdio_pin: GPIO18 clk_mode: GPIO0_IN phy_addr: 1 power_pin: GPIO16 manual_ip: static_ip: ${device_ip} gateway: !secret localgateway subnet: !secret localsubnet dns1: !secret localdns1 dns2: !secret localdns2
###############################################################################
Enable logging
logger:
###############################################################################
Enable Home Assistant API
api: encryption: key: !secret apikey ota: password: !secret otapass
###############################################################################
Time
time:
- platform: homeassistant id: esptime
###############################################################################
i2c: sda: 33 scl: 32 scan: true frequency: 800kHz
###############################################################################
text_sensor:
Send Uptime in raw seconds
- platform: template id: uptime_human icon: mdi:clock-start internal: true
###############################################################################
switch:
- platform: restart name: "${friendly_name} Reboot"
###############################################################################
sensor:
- platform: bme280 temperature: name: "${friendly_name} Amb Temp" id: bme280_temperature oversampling: 1x pressure: name: "${friendly_name} Amb Press" id: bme280_pressure humidity: name: "${friendly_name} Amb Hum" id: bme280_humidity address: 0x76 iir_filter: 16x update_interval: 5s
RPM Signal from Fan A
- platform: pulse_counter
pin:
number: 36
name: ${friendly_name} Fan A Speed
id: fan_a_pulse
unit_of_measurement: 'RPM'
filters:
- multiply: 0.5 count_mode: rising_edge: INCREMENT falling_edge: DISABLE update_interval: 5s accuracy_decimals: 0
RPM Signal from Fan B
- platform: pulse_counter
pin:
number: 39
name: ${friendly_name} Fan B Speed
id: fan_b_pulse
unit_of_measurement: 'RPM'
filters:
- multiply: 0.5 count_mode: rising_edge: INCREMENT falling_edge: DISABLE update_interval: 5s accuracy_decimals: 0
Uptime
-
platform: uptime name: $friendly_name Uptime id: uptime_sensor update_interval: 60s on_raw_value: then: - text_sensor.template.publish: id: uptime_human # Custom C++ code to generate the result
state: !lambda |- int seconds = round(id(uptime_sensor).raw_state); int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return (
(days ? to_string(days) + "d " : "") + (hours ? to_string(hours) + "h " : "") + (minutes ? to_string(minutes) + "m " : "") + (to_string(seconds) + "s") ).c_str(); -
platform: template name: $friendly_name p term id: p_term unit_of_measurement: "%" accuracy_decimals: 2
-
platform: template name: $friendly_name i term id: i_term unit_of_measurement: "%" accuracy_decimals: 2
-
platform: template name: $friendly_name d term id: d_term unit_of_measurement: "%" accuracy_decimals: 2
-
platform: template name: $friendly_name output value unit_of_measurement: "%" id: o_term accuracy_decimals: 2
-
platform: template name: $friendly_name error value id: e_term accuracy_decimals: 2
-
platform: template name: $friendly_name is in deadband id: in_deadband_term accuracy_decimals: 0
############################################################################### output:
- platform: ledc id: coolingfan pin: 15 frequency: 25000 Hz min_power: 0.2 max_power: 1.0
###############################################################################
number:
KP
- platform: template name: "${friendly_name} kp" icon: mdi:chart-bell-curve restore_value: true initial_value: 0.3 min_value: 0 max_value: 50 step: 0.001 set_action: lambda: |- id(${device_name}_pid).set_kp( x );
KI
- platform: template name: "${friendly_name} ki" icon: mdi:chart-bell-curve restore_value: true initial_value: 0.0015 min_value: 0 max_value: 50 step: 0.0001 set_action: lambda: id(${device_name}_pid).set_ki( x );
KD
- platform: template name: "${friendly_name} kd" icon: mdi:chart-bell-curve restore_value: true initial_value: 0.0 min_value: -50 max_value: 50 step: 0.001 set_action: lambda: id(${device_name}_pid).set_kd( x );
Set threshold low
- platform: template name: "${friendly_name} Deadband Threshold Low" icon: mdi:chart-bell-curve restore_value: true initial_value: -1.0 min_value: -20 max_value: 0 step: 0.1 set_action: lambda: id(${device_name}_pid).set_threshold_low( x );
Set threshold high
- platform: template name: "${friendly_name} Deadband Threshold High" icon: mdi:chart-bell-curve restore_value: true initial_value: 0.4 min_value: 0 max_value: 20 step: 0.1 set_action: lambda: id(${device_name}_pid).set_threshold_high( x );
Set ki multiplier
- platform: template name: "${friendly_name} Deadband ki Multiplier" icon: mdi:chart-bell-curve restore_value: true initial_value: 0.04 min_value: 0 max_value: .2 step: 0.01 set_action: lambda: id(${device_name}_pid).set_ki_multiplier( x );
###############################################################################
climate:
- platform: pid
id: ${device_name}_pid
name: "${friendly_name} Temp Controller"
visual:
min_temperature: 20.00 °C
max_temperature: 50.00 °C
temperature_step: 0.1 °C
sensor: bme280_temperature
default_target_temperature: 28.00 °C
cool_output: coolingfan
control_parameters:
kp: 0.3
ki: 0.0015
kd: 0.0
max_integral: 0.0
output_averaging_samples: 1
derivative_averaging_samples: 5
deadband_parameters: threshold_high: 0.4°C threshold_low: -1.0°C kp_multiplier: 0.0 ki_multiplier: 0.04 kd_multiplier: 0.0 deadband_output_averaging_samples: 15 on_state:- sensor.template.publish: id: p_term state: !lambda 'return -id(${device_name}_pid).get_proportional_term() * 100.0;'
- sensor.template.publish: id: i_term state: !lambda 'return -id(${device_name}_pid).get_integral_term()* 100.0;'
- sensor.template.publish: id: d_term state: !lambda 'return -id(${device_name}_pid).get_derivative_term()* 100.0;'
- sensor.template.publish: id: o_term state: !lambda 'return -id(${device_name}_pid).get_output_value()* 100.0;'
- sensor.template.publish: id: in_deadband_term state: !lambda 'return id(${device_name}_pid).in_deadband();'
- sensor.template.publish: id: e_term state: !lambda 'return -id(${device_name}_pid).get_error_value();'
Yep, totally possible, I like the idea. At the moment I set my temp at 30 in winter and 32 in summer. To some degree, you need to honor the max temp of your devices as well.
See this issue where I proposed how to get the average of two sensors, you could do something similar: https://github.com/patrickcollins12/esphome-fan-controller/issues/5
Hey, can you update if and how you got it working? I'm essentially trying to do the same thing. I have a chicken coop that i want to ventilate until the temperature and humidity values inside the coop match the values from outside (with a little tolerated difference).
You can dynamically adjust the pid target temperature to be the same as your external temperature sensor.
https://esphome.io/components/climate/#climate-control-action
Then set a dead band on your pidclimate of +/-2 degrees.
You can't control humidity with pidclimate, but you can measure it.