Welcome to esphome-fan-controller Discussions! #39
patrickcollins12
announced in
Announcements
Replies: 2 comments 6 replies
-
Your are a legend! I used this system to extract hot air from the top of a rack server. 2 Arctic fans at 30% help to keep the temp inside a 24° C. |
Beta Was this translation helpful? Give feedback.
2 replies
-
Thanks for your code as a start. The only thing I will still upgrade is an additional temperature probe outside the cabinet and use an offset of that temperature as the target temperature for a more dynamic control. #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}
esp32:
board: esp-wrover-kit
framework:
version: recommended
###############################################################################
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:
- platform: esphome
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_i2c
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
# RPM Signal from Fan C
- platform: pulse_counter
pin:
number: 14
name: ${friendly_name} Fan C Speed
id: fan_c_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 D
- platform: pulse_counter
pin:
number: 12
name: ${friendly_name} Fan D Speed
id: fan_d_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();'
|
Beta Was this translation helpful? Give feedback.
4 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
👋 Welcome!
We’re using Discussions as a place to connect with other members of our community. We hope that you:
build together 💪.
To get started, comment below with an introduction of yourself, what you want to do with this project, any questions you have. Hopefully you will also share photos of your fan so we I can show it off!
Beta Was this translation helpful? Give feedback.
All reactions