HELIOS PWM ESPHome

Steuerung für HELIOS KWL dezentrale Raumlüftung über einen ESPHOme
 avatar
unknown
plain_text
23 days ago
14 kB
10
No Index
esphome:
  name: heliospwm
  friendly_name: helios_pwm_control

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: arduino

wifi:
  ssid: "WLAN SSID"
  password: "WLAN PASSWORD"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "heliospwm"
    password: "12345678"
    
captive_portal:

web_server:
  local: true
  port: 80
  version: 3

ota:
  - platform: esphome
logger:
  level: INFO  # Auf INFO geändert für den Produktivbetrieb, DEBUG nur für Fehlersuche
  
api:

# Konstanten für häufig verwendete Werte
substitutions:
  pwm_frequency: "3200" #Frequenz in Herz
  pendel_interval: "45"  # Intervall in Sekunden für Dauer im Pendelmodus
  pendel_delay: "900" #Intervall in Millisekunden für Pause bei Richtungswechsel

# Output configurations for PWM signals
output:
  - platform: ledc
    pin: GPIO6 # Lüfter 1 - Wohnung
    frequency: ${pwm_frequency} Hz
    id: fan_pwm_1
    
  - platform: ledc
    pin: GPIO7 # Lüfter 2 - Wohnung
    frequency: ${pwm_frequency} Hz
    id: fan_pwm_2
    
  - platform: ledc
    pin: GPIO20 # Lüfter 3 - Trockenraum
    frequency: ${pwm_frequency} Hz
    id: fan_pwm_3
    
  - platform: ledc
    pin: GPIO21 # Lüfter 4 - Trockenraum
    frequency: ${pwm_frequency} Hz
    id: fan_pwm_4

# Input controls for the GUI
number:
  - platform: template
    name: "Fan Speed Wohnung [%]"
    id: fan_speed_wohnung
    min_value: 0
    max_value: 100
    step: 25  
    initial_value: 0  
    optimistic: true
    icon: "mdi:fan"  
    set_action:
      - lambda: |-
          ESP_LOGD("fan_speed_wohnung", "Fan Speed Wohnung set to: %.2f", x);
          
  - platform: template
    name: "Fan Speed Trockenraum [%]"
    id: fan_speed_trocken
    min_value: 0
    max_value: 100
    step: 25  
    initial_value: 0  
    optimistic: true
    icon: "mdi:fan"  
    set_action:
      - lambda: |-
          ESP_LOGD("fan_speed_trocken", "Fan Speed Trockenraum set to: %.2f", x);
          
  - platform: template
    name: "Obergrenze [%]"
    id: night_reduction
    min_value: 0
    max_value: 100
    step: 25  
    initial_value: 0  
    optimistic: true
    icon: "mdi:percent"  
    set_action:
      - lambda: |-
          ESP_LOGD("night_reduction", "Obergrenze set to: %.2f", x);

switch:
  - platform: template
    name: "Pendel Modus"
    id: pendel_mode
    optimistic: true
    icon: "mdi:swap-horizontal"  
    restore_mode: RESTORE_DEFAULT_ON
    turn_on_action:
      - lambda: |-
          ESP_LOGD("pendel_mode", "Pendel Mode turned ON");
    turn_off_action:
      - lambda: |-
          ESP_LOGD("pendel_mode", "Pendel Mode turned OFF");
          
  - platform: template
    name: "Abluft Modus"
    id: abluft_mode
    optimistic: true
    icon: "mdi:air-filter"  
    restore_mode: RESTORE_DEFAULT_OFF
    turn_on_action:
      - lambda: |-
          ESP_LOGD("abluft_mode", "Abluft Mode turned ON");
    turn_off_action:
      - lambda: |-
          ESP_LOGD("abluft_mode", "Abluft Mode turned OFF");

