Custom component - Dimmer 4ch I2c

Witam.

Prosze mi wybaczyc, jestem raczej nowy i mam problem z custom_component.
Kupilem 4 kanalowy sciemniacz na i2c.
Od producenta dostalem plik z przykladem uzycia custom component.
Wszystko dzialalo dopoki nie zaktualozowalem home assistant i esphome.

zmienilem lokalozacje pliku i dodalem:

external_components:

  • source:
    type: local
    path: my_components

do regulacji obotow wentylatora uzywalem:

dimmer
output:

  • platform: custom
    type: float
    lambda: |-
    auto my_custom_float_output = new MyCustomFloatOutput();
    App.register_component(my_custom_float_output);
    my_custom_float_output->channel = 3;
    return {my_custom_float_output};
    outputs:
    id: ch_1

Jednak w tym miejscu wywala blad nie nie wiem jak to zmodyfikowac aby znowu dzialalo.

fan:

  • platform: speed
    output: ch_1
    name: “4ch 1”
    id: fan1

do zmiany wartosci uzywam w kodzie lambda

id(fan1).turn_on().set_speed(id(fan1_mem)).perform();

2 dni kombinuje i nie wiem jak to ugrysc

link do sciemniacza

Jak prawidłowo zamieszczać YAML, inny kod lub logi w postach na forum

bez konkretów co dostałeś (zamieść pliki spakowane do zip) w ogóle nie ma dalszej rozmowy

Za bardzo nabierasz wody w usta, ale chyba chodzi o urządzenie ESPHome, a nie o HA…

Co producent na to? kontaktowałeś się z nim? ma jakieś repozytorium?

plik od producenta wyglada tak:

typ#include "esphome.h"
using namespace esphome;

class MyCustomFloatOutput : public Component, public FloatOutput {
  public:

    int i2c_addr;
    const int ch_addr[4] = {128, 129, 130, 131}; //AC dimmer channels
    int channel; // from 0 to -3
    int error;
    bool debug;

  void setup() override {

    debug = 0; // set debug off/on
    i2c_addr = 39; // set i2c address

    Wire.begin();
    Wire.beginTransmission(i2c_addr);
    for (int i = 0; i < 4; i++){ // loop through all channels
        Wire.write( ch_addr[i] );
        Wire.write(100); //off
    }
    error = Wire.endTransmission();
    if (debug == 1){log_err(error);} //debug

  }

  void write_state(float state) override {   // state is the amount this output should be on, from 0.0 to 1.0
    
    int value = state * 1024; // convert it to an integer first
    value = map(value, 0, 1024, 100, 0); //convert to 0-100%
  
    Wire.beginTransmission(i2c_addr);
    Wire.write( ch_addr[channel] );
    Wire.write(value);
    Wire.endTransmission();
    error = Wire.endTransmission();
    if (debug == 1){log_err(error);}
  }

    void log_err(int error){
    if (error==0){ ESP_LOGD ("custom", "I2C Transmissio: success");} // 0: success.
    else if (error==1){ ESP_LOGD ("custom", "I2C Transmissio: data too long to fit in transmit buffer");} // 1: data too long to fit in transmit buffer.
    else if (error==2){ ESP_LOGD("custom", "I2C Transmissio: received NACK on transmit of address");} // 2: received NACK on transmit of address.
    else if (error==3){ ESP_LOGD("custom", "I2C Transmissio: received NACK on transmit of data");} // 3: received NACK on transmit of data.
    else if (error==4){ ESP_LOGD("custom", "I2C Transmissio: other error");} // 4: other error.
    else if (error==5){ ESP_LOGD("custom", "I2C Transmissio: timeout");} // 5: timeout
    }

};

moj program sluzy do obslugi wentylacji a to kod :slight_smile:


# zmienne globalne
globals:
  - id: home_temp_target
    type: float
    restore_value: no
    initial_value: '26.0'
  - id: temp_target
    type: float
    restore_value: no
    initial_value: '0'
  - id: humidity_target
    type: float
    restore_value: no
    initial_value: '65'
  - id: mode_temp
    type: int
    restore_value: no
    initial_value: '0'
  - id: mode_mem
    type: int
    restore_value: no
    initial_value: '0'
  - id: mode_set
    type: int
    restore_value: no
    initial_value: '0'
  - id: mode_set_mem
    type: int
    restore_value: no
    initial_value: '0'
  - id: hp_mem
    type: int
    restore_value: no
    initial_value: '0'
  - id: hp_timer
    type: int
    restore_value: no
    initial_value: '0'
  - id: hold
    type: int
    restore_value: no
    initial_value: '0'
  - id: timer
    type: int
    restore_value: no
    initial_value: '0'
  - id: valvetime
    type: int
    restore_value: no
    initial_value: '180'
  - id: fan1_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan_min_speed
    type: int
    restore_value: no
    initial_value: '10'
  - id: fan1_mem
    type: int
    restore_value: no
    initial_value: '-1'
  - id: fan2_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan2_mem
    type: int
    restore_value: no
    initial_value: '-1'
  - id: fan3_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan3_mem
    type: int
    restore_value: no
    initial_value: '-1'
  - id: fan4_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan4_mem
    type: int
    restore_value: no
    initial_value: '-1'

esphome:
  name: ventilation
  

external_components:
  - source: 
      type: local
      path: my_components
    
esp32:
  board: wt32-eth01
  framework:
    type: arduino

# Enable logging
logger:

ota:
  - platform: esphome
    password: "******"

ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 1
  power_pin: GPIO16

web_server:
  port: 80
  
mqtt:
  broker: !secret mqtt_broker
  port: 1883
  username: !secret mqtt_username
  password: !secret mqtt_password

i2c:
  sda: GPIO2
  scl: GPIO4
  scan: True 

pcf8574:
- id: 'pcb1'
  address: 0x26

time:
  - platform: sntp
    id: sntp_time

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO36
      mode:
        input: true
      inverted: true
    filters:
      - delayed_on: 250ms
      - delayed_off: 250ms
    name: "Heat Pump Switch"
    id: hp_switch
    icon: mdi:heat-pump-outline
    
  - platform: gpio
    pin:
      number: GPIO39
      mode:
        input: true
      inverted: true
    filters:
      - delayed_on: 1000ms
      - delayed_off: 1000ms
    name: "Air Filter Switch"
    id: airfilterswitch
    icon: mdi:air-filter

