Intro

If you’ve been fiddling with ESPs, you’ve probably been playing with LED strips as well.

If so, I can heavily recommend WLED combined with Quindor’s boards.
WLED is an awesome piece of software which allows you to control a wide variety of LED strips, including a wide range of effects.
The QuinLED boards have everything you need to safely install your strips, like power protection for the ESP board, fuses and practical terminals.

You may also know that digitally adressable LED strips still consume some power while they’re turned off (their colour set to black).

And while WLED gives you to option to control an external relays to cut the power to your strips, I decided to go the DIY route and build something myself using the ESPHome software and a relays board.

Parts needed (shopping list)

Depending on how much you adapt this design to your needs, you’ll need to following items:

Obviously an ESP32 board, a relays board (I’m using a 2-channel 5V board), and LED strips. The motion sensors are a nice-to-have feature.
I’d also advise getting some aluminium channel to mount the strips in and to help cool the LEDs.

Optionally, you can add a capacitor for smoothing any power spikes, some [terminals][terminal] to make connecting wires easier, header pins for mounting the ESP, and a perfboard to install everything together.
Also useful are adhesive cable ties and these Wago knockoffs for cable management, and double-sided tape to mount everything.
Finally, some lengths of nicely coloured 18 AWG wire or red-black wire, and a 5V power supply sized according to your LED strip installation will be quite useful as well.

To put everything together, I also designed a small 3D printable box. The design isn’t perfect however, I’ve had to enlarge some holes and the margins for the posts are quite tight.
The print consists of 3 parts: the main chassis, the mount for the relay board, and the mount for the perfboard with the ESP32.
I also have a 3D printed housing for the motion sensor.

Wiring it all together

For the wiring we need to take into account the following:

  • Power
    • The ESP32 needs 5V power
    • The relays board needs 5V power
    • The LEDs need 5V power
    • The motion sensors need 3.3V power
    • Power for the LEDs needs to go through the relays, so we can turn them on/off
    • We do not want to run the 5V/GND from the LED strip through the board, otherwise we’ll fry it
  • Connections
    • The relays board needs a signal for each channel you want to control
    • Each motion sensor gives an input to the ESP32
    • The LED strip has a data input
Wiring diagram
Wiring diagram

Coding

ESPHome

Now the last thing we need is the ESPHome code to make this all function.

Note that I’m using 2 motion sensors and am controlling 2 LED strips (+ respective relays channels).

substitutions:
  # These substitions combined with the 'common' dir are based on Frenck's ESPHome setup
  # https://github.com/frenck/home-assistant-config/tree/master/esphome/common
  slug: esp32-ledstrip-relays
  name: ESP32 LEDstrip with relays
  description: LEDstrips attached to relays to reducde power consumption
  room: Bedroom

packages:
  <<: !include_dir_named common # Contains WiFi settings, API, OTA, restart button, time settings
  board: !include boards/esp32_doit-dev1.yaml # Note: the definition of boards has changed

status_led:
  pin: GPIO2

switch:
  - platform: gpio
    name: "${name} - Onboard LED"
    pin: GPIO2
    inverted: False
  - platform: gpio
    name: "${room} Relay 1"
    pin: GPIO21
    inverted: true
    restore_mode: ALWAYS_OFF
    id: mbr_relay_1
  - platform: gpio
    name: "${room} Relay 2"
    pin: GPIO22
    inverted: true
    restore_mode: ALWAYS_OFF
    id: mbr_relay_2

binary_sensor:
  - platform: gpio
    pin: GPIO32
    name: "${room} PIR 1"
    device_class: motion
    id: mbr_pir_1
  - platform: gpio
    pin: GPIO25
    name: "${room} PIR 2"
    device_class: motion
    id: mbr_pir_2

light:
  - platform: fastled_clockless
    chipset: WS2812B
    pin: GPIO27
    num_leds: 30
    rgb_order: GRB
    name: "${room} LED 1"
    id: mbr_led_1
    <<: !include components/light_effects.yaml
  - platform: fastled_clockless
    chipset: WS2812B
    pin: GPIO12
    num_leds: 30
    rgb_order: GRB
    name: "${room} LED 2"
    id: mbr_led_2
    <<: !include components/light_effects.yaml

You’ll notice I grouped the light effects in a single file so I don’t have to repeat this for every LEDstrip I setup. Here’s the contents of that file:

---
# ESPHome Light Effects
# https://esphome.io/components/light/index.html#light-effects
#
effects:
  - addressable_color_wipe:
      name: Police Wipe
      colors:
        - red: 100%
          green: 0%
          blue: 0%
          num_leds: 10
        - red: 0%
          green: 0%
          blue: 100%
          num_leds: 10
      add_led_interval: 100ms
      reverse: false
  - strobe:
      name: Police Strobe
      colors:
        - state: true
          brightness: 100%
          red: 100%
          green: 0%
          blue: 0%
          duration: 500ms
        - state: false
          duration: 100ms
        - state: true
          brightness: 100%
          red: 0%
          green: 0%
          blue: 100%
          duration: 500ms
        - state: false
          duration: 100ms
  - addressable_rainbow:
  - addressable_fireworks:
  - addressable_random_twinkle:

Home Assistant

I’ve actually programmed my triggers for turning the LEDs on and off in Node-RED, but this is fairly easy to do with Home Assistant Automations as well.

We want to turn on the LED when motion is detected. To do this, we also need to turn on the relays. As long as motion is detected, the LED stays on. If no motion is detected, we wait a bit longer and then turn off the LED strip and the relays.

alias: Motion automated lights (LED1)
description: >-
  Turn on LED1 when PIR1 is trigged. Turn off when there's been no motion for 10
  seconds.  
mode: restart
trigger:
  - platform: state
    entity_id:
      - binary_sensor.mbr_pir_1
    to: 'on'
condition: []
action:
  - service: switch.turn_on
    data: {}
    target:
      entity_id: switch.mbr_relay_1
  - service: light.turn_on
    data:
      transition: 2
      color_name: blue
      brightness_pct: 50
    target:
      entity_id: light.mbr_led_1
  - wait_for_trigger:
      - platform: state
        entity_id:
          - binary_sensor.mbr_pir_1
        to: 'off'
        for:
          hours: 0
          minutes: 0
          seconds: 10
  - service: light.turn_off
    data:
      transition: 2
    target:
      entity_id: light.mbr_led_1
  - delay:
      hours: 0
      minutes: 0
      seconds: 3
      milliseconds: 0
  - service: switch.turn_off
    data: {}
    target:
      entity_id: switch.mbr_relay_1

Copy and modify this automation for each PIR-LED-relay combination you have. You could probably turn this into a blueprint as well.

[TODO] Add pictures of my setup. I’ll add these one day, promise!