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.
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:
- Direct attachment (easiest but least reliable)
- 3D-printed custom connector (best option if you have access to a 3D printer)
- 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.”
Step 2: Wiring Everything Up
The wiring for this project is straightforward. Here’s how to connect the components:
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)
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