Sensor data processing and output control whit LAMBDA

I have an ESP32-C3 with two inlet temperature sensors connected and a fan controlled in speed via pwm.
What I would like to do is control the fan based on the temperature difference of the two sensors.
But I’m not succeeding, mainly because I don’t understand how to pass the sensor data from yalm to c++(lambda) and vice versa. Copy below what I wrote, can you help me better understand how to use the lambda function?

esphome:
  name: ventola-terzo-piano
  friendly_name: Ventola terzo piano

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

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "***"

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

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password

    - ssid: !secret wifi_ssid1
      password: !secret wifi_password1

    - ssid: !secret wifi_ssid2
      password: !secret wifi_password2

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Ventola-Terzo-Piano"
    password: "***"

captive_portal:

i2c:
  sda: GPIO01
  scl: GPIO02
  scan: True

output:
  - platform: ledc #esp8266_pwm
    pin: GPIO00
    frequency: 1000 Hz
    id: pwm_output

sensor:
  - platform: bmp280_i2c
    temperature:
      name: T_Ext
    pressure:
      name: P_Ext
    address: 0x76
    update_interval: 60s

  - platform: aht10
    #variant: AHT10
    temperature:
      name: T_int
    humidity:
      name: H_Int
    address: 0x38
    update_interval: 61s
  
  - platform: template 
    sensors: 
      temperature_difference: 
        friendly_name: "Differenza di temperatura" 
        unit_of_measurement: '°C'
        value_template: 
          "{{states('sensor.ventola_terzo_piano_t_int') | float - states('sensor.ventola_terzo_piano_t_ext') | float}}  

fan:
  - platform: speed
    output: pwm_output
    name: ventola
    on_speed_set:
      - logger.log:
          format: "Fan Speed was changed to %d!"
          args: pwm_output

Well to start you need to use the ESPHOME not the Home Assistant syntax.

Ok, I’ve correct this part

But now, how i can pass the value of return to pwm_output?

esphome:
  name: ventola-terzo-piano
  friendly_name: Ventola terzo piano

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

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "***"

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

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password

    - ssid: !secret wifi_ssid1
      password: !secret wifi_password1

    - ssid: !secret wifi_ssid2
      password: !secret wifi_password2

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Ventola-Terzo-Piano"
    password: "***"

captive_portal:

i2c:
  sda: GPIO01
  scl: GPIO02
  scan: True

output:
  - platform: ledc #esp8266_pwm
    pin: GPIO00
    frequency: 1000 Hz
    id: pwm_output

sensor:
  - platform: bmp280_i2c
    temperature:
      name: T_Ext
      id: t_ext
    pressure:
      name: P_Ext
    address: 0x76
    update_interval: 60s

  - platform: aht10
    #variant: AHT10
    temperature:
      name: T_int
      id: t_int
    humidity:
      name: H_Int
    address: 0x38
    update_interval: 61s
  
  - platform: template
    name: "Template Sensor"
    lambda: |-
      if ((((id(t_ext).state)-(id(t_int).state)) >= 2) && (((id(t_ext).state)-(id(t_int).state)) < 3)){
        return 30;
      } 
      if ((((id(t_ext).state)-(id(t_int).state)) >= 3) && (((id(t_ext).state)-(id(t_int).state)) < 5)){
        return 100;
      } 
      if (((id(t_ext).state)-(id(t_int).state)) >= 5){
        return 250;
      } else {
        return 0;
      }
    update_interval: 60s

fan:
  - platform: speed
    output: pwm_output
    name: ventola
    on_speed_set:
      - logger.log:
          format: "Fan Speed was changed to %d!"
          args: pwm_output

Add this to the end of your template sensor lambda call

auto call = id(fan1).turn_on();
call.set_speed(x);
call.perform();

and give id to your fan component:
id: fan1

I had read about this call on a documentation, but I never understood completely. by the way I Correct the yalm configuration in this way but the output never change…

i2c:
  sda: GPIO01
  scl: GPIO02
  scan: True

output:
  - platform: ledc #esp8266_pwm
    pin: GPIO00
    frequency: 1000 Hz
    id: pwm_output

sensor:
  - platform: bmp280_i2c
    temperature:
      name: T_Ext
      id: t_ext
    pressure:
      name: P_Ext
    address: 0x76
    update_interval: 60s

  - platform: aht10
    #variant: AHT10
    temperature:
      name: T_int
      id: t_int
    humidity:
      name: H_Int
    address: 0x38
    update_interval: 61s
  
  - platform: template
    name: "Template Sensor"
    lambda: |-
      int x = 0;
      if ((((id(t_ext).state)-(id(t_int).state)) >= 2) && (((id(t_ext).state)-(id(t_int).state)) < 3)){
        return 30;
      } 
      if ((((id(t_ext).state)-(id(t_int).state)) >= 3) && (((id(t_ext).state)-(id(t_int).state)) < 5)){
        return 100;
      } 
      if (((id(t_ext).state)-(id(t_int).state)) >= 5){
        return 250;
      } else {
        return 0;
      }
      auto call = id(fan1).turn_on();
      call.set_speed(x);
      call.perform(); 
    update_interval: 60s