#czujniki temperatur
sensor:
  - platform: template
    name: "Target Temperature"
    icon: mdi:home-thermometer-outline
    update_interval: 60s
    unit_of_measurement: "°C"
    device_class: "temperature"
    state_class: "measurement"
    accuracy_decimals: 1
    lambda: 'return id(temp_target);'

  - platform: dht
    pin: GPIO15
    model: DHT22
    temperature:
      name: "Outdoor Temperature"
      id: temp_outdoor
      filters:
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: "Outdoor Humidity"
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: dht
    pin: GPIO33
    model: DHT22
    temperature:
      name: "Home Temperature"
      id: temp_home
      filters:
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: "Home Humidity"
      id: humidity
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: dht
    pin: GPIO14
    model: DHT22
    temperature:
      name: "Supply Temperature"
      id: temp_supply
      filters:
       - calibrate_linear:
          - 0.0 -> 0.0
          - 27.5 -> 25.5
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: "Supply Humidity"
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: dht
    pin: GPIO32
    model: DHT22
    temperature:
      name: "Exhaust Temperature"
      id: temp_exhaust
      filters:
       - calibrate_linear:
          - 0.0 -> 0.0
          - 27.5 -> 25.5
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: "Exhaust Humidity"
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: template
    id: time_minutes
    lambda: |-
      auto time = id(sntp_time).now();
      return time.hour * 60 + time.minute;

# przekaźniki
switch:
- platform: restart
  name: "Ventilation REBOOT"
  id: restart_pcb

- platform: gpio
  name: "Valve 1"
  id: valve1
  icon: mdi:valve
  pin:
   pcf8574: pcb1
   number: 7
   mode: OUTPUT
   inverted: True
        
- platform: gpio
  name: "Valve 2"
  id: valve2
  icon: mdi:valve
  pin:
   pcf8574: pcb1
   number: 6
   mode: OUTPUT
   inverted: True   
  
- platform: gpio
  name: "Valve 3"
  id: valve3
  icon: mdi:valve
  pin:
   pcf8574: pcb1
   number: 5
   mode: OUTPUT
   inverted: True
           
- platform: gpio
  name: "Valve 4"
  id: valve4
  icon: mdi:valve
  pin:
   pcf8574: pcb1
   number: 4
   mode: OUTPUT
   inverted: True   
          
- platform: gpio
  name: "Valve Supply"
  id: valvesupply
  icon: mdi:lightning-bolt-outline
  pin:
   pcf8574: pcb1
   number: 3
   mode: OUTPUT
   inverted: True   

- platform: gpio
  name: "Valve 5"
  id: valve5
  icon: mdi:valve
  pin:
   pcf8574: pcb1
   number: 2
   mode: OUTPUT
   inverted: True   

- platform: gpio
  name: "Ionizer"
  icon: mdi:air-filter
  id: ionizer
  pin:
   pcf8574: pcb1
   number: 1
   mode: OUTPUT
   inverted: True  

- platform: gpio
  name: "Dirty Filter"
  id: dirtyfilter
  icon: mdi:air-filter
  pin:
   pcf8574: pcb1
   number: 0
   mode: OUTPUT
   inverted: True

#dimmer
output:
- platform: custom
  type: float
  lambda: |-
    auto my_custom_float_output = new MyCustomFloatOutput();
    App.register_component(my_custom_float_output);
    my_custom_float_output->channel = 3;
    return {my_custom_float_output};
  outputs:
    id: ch_1

- platform: custom
  type: float
  lambda: |-
    auto my_custom_float_output = new MyCustomFloatOutput();
    App.register_component(my_custom_float_output);
    my_custom_float_output->channel = 2;
    return {my_custom_float_output};
  outputs:
    id: ch_2

- platform: custom
  type: float
  lambda: |-
    auto my_custom_float_output = new MyCustomFloatOutput();
    App.register_component(my_custom_float_output);
    my_custom_float_output->channel = 1;
    return {my_custom_float_output};
  outputs:
    id: ch_3
    
- platform: custom
  type: float
  lambda: |-
    auto my_custom_float_output = new MyCustomFloatOutput();
    App.register_component(my_custom_float_output);
    my_custom_float_output->channel = 0;
    return {my_custom_float_output};
  outputs:
    id: ch_4
    
fan:
  - platform: speed
    output: ch_1
    name: "4ch 1"
    id: fan1
    
  - platform: speed
    output: ch_2
    name: "4ch 2"
    id: fan2
    
  - platform: speed
    output: ch_3
    name: "4ch 3"
    id: fan3
    
  - platform: speed
    output: ch_4
    name: "4ch 4"  
    id: fan4

text_sensor:
  - platform: template
    name: "Ventilation Mode"
    icon: mdi:air-filter
    id: mode
    update_interval: 1s
    
