Chicken Coop Door — ESP32 + IBT-2 + ESPHome#
codex resume 01a00aab-e96d-7aa3-8a96-579fe3727d04
Overview#
This note documents the final working configuration for controlling the chicken coop door using:
- ESP32 development board
- ESP32 screw-terminal breakout board
- IBT-2 / BTS7960 H-bridge motor driver
- 14 V DC linear actuator
- 14 V DC power supply
- ESPHome
- Home Assistant
The ESP32 communicates with Home Assistant over Wi-Fi using ESPHome.
The IBT-2 controls the direction of the two-wire DC actuator by reversing the polarity applied to the actuator.
The final system provides three Home Assistant controls:
- Coop Door Open
- Coop Door Close
- Coop Door Stop
The ESP32 is powered separately through USB. The actuator receives its power from the 14 V supply through the IBT-2.
Hardware#
ESP32#
ESP32 development board installed in a screw-terminal breakout board.
Relevant terminals used:
| ESP32 | Purpose |
|---|---|
3V3 |
IBT-2 logic supply / R_EN |
GND |
Common logic ground |
D25 / GPIO25 |
IBT-2 RPWM |
D26 / GPIO26 |
IBT-2 LPWM |
D27 / GPIO27 |
IBT-2 L_EN |
The breakout provides more than one GND connection. They are electrically common, so either may be used.
IBT-2 / BTS7960 Motor Driver#
The control header on this particular board is labeled:
VCC
GND
R_IS
L_IS
R_EN
L_EN
RPWM
LPWMThe four large green power/motor terminals were identified from the markings on the reverse side of the actual board as:
B- B+ M+ M-Where:
| Terminal | Function |
|---|---|
B- |
14 V supply negative |
B+ |
14 V supply positive |
M+ |
Actuator lead |
M- |
Actuator lead |
Final Wiring#
ESP32 → IBT-2#
Final working control wiring:
| IBT-2 | ESP32 | Purpose |
|---|---|---|
VCC |
3V3 |
IBT-2 logic power |
GND |
GND |
Common logic ground |
RPWM |
D25 / GPIO25 |
Motor direction control |
LPWM |
D26 / GPIO26 |
Motor direction control |
R_EN |
3V3 |
Permanently enables one side of driver |
L_EN |
D27 / GPIO27 |
Enables other side under ESPHome control |
R_IS |
Not connected | Optional current-sense output |
L_IS |
Not connected | Optional current-sense output |
R_ISandL_ISare not required for basic actuator operation and are left disconnected.
Why R_EN and L_EN Are Different#
The final wiring uses:
R_EN → 3V3
L_EN → GPIO27R_EN is permanently held HIGH.
L_EN is controlled by ESPHome using GPIO27 and is turned HIGH during boot.
This avoids needing another physical connection to the ESP32’s 3V3 terminal while still enabling both sides of the motor driver.
Actuator → IBT-2#
The actuator has two wires:
- Pink
- Black
Final connection:
| Actuator | IBT-2 |
|---|---|
| Pink | M+ |
| Black | M- |
For a two-wire DC actuator, these wires are not permanently positive and negative.
The H-bridge reverses the polarity across M+ and M- to reverse the actuator direction.
Therefore:
one polarity → actuator extends
opposite polarity → actuator retractsThe physical pink/black assignment can therefore be reversed if necessary. In this installation, direction was corrected in ESPHome instead of rewiring the actuator.
14 V Power Supply → IBT-2#
The power supply also has:
- Pink wire
- Black wire
Unlike the actuator wires, polarity matters here.
Because the wires had no polarity markings, polarity was verified using a multimeter.
Measuring polarity#
Multimeter:
Mode: DC Voltage (V⎓)Measurement:
Red probe → Pink power-supply wire
Black probe → Black power-supply wire
Reading: +14.34 VBecause the reading was positive:
Pink = positive
Black = negativeFinal connection:
| Power supply | IBT-2 |
|---|---|
| Pink (+14.34 V) | B+ |
| Black (−) | B- |
Never determine DC supply polarity solely from wire color. Measure it if the cable is not explicitly marked.
Complete Wiring Summary#
ESP32 IBT-2
────────────────────────────────────
3V3 ──────────────────> VCC
GND ──────────────────> GND
GPIO25 / D25 ──────────> RPWM
GPIO26 / D26 ──────────> LPWM
3V3 ──────────────────> R_EN
GPIO27 / D27 ──────────> L_EN
R_IS [unused]
L_IS [unused]
14 V POWER SUPPLY IBT-2
────────────────────────────────────
Pink +14.34 V ─────────> B+
Black negative ─────────> B-
LINEAR ACTUATOR IBT-2
────────────────────────────────────
Pink ──────────────────> M+
Black ──────────────────> M-Power Architecture#
There are two separate power functions in the system.
ESP32 / logic power#
The ESP32 is powered through:
USB-CThe ESP32 then provides 3.3 V logic power to the IBT-2 control circuitry.
Motor power#
The actuator receives power from:
14 V DC power supply
↓
IBT-2
↓
linear actuatorThe 14 V supply does not power the ESP32 directly.
ESPHome Installation#
The ESP32 was initially flashed using ESPHome.
After the initial USB installation and successful Wi-Fi connection, subsequent firmware updates can be performed OTA:
ESPHome
→ Install
→ On the networkThe device was successfully assigned:
Hostname: coop-door
IP during setup: 10.1.3.70The IP address may change unless a DHCP reservation/static assignment is configured.
Successful ESPHome logs included:
Successfully connected to coop-door
Successful handshake with coop-door
WiFi:
Connected: YESand finally:
Boot seems successful; resetting boot loop counterFinal ESPHome Configuration#
The first motor test revealed that the logical Open and Close directions were reversed.
Rather than changing the physical motor wires, GPIO25 and GPIO26 were logically swapped in ESPHome.
Final configuration:
esphome:
name: coop-door
friendly_name: Coop Door
min_version: 2026.4.0
name_add_mac_suffix: false
on_boot:
priority: -100
then:
# Make absolutely sure the actuator is stopped at startup
- output.turn_off: motor_open
- output.turn_off: motor_close
# Enable the L side of the BTS7960
- output.turn_on: motor_enable
esp32:
variant: esp32
framework:
type: esp-idf
# Enable logging
logger:
# Enable Home Assistant API
api:
# Allow Over-The-Air updates
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# BTS7960 control outputs
output:
# LPWM -> GPIO26
# This is the physical direction that OPENS the door
- platform: gpio
pin: GPIO26
id: motor_open
# RPWM -> GPIO25
# This is the physical direction that CLOSES the door
- platform: gpio
pin: GPIO25
id: motor_close
# L_EN -> GPIO27
# R_EN is permanently enabled from 3V3
- platform: gpio
pin: GPIO27
id: motor_enable
# Motor control scripts
script:
- id: stop_motor
mode: restart
then:
- output.turn_off: motor_open
- output.turn_off: motor_close
- id: open_door
mode: restart
then:
# Stop before changing direction
- script.execute: stop_motor
- delay: 250ms
# Drive actuator in OPEN direction
- output.turn_on: motor_open
# Absolute safety timeout
- delay: 45s
- output.turn_off: motor_open
- id: close_door
mode: restart
then:
# Stop before changing direction
- script.execute: stop_motor
- delay: 250ms
# Drive actuator in CLOSE direction
- output.turn_on: motor_close
# Absolute safety timeout
- delay: 45s
- output.turn_off: motor_close
# Home Assistant controls
button:
- platform: template
name: "Coop Door Open"
icon: mdi:arrow-up-bold
on_press:
- script.stop: close_door
- script.execute: open_door
- platform: template
name: "Coop Door Close"
icon: mdi:arrow-down-bold
on_press:
- script.stop: open_door
- script.execute: close_door
- platform: template
name: "Coop Door Stop"
icon: mdi:stop
on_press:
- script.stop: open_door
- script.stop: close_door
- script.execute: stop_motorMotor Control Logic#
Open#
Home Assistant:
Coop Door Openexecutes:
Stop motor
↓
Wait 250 ms
↓
GPIO26 ON
↓
Actuator moves OPEN
↓
Maximum 45 seconds
↓
GPIO26 OFFClose#
Home Assistant:
Coop Door Closeexecutes:
Stop motor
↓
Wait 250 ms
↓
GPIO25 ON
↓
Actuator moves CLOSED
↓
Maximum 45 seconds
↓
GPIO25 OFFStop#
Home Assistant:
Coop Door Stopimmediately stops both motor-direction outputs:
GPIO25 OFF
GPIO26 OFFDirection Change Protection#
The configuration deliberately prevents immediate direction reversal.
Before either direction starts:
- script.execute: stop_motor
- delay: 250msThis means the driver is first commanded to stop and then waits 250 ms before energizing the opposite direction.
This reduces electrical and mechanical stress from instantly reversing a moving DC motor.
45-Second Safety Timeout#
Both movement scripts contain:
- delay: 45s
- output.turn_off: motor_openor:
- delay: 45s
- output.turn_off: motor_closeThis is an absolute runtime safety limit.
The motor cannot remain commanded indefinitely if Home Assistant loses communication or a command is accidentally issued.
The 45-second timer is currently a safety timeout, not position detection.
The system currently does not know whether the door is physically open or closed unless additional position sensors are added.
Home Assistant#
After ESPHome integration, Home Assistant exposes the device as:
Coop Door (ESP32)Controls:
↓ Coop Door Close Press
↑ Coop Door Open Press
■ Coop Door Stop PressThese appear under:
Settings
→ Devices & services
→ ESPHome
→ Coop Door (ESP32)They can also be added to a Home Assistant dashboard.
Initial Power-Up Procedure#
The system was tested conservatively in stages.
1. ESP32 only#
Power the ESP32 using USB.
Leave the 14 V motor supply disconnected.
Confirm:
ESPHome online
Wi-Fi connected
API connected
Firmware boot successful2. Apply motor power without commanding movement#
With the ESP32 already running:
Plug in 14 V supplyDo not press Open or Close.
Expected result:
Actuator does not moveThis test passed successfully.
3. Short movement test#
Because the door was already physically open, the first command used was:
Coop Door CloseThe motor successfully moved.
However, the physical movement was opposite to the original software definition.
This confirmed:
- ESP32 control worked
- IBT-2 worked
- actuator worked
- 14 V supply worked
- Home Assistant command path worked
The direction was then corrected in software by swapping the GPIO assignments for motor_open and motor_close.
Important Lessons / Troubleshooting#
IBT-2 green terminals#
The four green terminals are not control terminals.
They carry motor current and supply power:
B-
B+
M+
M-The small control header handles:
VCC
GND
R_IS
L_IS
R_EN
L_EN
RPWM
LPWMActuator wire colors do not define polarity#
For the two-wire actuator:
Pink
Blackdo not represent fixed positive and negative connections during operation.
The H-bridge intentionally reverses their polarity.
If the actuator moves in the wrong direction, either:
- swap
M+andM-, or - swap the logical Open/Close outputs in software.
This installation uses option 2.
Power-brick polarity DOES matter#
Unlike the motor wires:
B+ and B-must receive the correct supply polarity.
The power supply was measured at:
14.34 V DCwith:
Pink = +
Black = -ESPHome firmware direction versus physical wiring#
Physical wiring remains:
RPWM → GPIO25
LPWM → GPIO26But the final software defines:
motor_open → GPIO26
motor_close → GPIO25This is intentional because the initial movement test showed that the actuator’s physical direction was opposite the original assumption.
Current Limitations#
The current controller provides movement commands, not actual door-position feedback.
It currently does not independently know:
Door fully open
Door fully closed
Door partially open
Door obstructedThe 45-second timeout only prevents indefinite motor operation.
Potential future improvements include:
- Open-position limit sensor
- Closed-position limit sensor
- Door-state entity in Home Assistant
- Proper Home Assistant
coverentity - Obstruction/current detection
- Automatic sunrise opening
- Automatic sunset closing
- Notifications if the door fails to reach its expected position
- Manual override
- Watchdog/failsafe behavior
Final Verified State#
At the end of the initial hardware test:
- ESP32 flashed successfully
- ESP32 connected to Wi-Fi
- ESPHome API connected
- OTA updates working
- GPIO25 configured
- GPIO26 configured
- GPIO27 configured
- IBT-2 logic connected
- 14 V supply polarity measured
- 14 V supply connected to
B+ / B- - Actuator connected to
M+ / M- - Power-up produced no unintended motor movement
- Home Assistant controls appeared
- Motor responded to Home Assistant
- Stop control available
- Physical direction identified
- Open/Close direction corrected in ESPHome configuration
- 45-second safety timeout configured
Final Wiring Quick Reference#
┌─────────────────┐
│ ESP32 │
│ │
3V3 ───┼───────────────┐ │
GND ───┼─────────────┐ │ │
GPIO25 ───┼───────────┐ │ │ │
GPIO26 ───┼─────────┐ │ │ │ │
GPIO27 ───┼───────┐ │ │ │ │ │
└───────┼─┼─┼─┼─┼─┘
│ │ │ │ │
│ │ │ │ └── VCC
│ │ │ └──── R_EN
│ │ └────── GND
│ └──────── RPWM
└────────── LPWM / L_EN*More explicitly:
ESP32 3V3 → IBT-2 VCC
ESP32 GND → IBT-2 GND
ESP32 D25 → IBT-2 RPWM
ESP32 D26 → IBT-2 LPWM
ESP32 3V3 → IBT-2 R_EN
ESP32 D27 → IBT-2 L_EN
IBT-2 R_IS → unused
IBT-2 L_IS → unused
14 V Pink → IBT-2 B+
14 V Black → IBT-2 B-
Actuator Pink → IBT-2 M+
Actuator Black → IBT-2 M-The ASCII diagram above is illustrative. The explicit connection list immediately below it is the authoritative wiring reference.
Next Phase#
The basic motor controller is operational.
The logical next phase is to add door-position sensing so Home Assistant knows whether the coop door is actually:
OPEN
CLOSED
MOVING
UNKNOWNOnce position sensing is available, the three temporary push buttons can potentially be replaced by a proper Home Assistant Cover entity with Open / Close / Stop controls and real state feedback.
That should be completed before relying on unattended scheduled operation.