-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrack_fan_controller.yml
237 lines (208 loc) · 6.7 KB
/
rack_fan_controller.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
esphome:
name: rack_fan_controller
platform: esp32
board: lolin32
# Enable Wifi
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable MQTT
mqtt:
broker: !secret mqtt_broker
client_id: 'rack_fan_controller'
discovery: false
reboot_timeout: 10s
# Enable logging
logger:
# Enable OTA
ota:
dallas:
- pin: GPIO18
update_interval: 5s
# Hardware PWM output for controlling fan speed
# Frequency is fixed at 25 KHz, per Intel specifications
# All fans are controlled by a single PWM signal
# If you want to control each fan independantly, just add corresponding outputs
output:
- platform: ledc
pin: GPIO13
frequency: 25000 Hz
id: fan_output
sensor:
# Dallas temperature sensors declaration
- platform: dallas
address: 0xF48000001EA0AF28
name: "Temperature Base Rack"
id: temp_base_rack
accuracy_decimals: 1
- platform: dallas
address: 0x408000001E87D828
name: "Temperature Top Rack"
id: temp_top_rack
accuracy_decimals: 1
on_value:
then:
- script.execute: fan_regulation
# Tachometers declaration for each fan
# Useful to detect malfunctioning fans
- platform: pulse_counter
pin: GPIO12
name: "Front Left Fan Tachometer"
id: fan_fl_tacho
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
unit_of_measurement: "tr/min"
accuracy_decimals: 0
filters:
- multiply: 0.5
update_interval: 10s
- platform: pulse_counter
pin: GPIO14
name: "Front Middle Fan Tachometer"
id: fan_fm_tacho
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
unit_of_measurement: "tr/min"
accuracy_decimals: 0
filters:
- multiply: 0.5
update_interval: 10s
- platform: pulse_counter
pin: GPIO27
name: "Front Right Fan Tachometer"
id: fan_fr_tacho
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
unit_of_measurement: "tr/min"
accuracy_decimals: 0
filters:
- multiply: 0.5
update_interval: 10s
- platform: pulse_counter
pin: GPIO26
name: "Rear Left Fan Tachometer"
id: fan_rl_tacho
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
unit_of_measurement: "tr/min"
accuracy_decimals: 0
filters:
- multiply: 0.5
update_interval: 10s
- platform: pulse_counter
pin: GPIO25
name: "Rear Middle Fan Tachometer"
id: fan_rm_tacho
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
unit_of_measurement: "tr/min"
accuracy_decimals: 0
filters:
- multiply: 0.5
update_interval: 10s
- platform: pulse_counter
pin: GPIO33
name: "Rear Right Fan Tachometer"
id: fan_rr_tacho
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
unit_of_measurement: "tr/min"
accuracy_decimals: 0
filters:
- multiply: 0.5
update_interval: 10s
# Fan declaration with speed values
fan:
- platform: speed
output: fan_output
name: "Ventilation rack"
id: fan_speed
speed:
low: 0.35
medium: 0.5
high: 1
script:
- id: fan_regulation
then:
- lambda: |-
// Set the hysteresis margin
const float margin = 0.25;
// Set the number of fan speed levels
const int num_fan_speed_levels = 3;
// Set the values of fan speed levels
const esphome::fan::FanSpeed fan_speed_levels[num_fan_speed_levels] = { FAN_SPEED_LOW,
FAN_SPEED_MEDIUM,
FAN_SPEED_HIGH };
// Fan speed output level; retained for next calculation
static esphome::fan::FanSpeed fan_speed_output = FAN_SPEED_MEDIUM;
// Set the number of mean temperature ranges
const int num_temp_mean_ranges = 3;
// Set the values of mean temperature ranges
const float temp_mean_ranges[num_temp_mean_ranges] = { 0, 22, 26 };
// Last mean temperature range; retained for next calculation
static int last_temp_mean = 0;
// Current mean temperature of the rack
float current_temp_mean = ( id(temp_base_rack).state + id(temp_top_rack).state ) / 2;
// Current top temperature of the rack
float current_temp_top = id(temp_top_rack).state;
// Set lower and upper bounds for last mean temperature range
float mean_lb = temp_mean_ranges[last_temp_mean];
float mean_ub = 0;
if ( last_temp_mean > 0 ) {
mean_lb -= margin;
}
if ( last_temp_mean + 1 > num_temp_mean_ranges - 1 ) {
mean_ub = temp_mean_ranges[num_temp_mean_ranges - 1] + margin;
} else {
mean_ub = temp_mean_ranges[last_temp_mean + 1] + margin;
}
// Set lower bound for high temperature limit
float top_lb = 27 - margin;
// Boolean to help with high temperature mode
// High temperature mode is triggered when top temperature is > 27 °C, independently of
// mean temperature value
static bool temp_is_high = false;
// Start of regulation code
//
// First detect if we are in high temperature mode
// Then quit this mode if top temperature is < to lower bound
//
// If we're not in high temperature mode, trigger it if top temperature is > 27 °C
//
// If top temperature is < 27 °C, regulate fan speed with mean temperature :
//
// < 22 °C ==> FAN_SPEED_LOW
// 22 - 22 °C ==> FAN_SPEED_MEDIUM
// > 26 °C ==> FAN_SPEED_HIGH
if ( temp_is_high ) {
if ( current_temp_top < top_lb ) {
temp_is_high = false;
}
} else {
if ( current_temp_top >= 27 ) {
temp_is_high = true;
fan_speed_output = FAN_SPEED_HIGH;
}
if ( current_temp_mean < mean_lb || current_temp_mean > mean_ub ) {
if ( current_temp_mean > temp_mean_ranges[num_temp_mean_ranges - 1] ) {
fan_speed_output = FAN_SPEED_HIGH;
} else {
int i;
for ( i = 0; i < num_temp_mean_ranges; i++ ) {
if ( current_temp_mean >= temp_mean_ranges[i] && current_temp_mean < temp_mean_ranges[i + 1] ) {
break;
}
}
last_temp_mean = temp_mean_ranges[i];
fan_speed_output = fan_speed_levels[i];
}
}
}
// Set fan speed
id(fan_speed).turn_on().set_speed(fan_speed_output).perform();