# Sensoren für aktuelle Lüftergeschwindigkeiten
sensor:
  - platform: template
    name: "Lüfter 1 Geschwindigkeit"
    id: fan1_speed_sensor
    unit_of_measurement: "%"
    icon: "mdi:gauge"
    accuracy_decimals: 1
    update_interval: 2s
    
  - platform: template
    name: "Lüfter 2 Geschwindigkeit"
    id: fan2_speed_sensor
    unit_of_measurement: "%"
    icon: "mdi:gauge"
    accuracy_decimals: 1
    update_interval: 2s
    
  - platform: template
    name: "Lüfter 3 Geschwindigkeit"
    id: fan3_speed_sensor
    unit_of_measurement: "%"
    icon: "mdi:gauge"
    accuracy_decimals: 1
    update_interval: 2s
    
  - platform: template
    name: "Lüfter 4 Geschwindigkeit"
    id: fan4_speed_sensor
    unit_of_measurement: "%"
    icon: "mdi:gauge"
    accuracy_decimals: 1
    update_interval: 2s

# Textsensoren für Lüftermodus
text_sensor:
  - platform: template
    name: "Lüfter 1 Modus"
    id: fan1_mode_sensor
    icon: "mdi:fan-direction-up"
    update_interval: 2s
  
  - platform: template
    name: "Lüfter 2 Modus"
    id: fan2_mode_sensor
    icon: "mdi:fan-direction-down"
    update_interval: 2s
  
  - platform: template
    name: "Lüfter 3 Modus"
    id: fan3_mode_sensor
    icon: "mdi:fan-direction-up"
    update_interval: 2s
  
  - platform: template
    name: "Lüfter 4 Modus"
    id: fan4_mode_sensor
    icon: "mdi:fan-direction-down"
    update_interval: 2s

# Globals für persistente Statusvariablen
globals:
  - id: reverse_state
    type: bool
    restore_value: false
    initial_value: 'false'
  - id: last_swap_time
    type: uint32_t
    restore_value: false
    initial_value: '0'
  # Letzte Lüftergeschwindigkeiten speichern
  - id: last_fan1_speed
    type: float
    restore_value: false
    initial_value: '50.0'
  - id: last_fan2_speed
    type: float
    restore_value: false
    initial_value: '50.0'
  - id: last_fan3_speed
    type: float
    restore_value: false
    initial_value: '50.0'
  - id: last_fan4_speed
    type: float
    restore_value: false
    initial_value: '50.0'
  # Hilfsvariablen für den Status des Richtungswechsels einzelner Lüfter
  - id: fan1_direction_change_time
    type: uint32_t
    restore_value: false
    initial_value: '0'
  - id: fan2_direction_change_time
    type: uint32_t
    restore_value: false
    initial_value: '0'
  - id: fan3_direction_change_time
    type: uint32_t
    restore_value: false
    initial_value: '0'
  - id: fan4_direction_change_time
    type: uint32_t
    restore_value: false
    initial_value: '0'

