Using RGBW light component with UART output to conrol LED lamp

Good Evening All,

I am new to using home assistant and EspHome. I’ve been doing alot of reading but have not been able to figure out how to achieve that I need to do.

Some background. I have a RGBW led that can be controlled over uart by sending the following commands as text:

“AT” returns: Comms ok and the current PWM values in seperate lines.

“AT-U#RRRR#GGGG#BBBB#WWWW” Sets pwm values of each colour with a input range between 0 and 1023 for Red, Green, Blue and White. It also returns Comms ok and return the received and updated pwm values

“AT-S” starts a routine and returns Comms ok and Sunrise commenced on seperate lines

The light also has buttons on the light that manually changes brightness up and down and change to a couple of preset modes.

The UART overides any modes that was running until a button is pressed again and the led sends the last received string, individual pwm values from the string and current PWM values every 500ms

example commands and feedback can be seen below:

I believe that I need to use a mix of the Light RGBW component and the UART components to achive the control from home assistant.

My ESPhome yaml file as follows:

esphome:
  name: led
  friendly_name: Led 

esp8266:
  board: esp01_1m

# Enable logging
logger:

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

ota:
  - platform: esphome
    password: "password removed"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  # Optional manual IP
  manual_ip:
    static_ip: 192.168.1.20
    gateway: 192.168.1.1
    subnet: 255.255.255.0
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Led Fallback Hotspot"
    password: "password removed"

uart:
  tx_pin: GPIO01
  rx_pin: GPIO03
  baud_rate: 115200

output:
  - platform: rgbw
    id: output_component1
    min_power: 0
    max_power: 1023
  - platform: rgbw
    id: output_component2
    min_power: 0
    max_power: 1023
  - platform: rgbw
    id: output_component3
    min_power: 0
    max_power: 1023
  - platform: rgbw
    id: output_component4
    min_power: 0
    max_power: 1023


light:
  - platform: rgbw
    name: "Led"
    red: output_component1
    green: output_component2
    blue: output_component3
    white: output_component4



captive_portal:


This is giving the following error

INFO ESPHome 2024.11.3
INFO Reading configuration /config/esphome/led.yaml...
INFO Unable to import component rgbw.output: No module named 'esphome.components.rgbw.output'
INFO Unable to import component rgbw.output: No module named 'esphome.components.rgbw.output'
INFO Unable to import component rgbw.output: No module named 'esphome.components.rgbw.output'
INFO Unable to import component rgbw.output: No module named 'esphome.components.rgbw.output'
Failed config

output.rgbw: [source /config/esphome/led.yaml:39]
  
  Platform not found: 'output.rgbw'.
  platform: rgbw
  id: output_component1
  min_power: 0
  max_power: 1023
output.rgbw: [source /config/esphome/led.yaml:43]
  
  Platform not found: 'output.rgbw'.
  platform: rgbw
  id: output_component2
  min_power: 0
  max_power: 1023
output.rgbw: [source /config/esphome/led.yaml:47]
  
  Platform not found: 'output.rgbw'.
  platform: rgbw
  id: output_component3
  min_power: 0
  max_power: 1023
output.rgbw: [source /config/esphome/led.yaml:51]
  
  Platform not found: 'output.rgbw'.
  platform: rgbw
  id: output_component4
  min_power: 0
  max_power: 1023

I am at a bit of a loss in how to get from the RGBW led component to outputing the string to the led lamp over uart.

I believe the max and min set in the output should limit the values to between 0 and 1023 but it seems to cause issues.

Any help will be much appreaciated to get the Led lamp controlled and integrated into home assistant.

Thanks
AB

You are getting errors because afaik output component doesn’t have rgbw platform.
You could try to build something around template output, never tried though.

Thank you for your help Karosm,

I have an update. I manage to get the button press to uart transmission sorted now. I have a couple of buttons that gives me a couple of different lights/turn the lights on/off using this snippit of Yaml code:

  tx_pin: GPIO01
  rx_pin: GPIO03
  baud_rate: 115200

button:
  - platform: template
    name: "Light Off"
    on_press:
      - uart.write: "AT-P#\r"
  - platform: template
    name: "Red Light"
    on_press:
      - uart.write: "AT-U#1023#0#0#0\r"
  - platform: template
    name: "Green Light"
    on_press:
      - uart.write: "AT-U#0#1023#0#0\r"
  - platform: template
    name: "Blue Light"
    on_press:
      - uart.write: "AT-U#0#0#1023#0\r"
  - platform: template
    name: "White Light"
    on_press:
      - uart.write: "AT-U#1023#1023#1023#1023\r"

Is there a way to used the light module RGBW and write that to a variable?

If this is possible i can write the values out over uart.

output:
  - platform: template
    id: output_component1
    min_power: 0
    max_power: 1023
    write_action:

When the state for this output is updated, the write_action is triggered. It is possible to access the state value inside Lambdas:

Hi Karosm,

Thank you for helping with a example, I will give it a go. I am still learning yaml and the lamdas.

Just to clarify the lamdas would be the “output_component1” etc. If so is all the lampdas avaiable as I need to efectively write it as a single string that contains all the RGBW values?

I’ve tried this but I am getting and error


