Closed martijn-brant closed 2 years ago
glad it worked for you!
Well you could easily run two separate systems off the one esp32: two pids, two dht, two fans. You would just copy all of those sections in the yaml file and give each a different name.
However, to answer your question directly. Yes you can take the max of two sensors to create a 3rd ”template” sensor. All three sensors will be visible to home assistant.
I’m not at my computer at the moment, so I can’t provide direct code.
This example creates a 3rd template sensor which is an average.
https://community.home-assistant.io/t/average-temperature-based-on-multiple-sensors/220781/3
to create a max instead the lambda is something like:
lambda: |-
return max(id(dht_temp_1).state, id(dht_temp_2).state);
let me know how you go.
Ah yes, great idea just to duplicate the YAML values for the sensors/outputs. I added an additional GPIO for extra PWM (Fan 2) and extra DHT11. Works like a charm. This gives me dual-zone option on a single Nodemcu. Thanks for your code and your reply.
Ah yes, great idea just to duplicate the YAML values for the sensors/outputs. I added an additional GPIO for extra PWM (Fan 2) and extra DHT11. Works like a charm. This gives me dual-zone option on a single Nodemcu. Thanks for your code and your reply.
Hello,
Could you share you working yaml. I am about to start and may end up with 3 fans as they are a little small ( not ideal I know but got to work with what you got.)
Anyway if you could share how you did dual fans and dual dht temp that would be great
Ah yes, great idea just to duplicate the YAML values for the sensors/outputs. I added an additional GPIO for extra PWM (Fan 2) and extra DHT11. Works like a charm. This gives me dual-zone option on a single Nodemcu. Thanks for your code and your reply.
Hey! I would be also interested in the code supporting two zones :) Many thanks!
Ah sorry I missed your first message @B08Z .. @bartaspoz here is the code:
#based on https://github.com/patrickcollins12/esphome-fan-controller
substitutions:
friendly_name: Console Fan
esphome:
name: console-fan
esp32:
board: nodemcu-32s
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: "xxx"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Console-Fan Fallback Hotspot"
password: "xxx"
captive_portal:
globals:
- id: dhttemp
type: float
restore_value: yes
initial_value: '0'
number:
## RECEIVE kp,ki and kd parameters from input_text.kx helpers in
# Home Assistant. See the PID controller below
# These helper values will get saved to flash thus permanently over-riding
# the initial values set in the PID below.
# KP
- platform: template
name: $friendly_name kp
icon: mdi:chart-bell-curve
restore_value: true
min_value: 0
max_value: 50
step: 0.001
set_action:
lambda: |-
// ESP_LOGI("main", "!!!!!! kp from boot %d", id("console_fan_kp") );
// id(console_thermostat).set_kp( id("$friendly_name kp") );
id(console_thermostat).set_kp( x );
# KI
- platform: template
name: $friendly_name ki
icon: mdi:chart-bell-curve
restore_value: true
min_value: 0
max_value: 50
step: 0.0001
set_action:
lambda: id(console_thermostat).set_ki( x );
# KD
- platform: template
name: $friendly_name kd
icon: mdi:chart-bell-curve
restore_value: true
min_value: -50
max_value: 50
step: 0.001
set_action:
lambda: id(console_thermostat).set_kd( x );
# KP2
- platform: template
name: $friendly_name kp2
icon: mdi:chart-bell-curve
restore_value: true
min_value: 0
max_value: 50
step: 0.001
set_action:
lambda: |-
// ESP_LOGI("main", "!!!!!! kp from boot %d", id("console_fan_kp") );
// id(console_thermostat).set_kp( id("$friendly_name kp") );
id(console_thermostat2).set_kp( x );
# KI2
- platform: template
name: $friendly_name ki2
icon: mdi:chart-bell-curve
restore_value: true
min_value: 0
max_value: 50
step: 0.0001
set_action:
lambda: id(console_thermostat2).set_ki( x );
# KD2
- platform: template
name: $friendly_name kd2
icon: mdi:chart-bell-curve
restore_value: true
min_value: -50
max_value: 50
step: 0.001
set_action:
lambda: id(console_thermostat2).set_kd( x );
text_sensor:
# Send IP Address
- platform: wifi_info
ip_address:
name: $friendly_name IP Address
# Send Uptime in raw seconds
- platform: template
name: $friendly_name Uptime
id: uptime_human
icon: mdi:clock-start
sensor:
# Send WiFi signal strength & uptime to HA
- platform: wifi_signal
name: $friendly_name WiFi Strength
update_interval: 60s
# This is a bit of overkill. It sends a human readable
# uptime string
# 1h 41m 32s instead of 6092 seconds
- 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();
########################################################
# START THE FAN CONTROLLER SETUP
- 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 zero
id: zero_value
update_interval: 60s
lambda: |-
return 0;
- platform: template
name: $friendly_name zero percent
unit_of_measurement: "%"
id: zero_value_percent
update_interval: 60s
lambda: |-
return 0;
# GET TEMP/HUMIDITY FROM DHT11
- platform: dht
pin: GPIO21
temperature:
name: "Temperature"
id: console_fan_temperature
accuracy_decimals: 3
# If you don't smooth the output readings
# the PID controller over reacts to small changes.
filters:
# - sliding_window_moving_average:
# window_size: 6
# send_every: 1
# send_first_at: 1
- exponential_moving_average:
alpha: 0.1
send_every: 1
humidity:
name: "Humidity"
id: console_fan_humidity
# the DHT11 can only be read every 1s. Use 1.3s to be safe.
# Note that 15 x 1.3s means that the true temperature may
# take 19.5s to emerge
update_interval: 1.3s
- platform: dht
pin: GPIO22
temperature:
name: "Temperature 2"
id: console_fan_temperature2
accuracy_decimals: 3
# If you don't smooth the output readings
# the PID controller over reacts to small changes.
filters:
# - sliding_window_moving_average:
# window_size: 6
# send_every: 1
# send_first_at: 1
- exponential_moving_average:
alpha: 0.1
send_every: 1
humidity:
name: "Humidity 2"
id: console_fan_humidity2
# the DHT11 can only be read every 1s. Use 1.3s to be safe.
# Note that 15 x 1.3s means that the true temperature may
# take 19.5s to emerge
update_interval: 1.3s
# Take the "COOL" value of the pid and send
# it to the frontend to graph the output voltage
- platform: pid
name: "Fan Speed (PWM Voltage)"
climate_id: console_thermostat
type: COOL
- platform: pid
name: "Fan Speed 2 (PWM Voltage)"
climate_id: console_thermostat2
type: COOL
output:
# Wire this pin (15) into the PWM pin of your 12v fan
# ledc is the name of the pwm output system on an esp32
- platform: ledc
id: console_fan_speed
pin: GPIO02
# 25KHz is standard PC fan frequency, minimises buzzing
frequency: "25000 Hz"
# my fans stop working below 13% powerful.
# also they're powerful and loud, cap their max speed to 80%
min_power: 0%
max_power: 75%
- platform: ledc
id: console_fan_speed2
pin: GPIO04
# 25KHz is standard PC fan frequency, minimises buzzing
frequency: "25000 Hz"
# my fans stop working below 13% powerful.
# also they're powerful and loud, cap their max speed to 80%
min_power: 0%
max_power: 75%
# Good for debugging, you can manually set the fan speed.
fan:
- platform: speed
output: console_fan_speed
name: "Console Fan Speed"
- platform: speed
output: console_fan_speed2
name: "Console Fan Speed 2"
# Expose a PID-controlled Thermostat
# Manual: https://esphome.io/components/climate/pid.html
climate:
- platform: pid
name: "Console Fan Thermostat"
id: console_thermostat
sensor: console_fan_temperature
# It is summer right now, so 30c is a decent target.
default_target_temperature: 30°C
cool_output: console_fan_speed
on_state:
- sensor.template.publish:
id: p_term
state: !lambda 'return -id(console_thermostat).get_proportional_term() * 100.0;'
- sensor.template.publish:
id: i_term
state: !lambda 'return -id(console_thermostat).get_integral_term()* 100.0;'
- sensor.template.publish:
id: d_term
state: !lambda 'return -id(console_thermostat).get_derivative_term()* 100.0;'
- sensor.template.publish:
id: o_term
state: !lambda 'return -id(console_thermostat).get_output_value()* 100.0;'
- sensor.template.publish:
id: e_term
state: !lambda 'return -id(console_thermostat).get_error_value();'
# dummy heater. enable this if using autotune
# heat_output: console_heat_speed
# The extents of the HA Thermostat
visual:
min_temperature: 20 °C
max_temperature: 50 °C
# See the README for setting up these parameters.
# These are over ridden by the number templates above.
control_parameters:
kp: 0.15
ki: 0.004
kd: 0.5
max_integral: 0.0
- platform: pid
name: "Console Fan Thermostat 2"
id: console_thermostat2
sensor: console_fan_temperature2
# It is summer right now, so 30c is a decent target.
default_target_temperature: 30°C
cool_output: console_fan_speed2
on_state:
- sensor.template.publish:
id: p_term
state: !lambda 'return -id(console_thermostat2).get_proportional_term() * 100.0;'
- sensor.template.publish:
id: i_term
state: !lambda 'return -id(console_thermostat2).get_integral_term()* 100.0;'
- sensor.template.publish:
id: d_term
state: !lambda 'return -id(console_thermostat2).get_derivative_term()* 100.0;'
- sensor.template.publish:
id: o_term
state: !lambda 'return -id(console_thermostat2).get_output_value()* 100.0;'
- sensor.template.publish:
id: e_term
state: !lambda 'return -id(console_thermostat2).get_error_value();'
# dummy heater. enable this if using autotune
# heat_output: console_heat_speed
# The extents of the HA Thermostat
visual:
min_temperature: 20 °C
max_temperature: 50 °C
# See the README for setting up these parameters.
# These are over ridden by the number templates above.
control_parameters:
kp: 0.15
ki: 0.004
kd: 0.5
max_integral: 0.0
switch:
# Expose an ESP32 restart button to HA
- platform: restart
name: "Console Fan ESP32 Restart"
Hello,
i want to hijack this closed thread because i'm trying to do the same. The first step i've done was to copy the DHT sensor yaml-part, pasted it down below and changed the IDs and names.
But whatever i do the 2nd sensor is always "NA". No values. I've already tried different GPIO Inputs, used different sensors. Attached the working sensor to the 2nd GPIO and so much more.
What could be wrong? Instead of the DHT11 i'm using DHT22 sensors for my project.
sensor:
# GET TEMP/HUMIDITY FROM DHT22
- platform: dht
pin: GPIO18
model: DHT22
temperature:
name: "Temperature Unten"
id: console_fan_temperature_1
accuracy_decimals: 3
# If you don't smooth the temperature readings
# the PID controller over reacts to small changes.
filters:
- exponential_moving_average:
alpha: 0.1
send_every: 1
humidity:
name: "Humidity Unten"
id: console_fan_humidity_1
# the DHT11 can only be read every 1s. Use 1.3s to be safe.
update_interval: 1.3s
# GET TEMP/HUMIDITY FROM DHT22
- platform: dht
pin: GPIO23
model: DHT22
temperature:
name: "Temperature Oben"
id: console_fan_temperature_2
accuracy_decimals: 3
# If you don't smooth the temperature readings
# the PID controller over reacts to small changes.
filters:
- exponential_moving_average:
alpha: 0.1
send_every: 1
humidity:
name: "Humidity Oben"
id: console_fan_humidity_2
# the DHT11 can only be read every 1s. Use 1.3s to be safe.
update_interval: 1.3s
Log looks like this:
<html><body>
<!--StartFragment-->
22:57:34 | [W] | [component:204] | Component dht.sensor took a long time for an operation (0.06 s).
-- | -- | -- | --
22:57:34 | [W] | [component:205] | Components should block for at most 20-30ms.
22:57:35 | [W] | [dht:169] | Requesting data from DHT failed!
22:57:35 | [W] | [dht:060] | Invalid readings! Please check your wiring (pull-up resistor, pin number).
<!--EndFragment-->
</body>
</html>
But as already said, if i wire the 2nd sensor the the first GPIO it works on the first GPIO. I've also tried to add a 10kO resistor as pull-up on the data-out, don't know if needed for the DHT22, but its also not working with it.
Thanks for this repo.. the code and schematics work great for me. My prototype is working great however I have a question.. is it possible to add another DHT temperature probe? My AV cabinets have two zones and I've added a fan in each. One is for the AV Receiver (always on when using TV) and the other is for gaming consoles (only on sometimes). I'd rather not build two separate fan controllers for two compartments. I don't mind both sides spinning faster when only one zone is needing more cooling (e.g. the gaming side being cooled even if there are no consoles active).
I had to reassign the DHT to GPIO23 on my nodemcu-32s board else it wouldn't work. PWM is on GPIO15. I've looking at the code as to what would be needed to support a 2nd DHT but the code is a bit too advanced for me. Ideally it would report two temperature values to Home Assistant as well and act on the worst one. But I would be more than pleased to get the worst value of the two as well. (one being 29c and the other 35c.. having it act like it's 35c and adjust fan accordingly).
Could you help with this? Many thanks.