# automatyzacja wykonywana cyklicznie
interval:
  - interval: 1s
    then:
      # zasilanie zaworów jeśli nastąpi zmiana trybu
      - lambda: |-
          if (id(mode_set) != id(mode_set_mem) ) {
            if ( id(mode_set_mem) == 0 ) { id(hold) = 2; }
            id(mode_set_mem)=id(mode_set);
            id(timer) = id(valvetime);
            id(valvesupply).turn_on();
            }

          if ( id(valvesupply).state ) {
            if (id(timer) > 0) { 
              id(timer) = id(timer) - 1 ;
              }else{
              id(valvesupply).turn_off();
              }
            }else{
            if ( id(valve1).state ) { id(valve1).turn_off(); }
            if ( id(valve2).state ) { id(valve2).turn_off(); }
            if ( id(valve3).state ) { id(valve3).turn_off(); }
            if ( id(valve4).state ) { id(valve4).turn_off(); }
            if ( id(valve5).state ) { id(valve5).turn_off(); }
            }

  - interval: 1s
    then: 
      # zmiana szybkości wentylatorów
      - lambda: |-
          if (id(fan1_speed) > id(fan1_mem) ) {
            if (id(fan1_speed) < id(fan_min_speed) ) { 
               id(fan1_mem)=0;
               id(fan1_speed)=0;
               id(fan1).turn_off().perform(); 
               }
            if (id(fan1_speed) >= id(fan_min_speed) ) {
               id(fan1_mem)=id(fan1_mem)+1;
               if (id(fan1_mem) < id(fan_min_speed) ) { id(fan1_mem)=id(fan_min_speed); }
               id(fan1).turn_on().set_speed(id(fan1_mem)).perform();
               }
            }
          if (id(fan1_speed) < id(fan1_mem) ) {
            if (id(fan1_speed) < id(fan_min_speed) ) { 
               id(fan1_mem)=0;
               id(fan1_speed)=0;
               id(fan1).turn_off().perform(); 
               }
            if (id(fan1_speed) >= id(fan_min_speed) ) {
               id(fan1_mem)=id(fan1_mem)-1;
               id(fan1).turn_on().set_speed(id(fan1_mem)).perform();
               }
            }
          
          if (id(fan2_speed) > id(fan2_mem) ) {
            if (id(fan2_speed) < id(fan_min_speed) ) { 
               id(fan2_mem)=0;
               id(fan2_speed)=0;
               id(fan2).turn_off().perform(); 
               }
            if (id(fan2_speed) >= id(fan_min_speed) ) {
               id(fan2_mem)=id(fan2_mem)+1;
               if (id(fan2_mem) < id(fan_min_speed) ) { id(fan2_mem)=id(fan_min_speed); }
               id(fan2).turn_on().set_speed(id(fan2_mem)).perform();
               }
            }
          if (id(fan2_speed) < id(fan2_mem) ) {
            if (id(fan2_speed) < id(fan_min_speed) ) { 
               id(fan2_mem)=0;
               id(fan2_speed)=0;
               id(fan2).turn_off().perform(); 
               }
            if (id(fan2_speed) >= id(fan_min_speed) ) {
               id(fan2_mem)=id(fan2_mem)-1;
               id(fan2).turn_on().set_speed(id(fan2_mem)).perform();
               }
            }
          
          if (id(fan3_speed) > id(fan3_mem) ) {
            if (id(fan3_speed) < id(fan_min_speed) ) { 
               id(fan3_mem)=0;
               id(fan3_speed)=0;
               id(fan3).turn_off().perform(); 
               }
            if (id(fan3_speed) >= id(fan_min_speed) ) {
               id(fan3_mem)=id(fan3_mem)+1;
               if (id(fan3_mem) < id(fan_min_speed) ) { id(fan3_mem)=id(fan_min_speed); }
               id(fan3).turn_on().set_speed(id(fan3_mem)).perform();
               }
            }
          if (id(fan3_speed) < id(fan3_mem) ) {
            if (id(fan3_speed) < id(fan_min_speed) ) { 
               id(fan3_mem)=0;
               id(fan3_speed)=0;
               id(fan3).turn_off().perform(); 
               }
            if (id(fan3_speed) >= id(fan_min_speed) ) {
               id(fan3_mem)=id(fan3_mem)-1;
               id(fan3).turn_on().set_speed(id(fan3_mem)).perform();
               }
            }
          
          if (id(fan4_speed) > id(fan4_mem) ) {
            if (id(fan4_speed) < id(fan_min_speed) ) { 
               id(fan4_mem)=0;
               id(fan4_speed)=0;
               id(fan4).turn_off().perform(); 
               }
            if (id(fan4_speed) >= id(fan_min_speed) ) {
               id(fan4_mem)=id(fan4_mem)+1;
               if (id(fan4_mem) < id(fan_min_speed) ) { id(fan4_mem)=id(fan_min_speed); }
               id(fan4).turn_on().set_speed(id(fan4_mem)).perform();
               }
            }
          if (id(fan4_speed) < id(fan4_mem) ) {
            if (id(fan4_speed) < id(fan_min_speed) ) { 
               id(fan4_mem)=0;
               id(fan4_speed)=0;
               id(fan4).turn_off().perform(); 
               }
            if (id(fan4_speed) >= id(fan_min_speed) ) {
               id(fan4_mem)=id(fan4_mem)-1;
               id(fan4).turn_on().set_speed(id(fan4_mem)).perform();
               }
            }

  - interval: 1s
    then:
      # Reset timera po włączeniu pompy ciepła
      - lambda: |-
          if (id(hp_switch).state ) {
            if ( id(hp_timer) == 0 ) { id(hold) = 0; }
            id(hp_timer) = 300;
            }

  - interval: 10s
    then:
      # kontrolka brudnego filtra
      - lambda: |-
          if (id(airfilterswitch).state ) {
            id(dirtyfilter).turn_on();
            }

      # Jonizator
      - lambda: |-
          if (id(fan1).state ) {
            if (id(ionizer).state) {
               }else{
               id(ionizer).turn_on();
               } 
            }else{
            if (id(ionizer).state) {
               id(ionizer).turn_off();
               } 
            }

  - interval: 60s
    then:
      # Ustalenie temperatury docelowej i trybu pracy
      
      - lambda: |-
          if (id(time_minutes).state > 480 && id(time_minutes).state < 1380 ) {
            id(temp_target)=id(home_temp_target);
            }else{
            id(temp_target)=id(home_temp_target) - 1;
            }
          if (id(mode_set) == 3) { id(temp_target)=id(home_temp_target) - 2; }

          id(mode_temp) = 1; 
          if (id(temp_home).state < id(temp_target) && id(temp_outdoor).state > id(temp_home).state + 3) {id(mode_temp) = 6;}
          if (id(temp_home).state > id(temp_target) && id(temp_outdoor).state < id(temp_home).state - 3) {id(mode_temp) = 6;}
          if (id(temp_home).state > id(temp_target) + 0.5 && id(temp_outdoor).state < id(temp_home).state - 3) {id(mode_temp) = 8;}
          if (id(temp_home).state > id(temp_target) + 1 && id(temp_outdoor).state < id(temp_home).state - 3) {id(mode_temp) = 9;}

          if (id(hp_timer) > 0) {
            id(mode_temp) = 3;
            if (id(temp_home).state > id(temp_target)) {id(mode_temp) = 4;}
            if (id(temp_home).state > id(temp_target) &&  id(temp_outdoor).state < id(temp_home).state -10) {id(mode_temp) = 5;}
            }

          if (id(humidity).state > id(humidity_target)) {
             if (id(mode_temp) == 1) {id(mode_temp) = 1;}
             if (id(mode_temp) == 6) {id(mode_temp) = 7;}
             if (id(mode_temp) == 8) {id(mode_temp) = 9;}
             if (id(mode_temp) == 3) {id(mode_temp) = 3;}
             }

          if (id(mode_temp) == 1 && id(temp_outdoor).state < 5) {id(mode_temp) = 11;}

      # Opóźnienie zmiany trybu pracy
      - lambda: |-
          if (id(mode_temp) == id(mode_mem)) {
             id(hold) = 15;
             }else{
             id(hold) = id(hold) - 1;
             }

          if (id(hp_timer) > 0) {
             if (id(hp_mem) == 0) {
                id(hp_mem) = 1;
                id(hold) = 0;
                }
             }else{
             if (id(hp_mem) == 1) {
                id(hp_mem) = 0;
                id(hold) = 0;
                } 
             }
 
      # Zmiana trybu pracy
      - lambda: |-  
          if (id(mode_temp) != id(mode_mem) && id(hold) < 1) {
            id(mode_mem) = id(mode_temp);
            id(hold) = 15;

            switch (id(mode_temp)) {
            
              case 1:  
               id(mode).publish_state("Heat Recovery - Eco");
               id(mode_set)=1;
               id(fan1_speed)=25;
               id(fan2_speed)=25;
               id(fan3_speed)=0;
               id(fan4_speed)=0;
               break;

              case 2:  
               id(mode).publish_state("Heat Recovery - Max");
               id(mode_set)=1;
               id(fan1_speed)=100;
               id(fan2_speed)=100;
               id(fan3_speed)=0;
               id(fan4_speed)=0;
               break;

              case 3:
               id(mode).publish_state("Heat Pump & Recovery - Eco");
               id(mode_set)=2;
               id(fan1_speed)=25;
               id(fan2_speed)=15;
               id(fan3_speed)=0;
               id(fan4_speed)=0;
               break;

              case 4:
               id(mode).publish_state("Heat Pump - Cooling");
               id(mode_set)=3;
               id(fan1_speed)=100;
               id(fan2_speed)=0;
               id(fan3_speed)=0;
               id(fan4_speed)=0;
               break;

              case 5:
               id(mode).publish_state("Heat Pump - By-pass");
               id(mode_set)=4;
               id(fan1_speed)=100;
               id(fan2_speed)=0;
               id(fan3_speed)=0;
               id(fan4_speed)=0;
               break;

              case 6:
               id(mode).publish_state("By-pass - Eco");
               id(mode_set)=4;
               id(fan1_speed)=40;
               id(fan2_speed)=0;
               id(fan3_speed)=25;
               id(fan4_speed)=0;
               break;

              case 7:
               id(mode).publish_state("By-pass - Max");
               id(mode_set)=4;
               id(fan1_speed)=100;
               id(fan2_speed)=0;
               id(fan3_speed)=50;
               id(fan4_speed)=0;
               break;

              case 8:
               id(mode).publish_state("Cooling By-pass");
               id(mode_set)=4;
               id(fan1_speed)=75;
               id(fan2_speed)=0;
               id(fan3_speed)=30;
               id(fan4_speed)=0;
               break;

              case 9:
               id(mode).publish_state("Cooling By-pass - Max");
               id(mode_set)=4;
               id(fan1_speed)=100;
               id(fan2_speed)=0;
               id(fan3_speed)=35;
               id(fan4_speed)=0;
               break;
            
              case 10:
               id(mode).publish_state("Heat Pump & Recovery - Max");
               id(mode_set)=2;
               id(fan1_speed)=100;
               id(fan2_speed)=75;
               id(fan3_speed)=0;
               id(fan4_speed)=0;
               break;

              case 11:  
               id(mode).publish_state("Heat Recovery - Eco Max");
               id(mode_set)=1;
               id(fan1_speed)=20;
               id(fan2_speed)=20;
               id(fan3_speed)=0;
               id(fan4_speed)=0;
               break;
              }

            switch (id(mode_set)) {
              case 1:  
               id(valve1).turn_off();
               id(valve2).turn_off();
               id(valve3).turn_off();
               id(valve4).turn_off();
               id(valve5).turn_off();
               break;

              case 2:  
               id(valve1).turn_off();
               id(valve2).turn_on();
               id(valve3).turn_off();
               id(valve4).turn_on();
               id(valve5).turn_on();
               break;

              case 3:  
               id(valve1).turn_on();
               id(valve2).turn_off();
               id(valve3).turn_on();
               id(valve4).turn_off();
               id(valve5).turn_off();
               break;

              case 4:  
               id(valve1).turn_on();
               id(valve2).turn_off();
               id(valve3).turn_off();
               id(valve4).turn_on();
               id(valve5).turn_off();
               break;
              }
            
            }

  - interval: 1s
    then:
      # timer wyłączenia pompy ciepła
      - lambda: |-
         if ( id(hp_switch).state) { id(hp_timer) = 300; }
         if ( id(hp_timer) == 1 ) { id(hold) = 0; }
         if ( id(hp_timer) > 0 ) { id(hp_timer) = id(hp_timer) - 1; }