output:
  - platform: template
    id: output_component1
    min_power: 0
    max_power: 1023
    write_action:
      uart.write: !lambda
        return {{ ["AT-U",output_component1, output_component2, output_component3,output_component4]|join('#') }} ;
  - platform: template
    id: output_component2
    min_power: 0
    max_power: 1023
    write_action:
      uart.write: !lambda
        return {{ ["AT-U",output_component1, output_component2, output_component3,output_component4]|join('#') }} ;
  - platform: template
    id: output_component3
    min_power: 0
    max_power: 1023
    write_action:
      uart.write: !lambda
        return {{ ["AT-U",output_component1, output_component2, output_component3,output_component4]|join('#') }} ;
  - platform: template
    id: output_component4
    min_power: 0
    max_power: 1023
    write_action:
      uart.write: !lambda
        return {{ ["AT-U",output_component1, output_component2, output_component3,output_component4]|join('#') }} ;


light:
  - platform: rgbw
    name: "Led"
    red: output_component1
    green: output_component2
    blue: output_component3
    white: output_component4

The error is:

INFO ESPHome 2024.11.3
INFO Reading configuration /config/esphome/led-bedlamp-1.yaml...
Failed config

output.template: [source /config/esphome/led-bedlamp-1.yaml:72]
  
  type not specified!.
  platform: template
  id: output_component1
  min_power: 0
  max_power: 1023
  write_action: 
    uart.write: !lambda |-
      return { ["AT-U",output_component1, output_component2, output_component3,output_component4]|join('#') } ;

Where am I going wrong?

Every color is separate output, you can’t have a state of them like that.
Also, max_power is not some multiplier, it’s just limiting output (max 1.0, 100%)
I also misunderstood your uart syntax.

You could try to get the values straight from the light component:

id(rgbw_led).current_values.get_red() * 1023;

Give id to your light though:

light:
  - platform: rgbw
    name: "Led"
    id: rgbw_led
...

I’ve managed to get the code working and I’ve attached a scrubbed version below to assist anyone else who needs to do something similar:

esphome:
  name: led
  friendly_name: Led

esp8266:
  board: esp01_1m

# Enable logging
logger:
  hardware_uart: UART1

# Enable Home Assistant API
api:
  encryption:
    key: "key removed to share"

ota:
  - platform: esphome
    password: "PW removed to share"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  # Optional manual IP
  manual_ip:
    static_ip: xxx.xx.xx.xx #ip address removed for sharing
    gateway: xxx.xx.xx.xx #ip address removed for sharing
    subnet: 255.255.255.0
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Led Fallback Hotspot"
    password: ""


uart:
  tx_pin: GPIO01
  rx_pin: GPIO03
  baud_rate: 115200

button:
  - platform: restart
    name: "Restart Device"
  - platform: template
    name: "Light Off"
    on_press:
      - uart.write: "AT-P#\r"
  - platform: template
    name: "Sun Rise"
    on_press:
      - uart.write: "AT-S#\r"
  - platform: template
    name: "Red Light"
    on_press:
      - uart.write: "AT-U#1023#0#0#0\r"
  - platform: template
    name: "Green Light"
    on_press:
      - uart.write: "AT-U#0#1023#0#0\r"
  - platform: template
    name: "Blue Light"
    on_press:
      - uart.write: "AT-U#0#0#1023#0\r"
  - platform: template
    name: "White Light"
    on_press:
      - uart.write: "AT-U#1023#1023#1023#1023\r"


captive_portal:

# Define global variables for RGBW values
globals:
  - id: red_value
    type: int
    initial_value: "0"
  - id: green_value
    type: int
    initial_value: "0"
  - id: blue_value
    type: int
    initial_value: "0"
  - id: white_value
    type: int
    initial_value: "0"

# Function to send the formatted string via UART that only updates every 4th time as the outputs are all updated at the same time therefore the function is called 4 times. 
script:
  - id: send_uart_data
    then:
      - lambda: |-
          static int update_counter = 0;
          char red_str[5], green_str[5], blue_str[5], white_str[5];  
          update_counter++;
          if (update_counter >= 4) 
          {
            snprintf(red_str, sizeof(red_str), "%d", id(red_value));
            snprintf(green_str, sizeof(green_str), "%d", id(green_value));
            snprintf(blue_str, sizeof(blue_str), "%d", id(blue_value));
            snprintf(white_str, sizeof(white_str), "%d", id(white_value));
            std::string message = std::string("AT-U#") + red_str + "#" + green_str + "#" + blue_str + "#" + white_str +"\r";
            Serial.print(message.c_str());
            update_counter = 0;
          }


# Template Light as a virtual RGBW light
light:
  - platform: rgbw
    name: "RGBW Light"
    red: output_red
    green: output_green
    blue: output_blue
    white: output_white
    default_transition_length: 1s

      
#    color_interlock: True

output:
  - platform: template
    id: output_red
    type: float
    zero_means_zero: True
    max_power: 1
    write_action:
      - lambda: |-
          id(red_value) = int(state * 1023);
          id(send_uart_data).execute(); 

  - platform: template
    id: output_green
    type: float
    zero_means_zero: True
    max_power: 1
    write_action:
      - lambda: |-
          id(green_value) = int(state * 1023);
          id(send_uart_data).execute(); 

  - platform: template
    id: output_blue
    type: float
    zero_means_zero: True
    max_power: 1
    write_action:
      - lambda: |-
          id(blue_value) = int(state * 1023);
          id(send_uart_data).execute();

  - platform: template
    id: output_white
    type: float
    zero_means_zero: True
    max_power: 1
    write_action:
      - lambda: |-
          id(white_value) = int(state * 1023);
          id(send_uart_data).execute();