Use output of one component as the input to another component

I have been having a play with the slow_pwm component to make a simulator for the flashing LED’s on my power tool charger so I can come up with a way to detect the charge states from the flashes.

So far I have slow_pwm doing it’s thing and have added a couple of rotary encoders that I have displayed on an OLED.

I would like to use the rotary encoder outputs to change the period and duty cycle.

Can someone point me in the direction of how to do this.

# slow pwm tester
# Lolin ESP32 OLED (HW-724)

# V3a - changed board to ESP32 OLED and add extra encoder
# V3b - display rotary setting on OLED, divide rotary2 by 100 for finer control
# V3c - rotate display to 270, center text
# V3d - start slow_pwm with rotary2 switch, add lo_led
# V3e - add power led


esphome:
  name: slow-pwm3
  friendly_name: slow-pwm3

  on_boot:
    priority: -10
    then:
      - output.turn_on: pwr_led
          
esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:
  level: verbose

# Enable Home Assistant API
api:

ota:
  password: ""

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Slow-Pwm3 Fallback Hotspot"
    password: "password"

output:
  - platform: slow_pwm
    pin: GPIO13
    id: slow_pwm3
    period: 2s

    turn_on_action:
      - output.turn_on: hi_led
      - output.turn_off: lo_led      

    turn_off_action:
      - output.turn_off: hi_led
      - output.turn_on: lo_led

  - platform: gpio # on when o/p high
    id: hi_led
    pin:
      number: GPIO15
      
  - platform: gpio # on when o/p low
    id: lo_led
    pin:
      number: GPIO3

  - platform: gpio # on when after boot
    id: pwr_led
    pin:
      number: GPIO2     
      
sensor:

  - platform: rotary_encoder # duty cycle set with rotary1  
    name: "Rotary1"
    id: rotary1
    pin_a: GPIO36
    pin_b: GPIO25
    min_value: 0
    max_value: 100
    publish_initial_value: true
    filters:
      - debounce: 0.1s
    resolution: 2

    on_clockwise:
      - logger.log: "Turned Clockwise 1"
    on_anticlockwise:
      - logger.log: "Turned Anticlockwise 1" 
      
  - platform: rotary_encoder # period set with rotary1
    name: "Rotary2"
    id: rotary2
    pin_a: GPIO39
    pin_b: GPIO16
    min_value: 0
    max_value: 1000
    publish_initial_value: true
    filters:
      - multiply: .01
      - debounce: 0.1s
    resolution: 2

    on_clockwise:
      - logger.log: "Turned Clockwise 2"
    on_anticlockwise:
      - logger.log: "Turned Anticlockwise 2" 

      
  - platform: wifi_signal
    name: "Slow PWM3 WiFi"
    update_interval: 10s 

# Display stuff
i2c:
  sda: GPIO5
  scl: GPIO4
  scan: true
  frequency: 400kHz

binary_sensor:

  - platform: gpio # momentary sw on rotary1
    pin: 
      number: GPIO26
      mode: INPUT_PULLUP
      inverted: true
    id: switch1
    name: "Rotary1 Switch"
    filters:
      - delayed_on: 10ms
      
  - platform: gpio # momentary sw on rotary2
    pin: 
      number: GPIO14
      mode: INPUT_PULLUP
      inverted: true
    id: switch2
    name: "Rotary2 Switch"
    filters:
      - delayed_on: 10ms
      
    on_click:
      min_length: 50ms
      max_length: 350ms
      then:
        - logger.log: "Single-Clicked"
        - output.turn_on: slow_pwm3
        - output.set_level:
            id: slow_pwm3
            level: "50%"


    on_multi_click:
    - timing:
        - ON for at most 3s
        - OFF for at most 3s
        - ON for at most 3s
        - OFF for at least 0.2s
      then:
        - logger.log: "Double-Clicked"
        - output.turn_off: slow_pwm3
      
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    update_interval: 0.5s
    contrast: 80%
    address: 0x3C
    rotation: 270
    lambda: |-
      it.print(32, 5, id(font3), TextAlign::TOP_CENTER, "DUTY");
      it.printf(32, 30, id(font5), TextAlign::TOP_CENTER, " %.0f %%", id(rotary1).state);
      it.print(32, 85, id(font3), TextAlign::TOP_CENTER, "PERIOD");
      it.printf(32, 110, id(font5), TextAlign::TOP_CENTER, " %.2f S", id(rotary2).state); 

font:

  - file: 'fonts/arial.ttf'
    id: font3
    size: 14
    
  - file: 'fonts/arial.ttf'
    id: font5
    size: 18

I think you would use Set Level action

Well that is a bit disappointing, I have had a play with lambda options and the duty cycle bit works with this:

    name: "Rotary1"
    id: rotary1
    pin_a: GPIO36
    pin_b: GPIO25
    min_value: 0
    max_value: 100
    publish_initial_value: true
    filters:
      - debounce: 0.1s
    resolution: 2

    on_clockwise:
      then:
        - logger.log: "Turned Clockwise 1"
        - output.set_level:
            id: slow_pwm3
            level: !lambda |-
              return id(rotary1).state / 100;

    on_anticlockwise:
      then:
        - logger.log: "Turned Anticlockwise 1"
        - output.set_level:
            id: slow_pwm3
            level: !lambda |-
              return id(rotary1).state / 100;

The real bummer is that the period value in the slow_pwm component is not templatable, so the whole idea is not really usable if I can’t adjust the time.

Any ideas on how I can work around this ??

Really?

output.set_level Action

This action sets the float output to the given level when executed. Note: This only works with floating point outputs like ESP8266 Software PWM Output, ESP32 LEDC Output, Sigma-Delta Output, Slow PWM Output.

on_…: then: - output.set_level: id: light_1 level: 50%
Note

This action can also be expressed in lambdas:

// range is 0.0 (off) to 1.0 (on) id(light_1).set_level(0.5);

The duty cycle is set from an output.set_level Action and that works but the period is set from the slow_pwm component.

output:
  - platform: slow_pwm
    pin: D1
    id: my_slow_pwm
    period: 15s

If I try to use a lambda for the period I get this error:

1 Like

Sorry, I get your meaning, not sure how to get through that issue.

Don’t use lambdas - clever code is unmaintainable, and seems to break parsers.
Trigger from a state change.
Change period: 300s directly.

Linked from:

?? I’ll need a bit more of a prompt to get an idea of what you are suggesting.