zatrzymuje sie w miejscu dimmer z komunikatem

The “custom” component has been removed. Consider conversion to an external component.
Code - ESPHome Developer Documentation.

Świetnie, a pozostałe odpowiedzi?

Bo jak na razie to jedyne co mogę zasugerować to kompilowanie w odpowiednio starej wersji ESPHome

Mam skompilowane w starej wersji i wszystko dziala ale chcialbym skompilowac w nowej, zeby np dodac nowe funkcje jak np wybor temperatury. W tym kodzie jest przypisana na stale. Latem ustawialem 22 stopnie i przekompilowywalem, a zima na 26 zeby nie wlaczala schladzania w nocy. Jak to kiedys pisalem to nie znalem number: i select:
Na stronie producenta nie ma.nic, kiedys mi przyslal w/w plik. Plytka kupiona na ebuy-u.

Dostalem tylko ten plik oraz przyklad jak go wykozystac. To bylo dawno, nie znajde. Na podstawie tego przykladu zrobilem ta czesc odnaczona dimmer i tylko ona jest dla mnie teraz problemem

rozwiązanie 1
To dobierz taką wersję, aby była możliwie najświeższa i nadal działała.

rozwiązanie 2
Skontaktuj się ze sprzedawcą i
a) otrzymaj od niego zaktualizowany niestandardowy komponent dla ESPHome (najlepiej dostosowany do współpracy z ESP-IDF)
lub
b) spytaj czy raczy otworzyć publiczne repozytorium ze swoim komponentem

rozwiązanie 3
być może to jednak już istnieje, więc poszukaj samodzielnie rozwiązania z punktu 2 b)

