/ #smart home #home automation 

Automating Window Blinds with ESP32 Servo Motor and Home Assistant

I’ve always been fascinated with the idea of waking up to natural sunlight instead of a blaring alarm clock. But as someone who also values sleeping in on weekends, I needed a solution that could give me the best of both worlds. That’s when I decided to automate my window blinds with an ESP32 and servo motors, integrating everything seamlessly with Home Assistant.

After a few prototypes (and one slightly mangled blind slat), I’ve perfected a system that opens my blinds based on either time schedules or ambient light conditions. The best part? The whole setup cost me less than $30, and I can control everything through my existing Home Assistant dashboard.

Pro Tip: If you're new to ESP32 or Home Assistant, I recommend checking out my previous guide on ESP32 temperature monitoring first for some foundational knowledge.

What You’ll Need

Before we dive in, let’s gather our materials. Here’s everything I used for this project:

  • ESP32-DevKit board: Buy it here
  • Servo Motor: Buy it here
  • Light Sensor BH1750: Buy it here
  • Jumper wires (male-to-female and male-to-male) - Amazon link
  • USB power supply (5V, 2A recommended)
  • 3D-printed servo mounts (optional but highly recommended)
  • Small screws and mounting tape

Total cost: Approximately $25-35 depending on what you already have.

Step 1: Understanding the Mechanics

Before writing any code, we need to address the physical connection between the servo and your blinds. Most horizontal blinds have a twist rod that opens and closes them. Our goal is to attach the servo to this rod.

I tried three different methods:

  1. Direct attachment (easiest but least reliable)
  2. 3D-printed custom connector (best option if you have access to a 3D printer)
  3. Rubber coupling (works surprisingly well for temporary setups)

I ended up designing a simple 3D-printed connector that fits snugly over both the servo horn and the blind rod. You can find similar designs on Thingiverse or Printables if you search for “blind automation servo mount.”

Warning: Be gentle during initial testing! Servos have limited torque, and forcing them can strip their gears. Test the movement with your hand first to ensure there's not too much resistance.

Step 2: Wiring Everything Up

The wiring for this project is straightforward. Here’s how to connect the components:

  1. Servo Motor Connections:

    • Brown wire (Ground) → ESP32 GND pin
    • Red wire (Power) → ESP32 5V pin (or external 5V power)
    • Orange wire (Signal) → ESP32 GPIO pin (I used GPIO 13)
  2. BH1750 Light Sensor (if using):

    • VCC → ESP32 3.3V
    • GND → ESP32 GND
    • SCL → ESP32 GPIO 22
    • SDA → ESP32 GPIO 21

If you’re powering multiple servos or notice jittery movement, consider using an external 5V power supply for the servos with a common ground.

Step 3: ESPHome Configuration

Now for the software part. I’m using ESPHome because it integrates seamlessly with Home Assistant and eliminates the need for custom Arduino code.

Here’s my complete ESPHome YAML configuration:

substitutions:
  device_name: "living-room-blinds"
  friendly_name: "Living Room Blinds"

esphome:
  name: ${device_name}
  platform: ESP32
  board: nodemcu-32s

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

api:
ota:
logger:

web_server:
  port: 80

i2c:
  sda: 21
  scl: 22

sensor:
  - platform: bh1750
    name: "${friendly_name} Illuminance"
    address: 0x23
    update_interval: 60s

output:
  - platform: ledc
    pin: GPIO13
    id: servo_output
    frequency: 50Hz

cover:
  - platform: time_based
    name: "${friendly_name}"
    open_duration: 15s
    close_duration: 15s
    open_action:
      - output.set_level:
          id: servo_output
          level: 100%
    open_end_action:
      - output.set_level:
          id: servo_output
          level: 0%
    close_action:
      - output.set_level:
          id: servo_output
          level: 0%
    close_end_action:
      - output.set_level:
          id: servo_output
          level: 0%
    stop_action:
      - output.set_level:
          id: servo_output
          level: 0%

This configuration creates a cover entity in Home Assistant that can be controlled like any other blind or shade. The time_based platform allows us to specify how long it takes to open or close the blinds completely.

Step 4: Home Assistant Automation

Now for the fun part - creating automations! Here are two examples: one time-based and one light-based.

Time-based automation (opens blinds at sunrise, closes at sunset):

alias: "Blinds - Open at Sunrise"
description: ""
trigger:
  - platform: sun
    event: sunrise
    offset: "-00:30:00"
condition: []
action:
  - service: cover.open_cover
    target:
      entity_id: cover.living_room_blinds
mode: single

alias: "Blinds - Close at Sunset"
description: ""
trigger:
  - platform: sun
    event: sunset
    offset: "+00:30:00"
condition: []
action:
  - service: cover.close_cover
    target:
      entity_id: cover.living_room_blinds
mode: single

Light-based automation (closes blinds when it gets too bright):

alias: "Blinds - Close When Too Bright"
description: ""
trigger:
  - platform: numeric_state
    entity_id: sensor.living_room_blinds_illuminance
    above: 10000
condition:
  - condition: state
    entity_id: cover.living_room_blinds
    state: open
action:
  - service: cover.close_cover
    target:
      entity_id: cover.living_room_blinds
mode: single