Complete Guide to Motor Automation with ESPHome
Automating motors opens up a world of possibilities: motorized blinds that close at sunset, curtains that open with your morning alarm, garage doors controlled by voice, and ventilation systems that respond to air quality. In this comprehensive guide, we'll explore how to build reliable motor automation using ESPHome firmware.
What is ESPHome?
ESPHome is open-source firmware for ESP8266 and ESP32 microcontrollers that makes IoT device creation incredibly simple. Instead of writing C++ code, you define device behavior in YAML configuration files.
Why ESPHome for Motor Control?
- Native Home Assistant integration - Devices appear instantly
- Over-the-air updates - No cables needed for firmware updates
- Built-in safety features - Timeouts, limits, and error handling
- Community support - Thousands of example configurations
- Cost-effective - ESP32 boards cost ₹300-500
- Reliable - Battle-tested in thousands of installations
Understanding Motor Control Basics
Types of Motors
DC Brushed Motors (12-24V)
- Most common for blinds and curtains
- Simple forward/reverse control
- PWM speed control
- Typical current: 0.5-3A
Stepper Motors
- Precise position control
- No feedback sensors needed
- More complex but very accurate
- Higher power requirements
AC Motors (110-240V)
- Used in garage doors, large blinds
- Require relay control
- More dangerous - professional installation recommended
This guide focuses on DC brushed motors which are safe, affordable, and perfect for most automation projects.
Motor Driver Basics
DC motors need a motor driver (H-bridge) to control direction and speed:
ESP32 ────> Motor Driver ────> Motor
(PWM signals) (Power)
Common motor drivers:
- L298N - 2A per channel, affordable (₹150)
- TB6612 - 1.2A per channel, compact
- BTS7960 - 43A, for heavy motors
The L298N is perfect for most home automation projects and is what MotorWala uses.
The MotorWala Hardware
MotorWala combines an ESP32 microcontroller with an L298N motor driver, designed specifically for blind/curtain automation:
Hardware Specifications
- Microcontroller: ESP32-WROOM-32 (dual-core 240MHz)
- Motor Driver: L298N Dual H-Bridge
- Input Voltage: 12-24V DC
- Motor Current: 2A continuous, 3A peak
- PWM Frequency: 1000 Hz
- Position Sensing: Dual limit switches (GPIO32, GPIO33)
- Current Monitoring: ADC on GPIO34
- Communication: WiFi, Home Assistant API, MQTT, HTTP
Connection Diagram
┌──────────────────────────────────────┐
│ MotorWala Board │
│ │
│ Power Input: │
│ +12-24V ──┐ │
│ GND ──────┤ │
│ │ │
│ Motor Output: │
│ M+ ───────┤ │
│ M- ───────┤ │
│ │ │
│ Limit Switches (optional): │
│ Upper ────┤ GPIO32 │
│ Lower ────┤ GPIO33 │
│ │ │
│ Current Sensor: │
│ ADC ──────┤ GPIO34 │
└──────────────────────────────────────┘
Basic ESPHome Configuration
Let's start with a minimal configuration to get a motor running:
Minimal Config
esphome:
name: my-first-motor
friendly_name: Bedroom Blinds
platform: ESP32
board: esp32dev
# WiFi connection
wifi:
ssid: "YourWiFiNetwork"
password: "YourPassword"
# Fallback hotspot if WiFi fails
ap:
ssid: "Motor Fallback"
password: "setup12345"
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "YOUR_32_BYTE_ENCRYPTION_KEY_HERE="
# Enable OTA updates
ota:
password: "yourOTApassword"
# Motor driver outputs
output:
# Forward direction
- platform: ledc
pin: GPIO25
id: motor_forward
frequency: 1000 Hz
# Backward direction
- platform: ledc
pin: GPIO26
id: motor_backward
frequency: 1000 Hz
# Cover entity
cover:
- platform: time_based
name: "Bedroom Blinds"
id: blinds
# Actions to open
open_action:
- output.set_level:
id: motor_forward
level: 100%
- output.set_level:
id: motor_backward
level: 0%
# Actions to close
close_action:
- output.set_level:
id: motor_forward
level: 0%
- output.set_level:
id: motor_backward
level: 100%
# Actions to stop
stop_action:
- output.set_level:
id: motor_forward
level: 0%
- output.set_level:
id: motor_backward
level: 0%
# How long it takes to fully open/close
open_duration: 30s
close_duration: 30s
This basic configuration gives you:
- WiFi connectivity with fallback AP
- Home Assistant integration
- Open, close, and stop commands
- Position estimation based on time
Using Secrets File
Never hardcode passwords! Create a secrets.yaml file:
# secrets.yaml
wifi_ssid: "YourActualNetworkName"
wifi_password: "YourActualPassword"
api_encryption_key: "base64encodedkey32byteslong=="
ota_password: "changeThisPassword"
Then reference in main config:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
encryption:
key: !secret api_encryption_key
Adding Limit Switches
Limit switches prevent the motor from running past its travel limits:
binary_sensor:
# Upper limit (fully open)
- platform: gpio
pin:
number: GPIO32
mode: INPUT_PULLUP
inverted: true
name: "Upper Limit"
id: upper_limit
on_press:
then:
- cover.stop: blinds
- logger.log: "Upper limit reached"
# Lower limit (fully closed)
- platform: gpio
pin:
number: GPIO33
mode: INPUT_PULLUP
inverted: true
name: "Lower Limit"
id: lower_limit
on_press:
then:
- cover.stop: blinds
- logger.log: "Lower limit reached"
How it works:
- Limit switches are normally open (NO)
- When pressed (blind reaches end), they close
- ESPHome detects press and stops motor
- Prevents mechanical damage
Wiring limit switches:
Limit Switch ──┬── GPIO pin
└── GND
Overcurrent Protection
Motors can draw excessive current if jammed or stalled. Protect them with current monitoring:
sensor:
- platform: adc
pin: GPIO34
name: "Motor Current"
id: motor_current
update_interval: 100ms
# Convert ADC reading to amperes
filters:
- multiply: 3.3 # ADC voltage
- calibrate_linear:
- 0.0 -> 0.0
- 3.3 -> 5.0 # Max current in amps
# Alert on high current
on_value_range:
# If current exceeds 2.5A
- above: 2.5
then:
# Stop motor immediately
- cover.stop: blinds
# Log warning
- logger.log:
format: "OVERCURRENT! Motor stopped at %.2fA"
args: ['x']
level: WARN
# Optional: send notification
- homeassistant.event:
event: esphome.motor_overcurrent
data:
device: "blinds"
current: !lambda 'return x;'
Why overcurrent protection matters:
- Prevents motor burnout
- Detects mechanical jams
- Saves expensive motors
- Fire safety
Typical current values:
- Normal operation: 0.5-1.5A
- Starting surge: 2-3A (brief)
- Jam/stall: >3A (dangerous!)
Advanced Speed Control
Control motor speed for quieter operation or energy savings:
output:
- platform: ledc
pin: GPIO25
id: motor_forward
frequency: 1000 Hz
- platform: ledc
pin: GPIO26
id: motor_backward
frequency: 1000 Hz
# Number component for speed adjustment
number:
- platform: template
name: "Motor Speed"
id: motor_speed
min_value: 30
max_value: 100
step: 10
initial_value: 80
optimistic: true
unit_of_measurement: "%"
icon: "mdi:speedometer"
cover:
- platform: time_based
name: "Bedroom Blinds"
id: blinds
open_action:
# Use variable speed
- output.set_level:
id: motor_forward
level: !lambda 'return id(motor_speed).state / 100.0;'
- output.set_level:
id: motor_backward
level: 0%
close_action:
- output.set_level:
id: motor_forward
level: 0%
- output.set_level:
id: motor_backward
level: !lambda 'return id(motor_speed).state / 100.0;'
Now you can adjust speed from Home Assistant:
- 30% - Very quiet, slow
- 50% - Quiet, moderate speed
- 80% - Default, good balance
- 100% - Maximum speed, louder
Soft Start/Stop
Prevent jerky motion with gradual acceleration:
cover:
- platform: time_based
name: "Bedroom Blinds"
id: blinds
open_action:
# Start slowly
- output.set_level:
id: motor_forward
level: 30%
- delay: 500ms
# Ramp up to full speed
- output.set_level:
id: motor_forward
level: 100%
stop_action:
# Slow down before stopping
- output.set_level:
id: motor_forward
level: 30%
- output.set_level:
id: motor_backward
level: 30%
- delay: 300ms
# Full stop
- output.turn_off: motor_forward
- output.turn_off: motor_backward
Benefits:
- Smoother operation
- Less wear on mechanics
- Quieter
- More elegant
Position Calibration
For accurate position tracking, calibrate your motor:
button:
- platform: template
name: "Calibrate Motor"
id: calibrate_button
on_press:
- logger.log: "Starting calibration..."
# Fully close
- cover.close: blinds
- wait_until:
binary_sensor.is_on: lower_limit
- delay: 500ms
# Fully open and time it
- globals.set:
id: calibration_start
value: !lambda 'return millis();'
- cover.open: blinds
- wait_until:
binary_sensor.is_on: upper_limit
- lambda: |-
uint32_t duration = millis() - id(calibration_start);
id(open_duration_ms) = duration;
id(close_duration_ms) = duration;
ESP_LOGI("calibration", "Travel time: %d ms", duration);
- logger.log: "Calibration complete!"
globals:
- id: calibration_start
type: uint32_t
- id: open_duration_ms
type: uint32_t
initial_value: '30000'
- id: close_duration_ms
type: uint32_t
initial_value: '30000'
Run calibration after installation for accurate position tracking.
Common Use Cases
Automated Morning Routine
# In Home Assistant automations.yaml
automation:
- alias: "Wake Up - Open Blinds"
trigger:
- platform: time
at: "07:00:00"
condition:
- condition: state
entity_id: person.you
state: "home"
- condition: state
entity_id: binary_sensor.workday
state: "on"
action:
- service: cover.set_cover_position
target:
entity_id: cover.bedroom_blinds
data:
position: 50 # Partial open for gentle wake
- delay: 00:10:00
- service: cover.open_cover
target:
entity_id: cover.bedroom_blinds # Fully open
Sun-Responsive Blinds
automation:
- alias: "Close Blinds on Hot Afternoon"
trigger:
- platform: numeric_state
entity_id: sensor.outdoor_temperature
above: 35
- platform: sun
event: sunrise
offset: "+03:00:00"
condition:
- condition: time
after: "12:00:00"
before: "18:00:00"
action:
- service: cover.close_cover
target:
entity_id: cover.south_facing_blinds
Energy Saving
automation:
- alias: "Winter - Open Blinds for Solar Heating"
trigger:
- platform: sun
event: sunrise
offset: "+01:00:00"
condition:
- condition: numeric_state
entity_id: sensor.outdoor_temperature
below: 15
- condition: template
value_template: "{{ now().month in [11, 12, 1, 2] }}"
action:
- service: cover.open_cover
target:
entity_id: cover.living_room_blinds
Safety Considerations
Electrical Safety
-
Use proper power supply
- 12V 5A or 24V 3A minimum
- Regulated DC supply only
- Fused on input side
-
Wire gauge matters
- Motor wires: 18 AWG (1.0mm²) minimum
- Power supply: 16 AWG (1.5mm²) recommended
- Undersized wires = heat and fire risk
-
Secure connections
- Use terminal blocks, not tape
- Double-check polarity
- Strain relief on moving parts
Mechanical Safety
-
Install safety limits
- Mechanical stops prevent overtravel
- Limit switches as backup
- Test before connecting to Home Assistant
-
Emergency stop
- Physical switch to cut power
- Accessible in emergencies
- Test regularly
-
Child safety
- Secure cords away from reach
- Consider cordless motors
- Soft-start reduces pinch risk
Software Safety
# Watchdog timer
interval:
- interval: 60s
then:
- if:
condition:
# If motor has been running >60 seconds
lambda: 'return id(blinds).current_operation != COVER_OPERATION_IDLE;'
then:
- logger.log:
level: ERROR
format: "Motor running too long! Emergency stop."
- cover.stop: blinds
# Timeout protection
cover:
- platform: time_based
name: "Bedroom Blinds"
id: blinds
open_duration: 30s
close_duration: 30s
# Built-in timeout (130% of expected time)
# Automatically stops if takes too long
Troubleshooting
Motor Doesn't Move
Check:
- Power supply voltage (12-24V)
- Motor connections (M+, M-)
- Driver board has power LED on
- Try direct power to motor (test if motor works)
- Check ESPHome logs for errors
Solutions:
# Add debug logging
logger:
level: DEBUG
logs:
cover: DEBUG
output: DEBUG
Motor Runs Backward
Quick fix: Swap M+ and M- wires
Or in software:
cover:
- platform: time_based
name: "Bedroom Blinds"
# Swap open/close actions
open_action:
- output.set_level:
id: motor_backward # Changed from motor_forward
level: 100%
Position Tracking Inaccurate
Causes:
- Mechanical slippage
- Variable load
- Incorrect timing
Solution: Use limit switches for absolute positioning:
cover:
- platform: endstop
name: "Bedroom Blinds"
open_action:
- output.turn_on: motor_forward
open_duration: 32s
open_endstop: upper_limit
close_action:
- output.turn_on: motor_backward
close_duration: 32s
close_endstop: lower_limit
High Current Draw
Check:
- Motor rated voltage matches supply
- Mechanical binding/friction
- Motor bearings OK
- No load on motor (disconnect and test)
Monitor:
sensor:
- platform: adc
pin: GPIO34
name: "Motor Current"
on_value_range:
- above: 3.0
then:
- homeassistant.service:
service: notify.mobile_app
data:
message: "Motor current high: {{ x }}A"
Performance Optimization
Reduce WiFi Reconnects
wifi:
power_save_mode: none
fast_connect: true
reboot_timeout: 5min
Optimize Update Intervals
sensor:
- platform: adc
pin: GPIO34
name: "Motor Current"
# Don't update too frequently
update_interval: 100ms # Good
# update_interval: 10ms # Excessive!
Use Static IP
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.1.150
gateway: 192.168.1.1
subnet: 255.255.255.0
Going Further
Add Manual Controls
binary_sensor:
# Wall-mounted up button
- platform: gpio
pin:
number: GPIO18
mode: INPUT_PULLUP
inverted: true
name: "Manual Up Button"
on_press:
- cover.open: blinds
# Wall-mounted down button
- platform: gpio
pin:
number: GPIO19
mode: INPUT_PULLUP
inverted: true
name: "Manual Down Button"
on_press:
- cover.close: blinds
Multiple Motors
# Control 2 motors independently
output:
# Motor 1
- platform: ledc
pin: GPIO25
id: motor1_forward
- platform: ledc
pin: GPIO26
id: motor1_backward
# Motor 2
- platform: ledc
pin: GPIO27
id: motor2_forward
- platform: ledc
pin: GPIO14
id: motor2_backward
cover:
- platform: time_based
name: "Left Curtain"
open_action:
- output.turn_on: motor1_forward
# ... rest of config
- platform: time_based
name: "Right Curtain"
open_action:
- output.turn_on: motor2_forward
# ... rest of config
Synchronized Dual Motors
# For wide blinds with 2 motors
cover:
- platform: template
name: "Living Room Blinds"
id: dual_blinds
open_action:
- cover.open: left_motor
- cover.open: right_motor
close_action:
- cover.close: left_motor
- cover.close: right_motor
stop_action:
- cover.stop: left_motor
- cover.stop: right_motor
Conclusion
Motor automation with ESPHome is powerful, flexible, and accessible. With the configurations in this guide, you can:
- Build reliable automated blinds and curtains
- Implement comprehensive safety features
- Integrate seamlessly with Home Assistant
- Customize behavior to your exact needs
- Maintain and debug your system easily
The beauty of ESPHome is that it grows with your needs. Start simple, add features gradually, and enjoy the comfort of automated motor control.
Resources
- Full Configuration Examples: GitHub Repository
- MotorWala Product: Shop
- ESPHome Documentation: esphome.io
- Community Forum: forum.walaworks.com
- Video Tutorials: YouTube Channel
Have questions about motor automation? Reach out on our community forum or contact support.