Ktoś już zaczął dopisywać obsługę tego sprzętu do ESPHome, ale nie dokończył. Kod wydaje się był gotowy:

1 polubienie

Przyjze sie temu jutro, dziekuje za wskazowki.
Znalazlem tez Generic I²C device component.
https://esphome.io/components/i2c_device/
W pliku dolaczonym jest podany adres i2c oraz adresy poszczegolnych kanalow na ktore sa wysylane wartosci.
Zastanawiam sie czy nie mozna wyslac ich bezposrednio przy uzyciu lambda, bez zadnych dodatkowych komponentow.

Problem rozwiazalem w dosc nietypowy sposob.
Znalazlem zewnetrzy komponent ktory przywraca dzialanie custom component.
Niestety zeby nie bylo tak prosto to przestal dzialac kod w lambda w sekcji interval. W zaden sposob nie chcialo dzialac wiec obeszlem to wrzucajac zawartos lambda do sensora. Przy okazji dodalem nowe funkcje i teraz wszystko smiga. Jak ktos ciekawy wrzucam pliczek po przerobce.

substitutions:
  friendly_name: Ventilation

# zmienne globalne
globals:
  - id: boot_count
    type: int
    restore_value: yes
  - id: temp_target
    type: float
    restore_value: no
    initial_value: '0'
  - id: humidity_target
    type: float
    restore_value: no
    initial_value: '65'
  - id: mode_temp
    type: int
    restore_value: no
    initial_value: '0'
  - id: mode_mem
    type: int
    restore_value: no
    initial_value: '0'
  - id: mode_set
    type: int
    restore_value: no
    initial_value: '0'
  - id: mode_set_mem
    type: int
    restore_value: no
    initial_value: '0'
  - id: hold
    type: int
    restore_value: no
    initial_value: '100'
  - id: timer
    type: int
    restore_value: no
    initial_value: '0'
  - id: valvetime
    type: int
    restore_value: no
    initial_value: '180'
  - id: fan1_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan_min_speed
    type: int
    restore_value: no
    initial_value: '10'
  - id: fan1_mem
    type: int
    restore_value: no
    initial_value: '-1'
  - id: fan2_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan2_mem
    type: int
    restore_value: no
    initial_value: '-1'
  - id: fan3_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan3_mem
    type: int
    restore_value: no
    initial_value: '-1'
  - id: fan4_speed
    type: int
    restore_value: no
    initial_value: '0'
  - id: fan4_mem
    type: int
    restore_value: no
    initial_value: '-1'
  - id: ventilation_mem
    type: std::string
    restore_value: no
    initial_value: '""'


esphome:
  name: ventilation
  friendly_name: $friendly_name
  includes:
    - "/config/esphome/libraries/4channel_krida.h"
  on_boot:
    - priority: 790
      then:
        - lambda: |-
            id(boot_count) = id(boot_count) + 1;


external_components:
  - source:
      type: git
      url: https://github.com/Davrosx/esphome-custom-component
    components: [ custom, custom_component ]


esp32:
  board: wt32-eth01
  framework:
    type: arduino


# Enable logging
logger:


ota:
  - platform: esphome
    password: "***********"


ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk:
    pin: GPIO0
    mode: CLK_EXT_IN
  phy_addr: 1
  power_pin: GPIO16


web_server:
  port: 80


mqtt:
  broker: !secret mqtt_broker
  port: 1883
  username: !secret mqtt_username
  password: !secret mqtt_password


i2c:
  sda: GPIO2
  scl: GPIO4
  scan: True 


pcf8574:
  - id: 'pcb1'
    address: 0x26


time:
  - platform: sntp
    id: sntp_time


text_sensor:
  - platform: template
    name: $friendly_name Uptime
    id: uptime_human
    icon: mdi:clock-start
    entity_category: "diagnostic"
  
  - platform: template
    name: $friendly_name Time
    id: internal_time
    icon: mdi:clock-time-eight-outline
    entity_category: "diagnostic" 

  - platform: template
    name: $friendly_name Mode
    icon: mdi:air-filter
    id: mode_info
    update_interval: 1s
    entity_category: "diagnostic" 

binary_sensor:
  - platform: status
    name: $friendly_name Network
    entity_category: "diagnostic" 
    
  - platform: gpio
    pin:
      number: GPIO36
      mode:
        input: true
      inverted: true
    filters:
      - delayed_on_off: 500ms
    name: $friendly_name Heat Pump State
    id: hp_switch
    icon: mdi:heat-pump-outline
    entity_category: "diagnostic"
    
    
  - platform: gpio
    pin:
      number: GPIO39
      mode:
        input: true
      inverted: true
    filters:
      - delayed_on_off: 1s
    name: $friendly_name Air Filter State
    id: airfilterswitch
    icon: mdi:air-filter
    entity_category: "diagnostic"
    

# przekaźniki
switch:
  - platform: restart
    name: $friendly_name  Reboot
    entity_category: "diagnostic"

  - platform: template
    name: $friendly_name Lock Mode
    icon: mdi:lock-outline
    id: lock
    optimistic: True
    restore_mode: RESTORE_DEFAULT_OFF
    turn_on_action:
      - switch.template.publish:
          id: lock
          state: ON 
    turn_off_action:
      - switch.template.publish:
          id: lock
          state: OFF 

  - platform: gpio
    name: $friendly_name Valve 1
    id: valve1
    icon: mdi:valve
    pin:
     pcf8574: pcb1
     number: 7
     mode: OUTPUT
     inverted: True
        
  - platform: gpio
    name: $friendly_name Valve 2
    id: valve2
    icon: mdi:valve
    pin:
     pcf8574: pcb1
     number: 6
     mode: OUTPUT
     inverted: True   
  
  - platform: gpio
    name: $friendly_name Valve 3
    id: valve3
    icon: mdi:valve
    pin:
     pcf8574: pcb1
     number: 5
     mode: OUTPUT
     inverted: True
           
  - platform: gpio
    name: $friendly_name Valve 4
    id: valve4
    icon: mdi:valve
    pin:
     pcf8574: pcb1
     number: 4
     mode: OUTPUT
     inverted: True   
          
  - platform: gpio
    name: $friendly_name Valve Supply
    id: valvesupply
    icon: mdi:lightning-bolt-outline
    pin:
     pcf8574: pcb1
     number: 3
     mode: OUTPUT
     inverted: True   

  - platform: gpio
    name: $friendly_name Valve 5
    id: valve5
    icon: mdi:valve
    pin:
     pcf8574: pcb1
     number: 2
     mode: OUTPUT
     inverted: True   

  - platform: gpio
    name: $friendly_name Ionizer
    icon: mdi:air-filter
    id: ionizer
    pin:
     pcf8574: pcb1
     number: 1
     mode: OUTPUT
     inverted: True  

  - platform: gpio
    name: $friendly_name Dirty Filter
    id: dirtyfilter
    icon: mdi:air-filter
    pin:
     pcf8574: pcb1
     number: 0
     mode: OUTPUT
     inverted: True


