esphome-fan-controller icon indicating copy to clipboard operation
esphome-fan-controller copied to clipboard

Two Sensors

Open theblujuice opened this issue 1 year ago • 3 comments

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();'

theblujuice avatar Dec 31 '23 07:12 theblujuice

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

patrickcollins12 avatar Jan 05 '24 00:01 patrickcollins12

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).

nhinnenthal avatar May 09 '24 21:05 nhinnenthal

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.

patrickcollins12 avatar May 09 '24 23:05 patrickcollins12