# Fan speed automation
interval:
  - interval: 1s
    then:
      - lambda: |-
          float speed_wohnung = id(fan_speed_wohnung).state;
          float speed_trocken = id(fan_speed_trocken).state;
          float reduction = id(night_reduction).state;
          bool pendel = id(pendel_mode).state;
          bool abluft = id(abluft_mode).state;
          bool &reverse = id(reverse_state);
          uint32_t now = millis();
          uint32_t &last_swap = id(last_swap_time);

          // Pendelmodus-Logik 
          if (pendel) {
            uint32_t now = millis();
            if (now - last_swap >= ${pendel_interval}000) {
              reverse = !reverse;
              last_swap = now;
              ESP_LOGD("pendel_mode", "Pendel Mode switched, new reverse state: %s", reverse ? "ON" : "OFF");
            }
          }
          
          // Effektive Geschwindigkeit mit Obergrenze
          float effective_speed_wohnung = (reduction > 0) ? std::min(speed_wohnung, reduction) : speed_wohnung;
          
          // Verbesserte Lüftergeschwindigkeitsberechnung mit besserer Lesbarkeit
          float fan1_speed, fan2_speed, fan3_speed, fan4_speed;
          
          //Begrenzung auf min 4 und maximal 96% std::max(4.9, std::min(96, ....))
          // Wohnraumlüfter
          if (abluft) {
            // beide Lüfter blasen Luft ein wenn andere Geräte im Haus Abluft ziehen
            fan1_speed = std::max(4.0, std::min(96.0, 50 + 0.5 * effective_speed_wohnung));
            fan2_speed = std::max(4.0, std::min(96.0, 50 + 0.5 * effective_speed_wohnung));
          } else {
            // Normaler Ab- und Zuluftmodus, ein Lüfter gibt Zuluft einer Abluft
            fan1_speed = std::max(4.0, std::min(96.0, 50 + (reverse ? -1 : 1) * effective_speed_wohnung * 0.5));
            fan2_speed = std::max(4.0, std::min(96.0, 50 + (reverse ? 1 : -1) * effective_speed_wohnung * 0.5));
          }
          
          // Trockenraumlüfter, ein Lüfter gibt Zuluft einer Abluft
          fan3_speed = std::max(4.0, std::min(96.0, 50 + (reverse ? -1 : 1) * speed_trocken * 0.5));
          fan4_speed = std::max(4.0, std::min(96.0, 50 + (reverse ? 1 : -1) * speed_trocken * 0.5));
          
          // Prüfen, ob individuelle Richtungswechsel für jeden Lüfter stattfinden
          // Für Lüfter 1
          if ((id(last_fan1_speed) < 50.0f && fan1_speed > 50.0f) || 
              (id(last_fan1_speed) > 50.0f && fan1_speed < 50.0f)) {
              id(fan1_direction_change_time) = now;
              ESP_LOGD("fan_control", "Fan 1 direction change detected - setting to 50% for ${pendel_delay}");
          }
          
          // Für Lüfter 2
          if ((id(last_fan2_speed) < 50.0f && fan2_speed > 50.0f) || 
              (id(last_fan2_speed) > 50.0f && fan2_speed < 50.0f)) {
              id(fan2_direction_change_time) = now;
              ESP_LOGD("fan_control", "Fan 2 direction change detected - setting to 50% for ${pendel_delay}");
          }
          
          // Für Lüfter 3
          if ((id(last_fan3_speed) < 50.0f && fan3_speed > 50.0f) || 
              (id(last_fan3_speed) > 50.0f && fan3_speed < 50.0f)) {
              id(fan3_direction_change_time) = now;
              ESP_LOGD("fan_control", "Fan 3 direction change detected - setting to 50% for ${pendel_delay}");
          }
          
          // Für Lüfter 4
          if ((id(last_fan4_speed) < 50.0f && fan4_speed > 50.0f) || 
              (id(last_fan4_speed) > 50.0f && fan4_speed < 50.0f)) {
              id(fan4_direction_change_time) = now;
              ESP_LOGD("fan_control", "Fan 4 direction change detected - setting to 50% for ${pendel_delay}");
          }
          
          // Prüfen, ob individuelle Lüfter sich noch in einer Pause nach Richtungswechsel befinden
          bool fan1_in_transition = (now - id(fan1_direction_change_time) < ${pendel_delay});
          bool fan2_in_transition = (now - id(fan2_direction_change_time) < ${pendel_delay});
          bool fan3_in_transition = (now - id(fan3_direction_change_time) < ${pendel_delay});
          bool fan4_in_transition = (now - id(fan4_direction_change_time) < ${pendel_delay});
          
          // Setzen der individuellen Lüftergeschwindigkeiten basierend auf Übergangsphase
          // Lüfter 1
          if (fan1_in_transition) {
              id(fan_pwm_1).set_level(0.50);
          } else {
              id(fan_pwm_1).set_level(fan1_speed / 100.0);
          }
          
          // Lüfter 2
          if (fan2_in_transition) {
              id(fan_pwm_2).set_level(0.50);
          } else {
              id(fan_pwm_2).set_level(fan2_speed / 100.0);
          }
          
          // Lüfter 3
          if (fan3_in_transition) {
              id(fan_pwm_3).set_level(0.50);
          } else {
              id(fan_pwm_3).set_level(fan3_speed / 100.0);
          }
          
          // Lüfter 4
          if (fan4_in_transition) {
              id(fan_pwm_4).set_level(0.50);
          } else {
              id(fan_pwm_4).set_level(fan4_speed / 100.0);
          }
          
          // Immer die letzten Geschwindigkeiten speichern
          id(last_fan1_speed) = fan1_speed;
          id(last_fan2_speed) = fan2_speed;
          id(last_fan3_speed) = fan3_speed;
          id(last_fan4_speed) = fan4_speed;
          
          // Angepasste Geschwindigkeiten für die Sensoren melden
          float display_fan1_speed = fan1_in_transition ? 50.0f : fan1_speed;
          float display_fan2_speed = fan2_in_transition ? 50.0f : fan2_speed;
          float display_fan3_speed = fan3_in_transition ? 50.0f : fan3_speed;
          float display_fan4_speed = fan4_in_transition ? 50.0f : fan4_speed;
          
          // Sensorwerte aktualisieren
          id(fan1_speed_sensor).publish_state(display_fan1_speed);
          id(fan2_speed_sensor).publish_state(display_fan2_speed);
          id(fan3_speed_sensor).publish_state(display_fan3_speed);
          id(fan4_speed_sensor).publish_state(display_fan4_speed);

          std::string fan1_mode, fan1_icon, fan2_mode, fan2_icon, fan3_mode, fan3_icon, fan4_mode, fan4_icon;

          // Modi-Bestimmung basierend auf den angezeigten Geschwindigkeiten
          if (display_fan1_speed < 50.0f) {
              fan1_mode = "Abluft";
              fan1_icon = "mdi:fan-direction-up";
          } else if (display_fan1_speed > 50.0f) {
              fan1_mode = "Zuluft";
              fan1_icon = "mdi:fan-direction-down";
          } else {
              fan1_mode = fan1_in_transition ? "Richtungswechsel" : "Aus";
              fan1_icon = "mdi:fan";
          }
          if (display_fan2_speed < 50.0f) {
              fan2_mode = "Abluft";
              fan2_icon = "mdi:fan-direction-up";
          } else if (display_fan2_speed > 50.0f) {
              fan2_mode = "Zuluft";
              fan2_icon = "mdi:fan-direction-down";
          } else {
              fan2_mode = fan2_in_transition ? "Richtungswechsel" : "Aus";
              fan2_icon = "mdi:fan";
          }
          if (display_fan3_speed < 50.0f) {
              fan3_mode = "Abluft";
              fan3_icon = "mdi:fan-direction-up";
          } else if (display_fan3_speed > 50.0f) {
              fan3_mode = "Zuluft";
              fan3_icon = "mdi:fan-direction-down";
          } else {
              fan3_mode = fan3_in_transition ? "Richtungswechsel" : "Aus";
              fan3_icon = "mdi:fan";
          }
          if (display_fan4_speed < 50.0f) {
              fan4_mode = "Abluft";
              fan4_icon = "mdi:fan-direction-up";
          } else if (display_fan4_speed > 50.0f) {
              fan4_mode = "Zuluft";
              fan4_icon = "mdi:fan-direction-down";
          } else {
              fan4_mode = fan4_in_transition ? "Richtungswechsel" : "Aus";
              fan4_icon = "mdi:fan";
          }
          
          // Lüftermodi setzen
          id(fan1_mode_sensor).publish_state(fan1_mode);
          id(fan2_mode_sensor).publish_state(fan2_mode);
          id(fan3_mode_sensor).publish_state(fan3_mode);
          id(fan4_mode_sensor).publish_state(fan4_mode);

          // Dynamisches Icon für jeden Lüfter basierend auf dem Modus
          id(fan1_mode_sensor).set_icon(fan1_icon.c_str());
          id(fan2_mode_sensor).set_icon(fan2_icon.c_str());
          id(fan3_mode_sensor).set_icon(fan3_icon.c_str());
          id(fan4_mode_sensor).set_icon(fan4_icon.c_str());
Editor is loading...
Leave a Comment