In de computerruimte is mechanische ventilatie gerealiseerd. Hiervan wordt de snelheid van een ventilator geregeld op basis van CO2 concentratie. Hieronder zie je de vierkante bak die oorspronkelijk al in de ruimte zat. Hierin is een bekisting gemaakt waarin een blower fan van een server in gemoteerd is geworden.
Documentatie bijwerken. Fotomateriaal toevoegen.
Serverventilator blower fan 230V 1fase
1-fase frequentieregelaar Mf-Net Frelink-4f overgenomen van Vostermans Ventilation
ESP32 WiFi kit 32
Relais module 5V (afbeelding ter illustratie)
Hall effect sensor type 3144 https://hackerstore.nl/Artikel/81
Meanwell 5V 2A schakelende voeding MW APV-12-5
TLC27L4BCN Quad opamp DIP14
Parameter | Waarde | Beschrijving |
co2_off | 600 | ppm | CO2 niveau voor uitschakelen van ventilatie |
co2_min | 650 | ppm | CO2 niveau voor minimale ventilatie en inschakelen van ventilatie |
co2_max | 1200 | ppm | CO2 niveau voor maximale ventilatie |
speed_min | 900 | rpm | Toerental bij minimale ventilatie |
speed_max | 2050 | rpm | Toerental bij maximale ventilatie |
Maximale toerental van de ventilator: 2568 rpm
PI regeling
Elke 1 seconde:
$error = rpm_{actual} - rpm_{setpoint}$
$P = 0.00001*(rpm_{setpoint})^2 + 0.0037*rpm_{setpoint} + 22.984$
$I = I -error*0.0002$
$Analog output = P+I$
Analog output wordt beperkt tussen 0 en 100.
Integrator stopt met integreren als het gemeten toerental binnen 25rpm van het toerentalsetpoint ligt.
Berekening van non-lineaire P factor in Excel:
Gemaakt voor de eerste test met een ESP32 (Wifi Kit 32) en de Frelink-4F frequentiereglaar.
De software van de ventilatieregeling is in ESPHome geconfigureerd en geschreven.
Kijk voor de laatste configuratie op ESPHome binnen TDvenlo: http://automation.ald-weishoes.lan:6052/
ESPHome configuratie (uitvouwen)
substitutions:
device_name: room1-ventilation
device_friendly_name: Room1 ventilation
api_pass: "5aTYYS5odajZ6BFMGBmVUgGOlwKYPxTxOR3B5V5tRNA="
ota_pass: "dda7b5d5ca5b1b0dbeb9028838e491bb"
packages:
base: !include packages/base.yaml
device: !include packages/nodemcu-esp32.yaml
esphome:
on_boot:
then:
- lambda: |-
id(rpm_setpoint).publish_state(0);
id(control_integrator).publish_state(0); // Reset integrator
id(status).publish_state("off");
output:
- platform: esp32_dac
pin: GPIO26
id: dac_output
- platform: gpio
pin: GPIO25
id: relay_output
#interval:
# - interval: 1000ms
# then:
# - output.turn_on: relay_output
# - delay: 500ms
# - output.turn_off: relay_output
sensor:
# Import value from operame
- platform: homeassistant
name: "CO2"
entity_id: sensor.operame
id: CO2
filters:
- sliding_window_moving_average:
window_size: 5
send_every: 1
on_value:
then:
- lambda: |-
ESP_LOGI("main", "New CO2 value %.1f", x);
auto co2_off = 550; //ppm
auto co2_min = 600; //ppm
auto co2_max = 1200; //ppm
auto speed_min = 900; //rpm
auto speed_max = 2050; //rpm
auto rpm_max = 2568; //rpm
auto speed_calc = map(x,co2_min,co2_max,speed_min,speed_max);
if(speed_calc<speed_min) speed_calc=speed_min;
if(speed_calc>speed_max) speed_calc=speed_max;
if(id(status).state == "on"){
//Fan is enabled
if(x<co2_off){
id(status).publish_state("standby");
}
}else if(id(status).state == "standby"){
//Fan is disabled
if(x>=co2_min){
id(control_integrator).publish_state(0); // Reset integrator
id(status).publish_state("on");
}
}
if(id(rpm_manual).state>0){
id(rpm_setpoint).publish_state(id(rpm_manual).state);
}else if(id(status).state == "on"){
//Fan is enabled
id(rpm_setpoint).publish_state(speed_calc);
id(relay_output).set_state(true);
}else{
//Fan is disabled
id(rpm_setpoint).publish_state(0);
id(relay_output).set_state(false);
}
#RPM sensor
- platform: pulse_counter
pin:
number: 2
mode:
input: true
pullup: true
id: "Room1fan_rpm"
name: "Room1fan RPM"
unit_of_measurement: "RPM"
accuracy_decimals: 1
update_interval: 1s
filters:
- calibrate_linear:
- 0.0 -> 0.0
- 1.0 -> 1.0
- sliding_window_moving_average:
window_size: 5
send_every: 1
on_value:
then:
- lambda: |-
float control_setpoint = id(control_rpm).state;
if(isnan(control_setpoint)) control_setpoint=0;
float setpoint = id(rpm_setpoint).state;
if(control_setpoint < setpoint){
control_setpoint +=10;
if(control_setpoint<500) control_setpoint=500;
if(control_setpoint > setpoint) control_setpoint = setpoint;
}else if(control_setpoint > setpoint){
control_setpoint -=10;
if(control_setpoint < setpoint) control_setpoint = setpoint;
}
float error = x- control_setpoint;
//float out = id(Output_value).state;
float integrator = id(control_integrator).state;
float base = 0.00001*control_setpoint*control_setpoint + 0.0037*control_setpoint + 22.984;
//if(isnan(out)) out = 0;
if(isnan(integrator)) integrator=0;
if(control_setpoint == setpoint || control_setpoint==0){
if(abs(error)>25){
integrator = integrator -error*0.0002;
if(integrator>50) integrator=50;
if(integrator<-50) integrator=-50;
}
}
float out = base + integrator;
if(out>100) out=100;
if(out< 0) out=0;
if(control_setpoint ==0){
out=0;
}
id(dac_output).set_level(out/100.0);
id(Output_value).publish_state(out);
id(control_base).publish_state(base);
id(control_integrator).publish_state(integrator);
id(control_rpm).publish_state(control_setpoint);
ESP_LOGI("main", "SpaceState:%.1f co2:%.1f status:%s",0, id(CO2).state ,id(status).state.c_str());
# output value dummy for publishing
- platform: template
id: "Output_value"
name: "Room1fan output"
unit_of_measurement: "%"
accuracy_decimals: 3
update_interval: 5s
- platform: template
id: "control_integrator"
name: "Room1fan control integrator"
unit_of_measurement: "%"
accuracy_decimals: 3
update_interval: 5s
- platform: template
id: "control_base"
name: "Room1fan control base"
unit_of_measurement: "%"
accuracy_decimals: 3
update_interval: 5s
- platform: template
id: "control_rpm"
name: "Room1fan control rpm"
unit_of_measurement: "rpm"
accuracy_decimals: 1
update_interval: 5s
- platform: template
id: "rpm_setpoint"
name: "Room1fan RPM setpoint"
unit_of_measurement: "RPM"
accuracy_decimals: 1
update_interval: 5s
text_sensor:
- platform: template
id: "status"
name: "Room1fan status"
update_interval: 5s
on_value:
then:
- lambda: |-
ESP_LOGI("main", "New state value %s", x.c_str());
number:
- platform: template
id: "rpm_manual"
name: "Room1fan rpm manual override"
unit_of_measurement: "RPM"
optimistic: true
min_value: 0
max_value: 2568
step: 1
on_value:
then:
- lambda: |-
id(rpm_setpoint).publish_state(id(rpm_manual).state);
switch:
- platform: template
name: "Room1fan on"
id: "on"
optimistic: True
restore_mode: RESTORE_DEFAULT_OFF
turn_on_action:
- lambda: |-
if(id(status).state =="off") id(status).publish_state("standby");
turn_off_action:
- lambda: |-
id(status).publish_state("off");
id(rpm_setpoint).publish_state(0);
id(relay_output).set_state(false);
Het aansluitcompartiment van de frequentiereglaar is groter gemaakt om een 5V voeding in te kunnen bouwen voor de ESP32. Hiervoor is een tussenzetstuk ontworpen die op de originele plek van de deksel gemonteerd is. Daarbovenop is dan de originele deksel gemonteerd.
3D model: frelink_extensie.amf