Prototyping: struggling to get RGB LED to show status of a Servo controlled blast gate

I am trying to prototype 3 blast gates being controlled by espHome in a workshop. Only one blast gate can be open at a time (opening one immediately closes the one that was open) and each has a single RGB LED which can be in one of 3 states:
Open (Green)
Closed (Red)
Blue (opening or closing).
I suspect that the opening closing duration would be 2-3 secs.
At the moment I am struggling to get a single gate working with these basic states. I just have a simple control on the dashboard to open or close the gate

Can anyone help me with the logic. I am relatively new to espHome and am going around in circles with Effects, on_light_on etc


esphome:
  name: blast-gatea1
  friendly_name: blast-gateA1

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "REMOVED FOR SECURITY"
  services:
    - service: control_servo
      variables:
        level: float
      then:
        - servo.write:
            id: my_servo
            level: !lambda 'return level / 100.0;'
 
ota:
  password: "REMOVED FOR SECURITY"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Blast-Gatea1 Fallback Hotspot"
    password: "REMOVED FOR SECURITY"

captive_portal:

servo:
  - id: my_servo
    output: pwm_output
    auto_detach_time: 2s
   
# Usage of ledc in lights
light:
  - platform: rgb
    name: "RGB led single"
    red: output_red
    green: output_green
    blue: output_blue
    id: test
    effects:
      - pulse:
      - pulse:
          name: "pulsing"
          transition_length: 0.5s
          update_interval: 1s
    default_transition_length: 1s
    on_turn_on:
      light.turn_on:
        id: test
        effect: pulsing

output:
  - platform: ledc
    id: pwm_output
    pin: 18
    frequency: 50 Hz
  - platform: ledc
    pin: GPIO22
    id: output_red
    frequency: 100 Hz
    max_power: 100%
  - platform: ledc
    pin: GPIO21
    id: output_green
    frequency: 100 Hz
    max_power: 100%
  - platform: ledc
    pin: GPIO19
    id: output_blue
    frequency: 100 Hz
    max_power: 100%

Which particular bits are you struggling with? Have you got one gate opening and closing as you want? Have you got one light turning on/off as you like?

I take it the gates don’t have fully open/fully closed endstop/state detection?

My initial thought here was to set up each gate as a cover (perhaps a feedback cover).

As part of the open action, each gate would also close the other gates (with delays if required) and turn on/off lights.

You could also potentially do something similar with template switches.

Your light should just be a light, no effects.

What I’d do is create an internal template that’s set to the same value as your servo setpoint, I think it would be 0-100. Then use three different on_value or on_range actions to turn on the light to a specific RGB mix.

Thanks for your reply. I was struggling with the logic of whether to control the lights independently of the servo and thus whether to use to the native lights and output functionality or whether to link it more closely to the Servo state. I will have a look at both the covers and the templates you have suggested, but the short answer is I haven’t got either the gate or the lights working at the moment!

My hope was to start with a single servo. When it is closed the led is red; when it is opening (Or closing) the led flashes blue and when it is open then the led shows green. I then hope to add two more gates and the logic that said “if you open a gate, check that no other gate is open and if it is then close it”

But thanks so much for taking the time to reply and for your suggestions. I will look into those now but happy to have any further guidance if my answer has helped clarify

Thank you - I am going to look at templates now.

Maybe try Automations and Templates — ESPHome

You’d have three if areas that use your servo_id and tell them light the light if in range.

Also, look at the detach function so your servos so stay powered on indefinitely. That will cause them to burn up prematurely.

Firslty thanks for your suggestions but I am really struggling to make progress. I am not sure I understand enough about templates or feedback covers to progress. Worse even is that I suspect I should be using a state machine (and I don’t understand how to code that even if I understand the logic!)
I have 3 servos. Each servo controls a blast gate and each blast gate can be in any one of 4 states:

  • Open
  • Closed
  • Opening
  • Closing
    Only 1 servo can be open at anyone time. But of course a couple of servos could be in transition states (opening or closing) because we have decided to open a different servo. Each servo has a single RGB LED that reflects its state.
    Open - Green
    Closed - red
    Opening/closing: blue

I am not sure is how to determine the servo value and even more confused now about Feedback Cover and templates! The blast gates do not have any endstop sensor, so a feedback cover would have to be time based, but I would rather use the position of the servo to determine the state ie Closed (-100) or open (100) and anything in between means opening or closing

I tried it by setting a number and I could get this to work ie -100 red led comes on; +100 green Led comes on and anything in between the blue led comes on, but of course I want this to be read automatically rather than for me to input a number.

Here’s where I am at (also known as lost!)

number:
  - platform: template
    name: Servo Control
    min_value: -100
    initial_value: -100
    max_value: 100
    step: 1
    optimistic: true
    set_action:
      then:
        - servo.write:
            id: blast_gate1_servo
            level: !lambda 'return x / 100.0;'
        - switch.turn_off: LEDred
        - switch.turn_on: LEDblue


cover:
  - platform: feedback
    name: "Blast Gate Cover"
    has_built_in_endstop: false
    max_duration: 3s
    device_class: garage
    open_action:
      - servo.write:   # close gate 2
          id: blast_gate2_servo
          level: -100.0%
      - sensor.in_range:   # This is not the corect way to read the servo position but not sure what is!
          id: blast_gate1_servo
          - below: 100.0
              switch.turn_on: LEDblue
          
    close_action:
      - switch.turn_on: LEDblue
      - switch.turn_off: LEDgreen
    stop_action:
     - switch.turn_off: LEDblue
     - switch.turn_on: LEDred

I wouldn’t use covers, they are not a good fit here

Ping me on esphome discord and I can help

thank you. I will do that now

I reckon they are, but it’s definitely a matter of preference and different ways to approach it. Each gate has a very strong analogy to a cover.

Once set up it has all the states you need and the cover will report these states (which you can also access).

I would probably “create some endstop binary sensors from the servo values” (fully open/fully closed) using a binary sensor template if the best way to determine open/closed is from the servo value.

The approach you’re suggesting will work very well too and it’s probably “lighter touch”.

The cover approach will give you nice frontend controls.

I haven’t done this for ages and am not sure either. This post seems to have some info on creating a sensor for servo position. Seems harder than it should be. Once you’re tracking the servo position everything should get a lot easier.