fan:
  - platform: speed
    output: pwm_output
    name: ventola
    id: fan1
    on_speed_set:
      - logger.log:
          format: "Fan Speed was changed to %d!"
          args: pwm_output

Afaik as default fan speed is 0-100.
Set the update interval to few seconds (for debugging) and observe what you get on log.

On a log it works properly. But the output work only malualli if I switch the output on. And when it’s on is at the maximum out, it never change whith the Return value display on a log.

Ps. i change the value of return from 250 to 100 and 100 to 50.

So you say it’s updating the fan speed on fan component but not the pwm on output component??

You don’t want to set int x=0;

In case it’s not updating the fan speed with that lambda call, try like this:

platform: template
    name: "Template Sensor"
    lambda: |-
      if ((((id(t_ext).state)-(id(t_int).state)) >= 2) && (((id(t_ext).state)-(id(t_int).state)) < 3)){
        return 30;
      } 
      if ((((id(t_ext).state)-(id(t_int).state)) >= 3) && (((id(t_ext).state)-(id(t_int).state)) < 5)){
        return 50;
      } 
      if (((id(t_ext).state)-(id(t_int).state)) >= 5){
        return 100;
      } else {
        return 0;
      }
    on_value:
      then:
        - fan.turn_on:
            id: fan1
            speed: !lambda "return x;"   
    update_interval: 60s
1 Like

I have setted x=0; because compiling ask me to declare…

So I try the new version but it give me back an error… but I indent correctly

- platform: template
    name: "Template Sensor"
    lambda: |-
      if ((((id(t_ext).state)-(id(t_int).state)) >= 2) && (((id(t_ext).state)-(id(t_int).state)) < 3)){
        return 30;
      } 
      if ((((id(t_ext).state)-(id(t_int).state)) >= 3) && (((id(t_ext).state)-(id(t_int).state)) < 5)){
        return 50;
      } 
      if (((id(t_ext).state)-(id(t_int).state)) >= 5){
        return 100;
      } else {
        return 0;
      }
      //auto call = id(fan1).turn_on();
      //call.set_speed(x);
      //call.perform(); 
    on_value:
      then:
        - fan.turn_on:
          id: fan1
          speed: !lambda "return x;"
    update_interval: 10s
sensor.template: [source /config/esphome/ventola-terzo-piano.yaml:71]
  platform: template
  name: Template Sensor
  lambda: |-
    if ((((id(t_ext).state)-(id(t_int).state)) >= 2) && (((id(t_ext).state)-(id(t_int).state)) < 3)){
      return 30;
    } 
    if ((((id(t_ext).state)-(id(t_int).state)) >= 3) && (((id(t_ext).state)-(id(t_int).state)) < 5)){
      return 50;
    } 
    if (((id(t_ext).state)-(id(t_int).state)) >= 5){
      return 100;
    } else {
      return 0;
    }
    //auto call = id(fan1).turn_on();
    //call.set_speed(x);
    //call.perform(); 
  on_value: 
    then: 
      
Cannot have two actions in one item. Key 'fan.turn_on' overrides 'id'! Did you forget to indent the block inside the fan.turn_on?.
      - fan.turn_on: 
        id: fan1
        speed: !lambda |-

Maybe I have to move all the lambda code on a speed: !lambda |- … ?

remove those lines, you are not with arduino ide…
And you didn’t answer my first question of my previous post!

I make a step back and I reintegrated auto call function and this is the log

