Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two Sensors #27

Open
theblujuice opened this issue Dec 31, 2023 · 3 comments
Open

Two Sensors #27

theblujuice opened this issue Dec 31, 2023 · 3 comments

Comments

@theblujuice
Copy link

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();'
@patrickcollins12
Copy link
Owner

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:
#5

@nhinnenthal
Copy link

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

@patrickcollins12
Copy link
Owner

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants