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
szopen
13 Październik 2025 14:41
2
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
# 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 .
szopen
13 Październik 2025 18:16
4
Świetnie, a pozostałe odpowiedzi?
Bo jak na razie to jedyne co mogę zasugerować to kompilowanie w odpowiednio starej wersji ESPHome
ESPHome addons from previous versions. Just in case something isn't working with the new version
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
szopen
13 Październik 2025 19:00
6
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)
angler
(Cezary.K)
13 Październik 2025 20:04
7
Ktoś już zaczął dopisywać obsługę tego sprzętu do ESPHome, ale nie dokończył. Kod wydaje się był gotowy:
esphome:dev ← dcsim0n:krida_dimmer
opened 10:09PM - 15 Nov 23 UTC
# What does this implement/fix?
Adds support for multi-channel i2c leading ed… ge ac dimmers
https://www.tindie.com/products/bugrovs2012/i2c-4ch-ac-led-dimmer-module/
## Types of changes
- [x ] New feature (non-breaking change which adds functionality)
**Related issue or feature (if applicable):** fixes [<link to issue>](https://github.com/esphome/feature-requests/issues/1409)
**Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here>
## Test Environment
- [ ] ESP32
- [ ] ESP32 IDF
- [x] ESP8266
- [ ] RP2040
- [ ] BK72xx
- [ ] RTL87xx
## Example entry for `config.yaml`:
```yaml
output:
- platform: krida_4ch_dimmer
address: 0x27
id: krida_ch1
channel: 0x80
light:
- platform: monochromatic
name: "Channel 1"
output: krida_ch1
```
## Checklist:
- [x ] The code change is tested and works locally.
- [ ] Tests have been added to verify that the new code works (under `tests/` folder).
If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [esphome-docs](https://github.com/esphome/esphome-docs).
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