[14:39:37][D][sensor:094]: 'Template Sensor': Sending state 30.00000  with 1 decimals of accuracy
[14:39:40][D][sensor:094]: 'T_int': Sending state 20.48111 °C with 2 decimals of accuracy
[14:39:40][D][sensor:094]: 'H_Int': Sending state 34.09138 % with 2 decimals of accuracy
[14:39:40][W][component:170]: Component aht10.sensor cleared Warning flag
[14:39:43][D][bmp280.sensor:182]: Got temperature=24.8°C pressure=945.5hPa
[14:39:43][D][sensor:094]: 'T_Ext': Sending state 24.81398 °C with 1 decimals of accuracy
[14:39:43][D][sensor:094]: 'P_Ext': Sending state 945.52264 hPa with 1 decimals of accuracy
[14:39:43][W][component:170]: Component bmp280_base cleared Warning flag
[14:39:48][D][sensor:094]: 'Template Sensor': Sending state 50.00000  with 1 decimals of accuracy
[14:39:50][D][sensor:094]: 'T_int': Sending state 20.55969 °C with 2 decimals of accuracy
[14:39:50][D][sensor:094]: 'H_Int': Sending state 34.61981 % with 2 decimals of accuracy
[14:39:52][D][bmp280.sensor:182]: Got temperature=24.2°C pressure=945.5hPa
[14:39:52][D][sensor:094]: 'T_Ext': Sending state 24.16320 °C with 1 decimals of accuracy
[14:39:52][D][sensor:094]: 'P_Ext': Sending state 945.45013 hPa with 1 decimals of accuracy
[14:39:54][D][fan:021]: 'ventola' - Setting:
[14:39:54][D][fan:024]:   State: OFF
[14:39:54][D][fan:120]: 'ventola' - Sending state:
[14:39:54][D][fan:121]:   State: OFF
[14:39:54][D][fan:123]:   Speed: 100
[14:39:55][D][fan:021]: 'ventola' - Setting:
[14:39:55][D][fan:024]:   State: ON
[14:39:55][D][fan:120]: 'ventola' - Sending state:
[14:39:55][D][fan:121]:   State: ON
[14:39:55][D][fan:123]:   Speed: 100
[14:39:57][D][fan:021]: 'ventola' - Setting:
[14:39:57][D][fan:024]:   State: OFF
[14:39:57][D][fan:120]: 'ventola' - Sending state:
[14:39:57][D][fan:121]:   State: OFF
[14:39:57][D][fan:123]:   Speed: 100
[14:39:58][D][fan:021]: 'ventola' - Setting:
[14:39:58][D][fan:024]:   State: ON
[14:39:58][D][fan:120]: 'ventola' - Sending state:
[14:39:58][D][fan:121]:   State: ON
[14:39:58][D][fan:123]:   Speed: 100
[14:39:59][D][sensor:094]: 'Template Sensor': Sending state 50.00000  with 1 decimals of accuracy
[14:40:00][D][sensor:094]: 'T_int': Sending state 20.55607 °C with 2 decimals of accuracy
[14:40:00][D][sensor:094]: 'H_Int': Sending state 33.83141 % with 2 decimals of accuracy
[14:40:01][D][bmp280.sensor:182]: Got temperature=23.6°C pressure=945.4hPa
[14:40:01][D][sensor:094]: 'T_Ext': Sending state 23.59367 °C with 1 decimals of accuracy
[14:40:01][D][sensor:094]: 'P_Ext': Sending state 945.43341 hPa with 1 decimals of accuracy
[14:40:10][D][bmp280.sensor:182]: Got temperature=23.2°C pressure=945.4hPa
[14:40:10][D][sensor:094]: 'T_Ext': Sending state 23.24406 °C with 1 decimals of accuracy
[14:40:10][D][sensor:094]: 'P_Ext': Sending state 945.42932 hPa with 1 decimals of accuracy
[14:40:10][D][sensor:094]: 'T_int': Sending state 20.56618 °C with 2 decimals of accuracy
[14:40:10][D][sensor:094]: 'H_Int': Sending state 33.64458 % with 2 decimals of accuracy
[14:40:11][D][sensor:094]: 'Template Sensor': Sending state 30.00000  with 1 decimals of accuracy
[14:40:20][D][bmp280.sensor:182]: Got temperature=23.0°C pressure=nanhPa
[14:40:20][D][sensor:094]: 'T_Ext': Sending state 22.98313 °C with 1 decimals of accuracy
[14:40:20][D][sensor:094]: 'P_Ext': Sending state nan hPa with 1 decimals of accuracy

the [fan:****] is me that turn off and on the output
But in other case the output was stable on or off and never change

So it didn’t update the fan.
Then try the code on my post#8. What you get on log…?

I haven’t a log because fail during compiling

Cannot have two actions in one item. Key 'fan.turn_on' overrides 'id'! Did you forget to indent the block inside the fan.turn_on?.

did you remove those 3 call lines from lamda??

Yes I do :wink:
And I declared int x; without 0

so post the yaml…

- platform: template
    name: "Template Sensor"
    lambda: |-
      if ((((id(t_ext).state)-(id(t_int).state)) >= 2) && (((id(t_ext).state)-(id(t_int).state)) < 3)){
        return 30;
      } 
      if ((((id(t_ext).state)-(id(t_int).state)) >= 3) && (((id(t_ext).state)-(id(t_int).state)) < 5)){
        return 50;
      } 
      if (((id(t_ext).state)-(id(t_int).state)) >= 5){
        return 100;
      } else {
        return 0;
      }
    on_value:
      then:
        - fan.turn_on:
          id: fan1
          speed: !lambda "return x;"
    update_interval: 11s

fan:
  - platform: speed
    output: pwm_output
    name: ventola
    id: fan1
    on_speed_set:
      - logger.log:
          format: "Fan Speed was changed to %d!"
          args: pwm_output
    

it’s missing indentation for id and speed

1 Like

:flushed: Sorry.
Now it work.
Can I ask 1 more question? or maybe I have to create another post…
If I want to use a data from another device like a temperature I have only to declare the ID setted on that device?

Good!
Indentations are pain in the ass.

“from another device” means what exactly? Something not connected to that Esphome? Or?