#dimmer
output:
  - platform: custom
    type: float
    lambda: |-
      auto my_custom_float_output = new MyCustomFloatOutput();
      App.register_component(my_custom_float_output);
      my_custom_float_output->channel = 3;
      return {my_custom_float_output};
    outputs:
      id: ch_1

  - platform: custom
    type: float
    lambda: |-
      auto my_custom_float_output = new MyCustomFloatOutput();
      App.register_component(my_custom_float_output);
      my_custom_float_output->channel = 2;
      return {my_custom_float_output};
    outputs:
      id: ch_2

  - platform: custom
    type: float
    lambda: |-
      auto my_custom_float_output = new MyCustomFloatOutput();
      App.register_component(my_custom_float_output);
      my_custom_float_output->channel = 1;
      return {my_custom_float_output};
    outputs:
      id: ch_3
    
  - platform: custom
    type: float
    lambda: |-
      auto my_custom_float_output = new MyCustomFloatOutput();
      App.register_component(my_custom_float_output);
      my_custom_float_output->channel = 0;
      return {my_custom_float_output};
    outputs:
      id: ch_4

    
fan:
  - platform: speed
    output: ch_1
    name: $friendly_name 4ch 1
    id: fan1
    
  - platform: speed
    output: ch_2
    name: $friendly_name 4ch 2
    id: fan2
    
  - platform: speed
    output: ch_3
    name: $friendly_name 4ch 3
    id: fan3
    
  - platform: speed
    output: ch_4
    name: $friendly_name 4ch 4
    id: fan4


number:
  - platform: template
    name: $friendly_name Target Temperature
    id: home_temp_target
    unit_of_measurement: "°C"
    icon: mdi:thermometer
    optimistic: true
    min_value: 15
    max_value: 30
    restore_value: True
    initial_value: 25
    step: 1
    entity_category: "diagnostic"
    
  - platform: template
    name: $friendly_name Lower Night Temperature
    id: night_temp
    unit_of_measurement: "°C"
    icon: mdi:thermometer
    optimistic: true
    min_value: 0
    max_value: 5
    restore_value: True
    initial_value: 0
    step: 1
    entity_category: "diagnostic"

select:
  - platform: template
    name: $friendly_name Mode
    id: ventilation_mode
    options:
      - Fan Off
      - Heat Recovery - Eco
      - Heat Recovery - Max
      - Heat Pump & Recovery - Eco
      - Heat Pump - Cooling
      - Heat Pump - By-pass
      - By-pass - Eco
      - By-pass - Max
      - Cooling By-pass
      - Cooling By-pass - Max
      - Heat Pump & Recovery - Max
      - Heat Recovery - Eco Max
    initial_option: Heat Recovery - Eco
    optimistic: True
    restore_value: True
    icon: mdi:auto-mode
      

sensor:
  - platform: template
    name: $friendly_name Target Temperature
    icon: mdi:home-thermometer-outline
    update_interval: 10s
    unit_of_measurement: "°C"
    device_class: "temperature"
    accuracy_decimals: 1
    lambda: 'return id(temp_target);'

  - platform: dht
    pin: GPIO15
    model: DHT22
    temperature:
      name: $friendly_name Outdoor Temperature
      id: temp_outdoor
      filters:
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: $friendly_name Outdoor Humidity
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: dht
    pin: GPIO33
    model: DHT22
    temperature:
      name: $friendly_name Home Temperature
      id: temp_home
      filters:
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: $friendly_name Home Humidity
      id: humidity
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: dht
    pin: GPIO14
    model: DHT22
    temperature:
      name: $friendly_name Supply Temperature
      id: temp_supply
      filters:
       - calibrate_linear:
          - 0.0 -> 0.0
          - 27.5 -> 25.5
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: $friendly_name Supply Humidity
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: dht
    pin: GPIO32
    model: DHT22
    temperature:
      name: $friendly_name Exhaust Temperature
      id: temp_exhaust
      filters:
       - calibrate_linear:
          - 0.0 -> 0.0
          - 27.5 -> 25.5
       - filter_out: nan
       - filter_out: 85.0 
       -  exponential_moving_average:
            send_every:  2
    humidity:
      name: $friendly_name Exhaust Humidity
      filters:
       - filter_out: nan
       -  exponential_moving_average:
            send_every:  2
    update_interval: 30s

  - platform: template
    id: time_minutes
    lambda: |-
      auto time = id(sntp_time).now();
      return time.hour * 60 + time.minute;
  
  - platform: uptime
    id: uptime_sensor
    internal: True
    
  - platform: template
    name: "Interval 60s"
    update_interval: 60s
    internal: true
    lambda: |-
        ESP_LOGW("main", "Set Mode: %d", id(mode_set));
        
          auto time = id(sntp_time).now();  // # wyświetla bieżący czas
          auto hr = std::to_string(time.hour);
          auto min = std::to_string(time.minute);
          if (time.minute<10) {min="0"+min;}
          auto txt = hr + ":" + min;
          id(internal_time).publish_state(txt);
          
          int boot = id(boot_count);  // # wyświetla czas od włączenia
          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;
          txt = (
                ("(" + to_string(boot) + ") ") +
                (days ? to_string(days) + "d " : "") +
                (hours ? to_string(hours) + "h " : "") +
                (minutes ? to_string(minutes) + "m " : "") +
                (to_string(seconds) + "s")
              ).c_str();
          id(uptime_human).publish_state(txt);

          id(mode_temp) = 1;  // # Ustalenie trybu pracy na podstawie temperatury
          if (id(temp_home).state < id(temp_target) && id(temp_outdoor).state > id(temp_home).state + 3) {id(mode_temp) = 6;}
          if (id(temp_home).state > id(temp_target) && id(temp_outdoor).state < id(temp_home).state - 3) {id(mode_temp) = 6;}
          if (id(temp_home).state > id(temp_target) + 0.5 && id(temp_outdoor).state < id(temp_home).state - 3) {id(mode_temp) = 8;}
          if (id(temp_home).state > id(temp_target) + 1 && id(temp_outdoor).state < id(temp_home).state - 3) {id(mode_temp) = 9;}

          if (id(hp_switch).state) {  // Jeżeli pompa ciepła jest włączona
            id(mode_temp) = 3;
            if (id(temp_home).state > id(temp_target)) {id(mode_temp) = 4;}
            if (id(temp_home).state > id(temp_target) &&  id(temp_outdoor).state < id(temp_home).state -10) {id(mode_temp) = 5;}
          }

          if (id(humidity).state > id(humidity_target)) {  // # Jeżeli jest duża wilgotność
            if (id(mode_temp) == 1) {id(mode_temp) = 1;}
            if (id(mode_temp) == 6) {id(mode_temp) = 7;}
            if (id(mode_temp) == 8) {id(mode_temp) = 9;}
            if (id(mode_temp) == 3) {id(mode_temp) = 3;}
          }

          if (id(mode_temp) == 1 && id(temp_outdoor).state < 5) {id(mode_temp) = 11;}  // Jeżeli jest niska temperatura zewnętrzna
          
          if (id(mode_temp) == id(mode_mem)) {  // # Opóźnienie zmiany trybu pracy
            id(hold) = 10;
          }else{
            id(hold) = id(hold) - 1;
          }
          
          if (id(mode_mem) == 3 or id(mode_mem) == 4 or id(mode_mem) == 5 or id(mode_mem) == 10) {  // # Wyłącznie opóźnienia 
            if (!id(hp_switch).state) {id(hold) = 0;}
          }else{
            if (id(hp_switch).state) {id(hold) = 0;}
          }  
                
          if (id(mode_temp) != id(mode_mem) && id(hold) < 1 && !id(lock).state) {  // # Zmiana trybu pracy
            id(mode_mem) = id(mode_temp);
            id(hold) = 10;

            switch (id(mode_temp)) {
            
              case 1:
                id(ventilation_mode).make_call().set_option("Heat Recovery - Eco").perform();
              break;

              case 2:  
                id(ventilation_mode).make_call().set_option("Heat Recovery - Max").perform(); 
              break;

              case 3:
                id(ventilation_mode).make_call().set_option("Heat Pump & Recovery - Eco").perform(); 
              break;

              case 4:
                id(ventilation_mode).make_call().set_option("Heat Pump - Cooling").perform(); 
              break;

              case 5:
                id(ventilation_mode).make_call().set_option("Heat Pump - By-pass").perform(); 
              break;

              case 6:
                id(ventilation_mode).make_call().set_option("By-pass - Eco").perform(); 
              break;

              case 7:
                id(ventilation_mode).make_call().set_option("By-pass - Max").perform(); 
              break;

              case 8:
                id(ventilation_mode).make_call().set_option("Cooling By-pass").perform(); 
              break;

              case 9:
                id(ventilation_mode).make_call().set_option("Cooling By-pass - Max").perform(); 
              break;
            
              case 10:
                id(ventilation_mode).make_call().set_option("Heat Pump & Recovery - Max").perform(); 
              break;

              case 11:  
                id(ventilation_mode).make_call().set_option("Heat Recovery - Eco Max").perform(); 
              break;
            }
          }
        return 0;

  - platform: template
    name: "Interval 1s"
    update_interval: 1s
    internal: true
    lambda: |-
        if (id(mode_info).state != id(ventilation_mode).state){id(mode_info).publish_state(id(ventilation_mode).state);}
      
        if (id(time_minutes).state > 480 && id(time_minutes).state < 1380 ) {  // # ustalenie temperatury
          id(temp_target) = id(home_temp_target).state;
        }else{
          id(temp_target) = id(home_temp_target).state - id(night_temp).state;
        }
        
        if (id(airfilterswitch).state ) {                   // # kontrolka brudnego filtra
          id(dirtyfilter).turn_on();
        }
        
        if (id(fan1).state ) {                              // # Jonizator 
          if (!id(ionizer).state) {
            id(ionizer).turn_on();
          } 
        }else{
          if (id(ionizer).state) {
            id(ionizer).turn_off();
          } 
        }

        if (id(ventilation_mode).state != id(ventilation_mem) ) {  // # zmiana trybu
          id(ventilation_mem) = id(ventilation_mode).state;

          if (id(ventilation_mode).state == "Fan Off") {  // # Ustawienia parametrów dla wszystkich trybów
            id(mode_set) = 1;
            id(fan1_speed) = 0;
            id(fan2_speed) = 0;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Heat Recovery - Eco") {
            id(mode_set) = 1;
            id(fan1_speed) = 25;
            id(fan2_speed) = 25;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Recovery - Max") {
            id(mode_set) = 1;
            id(fan1_speed) = 100;
            id(fan2_speed) = 100;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Heat Pump & Recovery - Eco") {
            id(mode_set) = 2;
            id(fan1_speed) = 25;
            id(fan2_speed) = 15;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Heat Pump - Cooling") {
            id(mode_set) = 3;
            id(fan1_speed) = 100;
            id(fan2_speed) = 0;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Heat Pump - By-pass") {
            id(mode_set) = 4;
            id(fan1_speed) = 100;
            id(fan2_speed) = 0;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "By-pass - Eco") {
            id(mode_set) = 4;
            id(fan1_speed) = 40;
            id(fan2_speed) = 0;
            id(fan3_speed) = 25;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "By-pass - Max") {
            id(mode_set) = 4;
            id(fan1_speed) = 100;
            id(fan2_speed) = 0;
            id(fan3_speed) = 50;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Cooling By-pass") {
            id(mode_set) = 4;
            id(fan1_speed) = 75;
            id(fan2_speed) = 0;
            id(fan3_speed) = 30;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Cooling By-pass - Max") {
            id(mode_set) = 4;
            id(fan1_speed) = 100;
            id(fan2_speed) = 0;
            id(fan3_speed) = 35;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Heat Pump & Recovery - Max") {
            id(mode_set) = 2;
            id(fan1_speed) = 100;
            id(fan2_speed) = 75;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
          if (id(ventilation_mode).state == "Heat Recovery - Eco Max") {
            id(mode_set) = 1;
            id(fan1_speed) = 20;
            id(fan2_speed) = 20;
            id(fan3_speed) = 0;
            id(fan4_speed) = 0;
          }
        }
        
        if (id(mode_set) != id(mode_set_mem) ) {  // # zasilanie zaworów jeśli nastąpiła zmiana trybu
          if ( id(mode_set_mem) == 0 ) { id(hold) = 2; }
          id(mode_set_mem) = id(mode_set);
          id(timer) = id(valvetime);
          id(valvesupply).turn_on();
        
          switch (id(mode_set)) {  // # ustawienie zaworów
            case 1:  
              id(valve1).turn_off();
              id(valve2).turn_off();
              id(valve3).turn_off();
              id(valve4).turn_off();
              id(valve5).turn_off();
            break;

            case 2:  
              id(valve1).turn_off();
              id(valve2).turn_on();
              id(valve3).turn_off();
              id(valve4).turn_on();
              id(valve5).turn_on();
            break;

            case 3:  
              id(valve1).turn_on();
              id(valve2).turn_off();
              id(valve3).turn_on();
              id(valve4).turn_off();
              id(valve5).turn_off();
            break;

            case 4:  
              id(valve1).turn_on();
              id(valve2).turn_off();
              id(valve3).turn_off();
              id(valve4).turn_on();
              id(valve5).turn_off();
            break;
          }
        }

        if ( id(valvesupply).state ) {  // # Wyłączenie zaworów i zasilania
          if (id(timer) > 0) { 
            id(timer) = id(timer) - 1 ;
          }else{
            id(valvesupply).turn_off();
          }
        }else{
          if ( id(valve1).state ) { id(valve1).turn_off(); }
          if ( id(valve2).state ) { id(valve2).turn_off(); }
          if ( id(valve3).state ) { id(valve3).turn_off(); }
          if ( id(valve4).state ) { id(valve4).turn_off(); }
          if ( id(valve5).state ) { id(valve5).turn_off(); }
        }
      
          if (id(fan1_speed) > id(fan1_mem) ) {  // # zmiana szybkości wentylatorów
            if (id(fan1_speed) < id(fan_min_speed) ) { 
              id(fan1_mem)=0;
              id(fan1_speed)=0;
              id(fan1).turn_off().perform(); 
            }
            if (id(fan1_speed) >= id(fan_min_speed) ) {
              id(fan1_mem)=id(fan1_mem)+1;
              if (id(fan1_mem) < id(fan_min_speed) ) { id(fan1_mem)=id(fan_min_speed); }
              id(fan1).turn_on().set_speed(id(fan1_mem)).perform();
            }
          }
          if (id(fan1_speed) < id(fan1_mem) ) {
            if (id(fan1_speed) < id(fan_min_speed) ) { 
              id(fan1_mem)=0;
              id(fan1_speed)=0;
              id(fan1).turn_off().perform(); 
            }
            if (id(fan1_speed) >= id(fan_min_speed) ) {
              id(fan1_mem)=id(fan1_mem)-1;
              id(fan1).turn_on().set_speed(id(fan1_mem)).perform();
            }
          }
          
          if (id(fan2_speed) > id(fan2_mem) ) {
            if (id(fan2_speed) < id(fan_min_speed) ) { 
              id(fan2_mem)=0;
              id(fan2_speed)=0;
              id(fan2).turn_off().perform(); 
            }
            if (id(fan2_speed) >= id(fan_min_speed) ) {
              id(fan2_mem)=id(fan2_mem)+1;
              if (id(fan2_mem) < id(fan_min_speed) ) { id(fan2_mem)=id(fan_min_speed); }
              id(fan2).turn_on().set_speed(id(fan2_mem)).perform();
            }
          }
          if (id(fan2_speed) < id(fan2_mem) ) {
            if (id(fan2_speed) < id(fan_min_speed) ) { 
              id(fan2_mem)=0;
              id(fan2_speed)=0;
              id(fan2).turn_off().perform(); 
            }
            if (id(fan2_speed) >= id(fan_min_speed) ) {
              id(fan2_mem)=id(fan2_mem)-1;
              id(fan2).turn_on().set_speed(id(fan2_mem)).perform();
              }
          }
          
          if (id(fan3_speed) > id(fan3_mem) ) {
            if (id(fan3_speed) < id(fan_min_speed) ) { 
              id(fan3_mem)=0;
              id(fan3_speed)=0;
              id(fan3).turn_off().perform(); 
            }
            if (id(fan3_speed) >= id(fan_min_speed) ) {
              id(fan3_mem)=id(fan3_mem)+1;
              if (id(fan3_mem) < id(fan_min_speed) ) { id(fan3_mem)=id(fan_min_speed); }
              id(fan3).turn_on().set_speed(id(fan3_mem)).perform();
            }
          }
          if (id(fan3_speed) < id(fan3_mem) ) {
            if (id(fan3_speed) < id(fan_min_speed) ) { 
              id(fan3_mem)=0;
              id(fan3_speed)=0;
              id(fan3).turn_off().perform(); 
            }
            if (id(fan3_speed) >= id(fan_min_speed) ) {
              id(fan3_mem)=id(fan3_mem)-1;
              id(fan3).turn_on().set_speed(id(fan3_mem)).perform();
            }
          }
          
          if (id(fan4_speed) > id(fan4_mem) ) {
            if (id(fan4_speed) < id(fan_min_speed) ) { 
              id(fan4_mem)=0;
              id(fan4_speed)=0;
              id(fan4).turn_off().perform(); 
            }
            if (id(fan4_speed) >= id(fan_min_speed) ) {
              id(fan4_mem)=id(fan4_mem)+1;
              if (id(fan4_mem) < id(fan_min_speed) ) { id(fan4_mem)=id(fan_min_speed); }
              id(fan4).turn_on().set_speed(id(fan4_mem)).perform();
            }
          }
          if (id(fan4_speed) < id(fan4_mem) ) {
            if (id(fan4_speed) < id(fan_min_speed) ) { 
              id(fan4_mem)=0;
              id(fan4_speed)=0;
              id(fan4).turn_off().perform(); 
            }
            if (id(fan4_speed) >= id(fan_min_speed) ) {
              id(fan4_mem)=id(fan4_mem)-1;
              id(fan4).turn_on().set_speed(id(fan4_mem)).perform();
              }
          }

        return 0;
2 polubienia