Is A4988 Stepper Motor Driver Shield Compatible with Home Assistant (ESPHome)?
Electrical Specifications
Always confirm pin assignments against the manufacturer datasheet before wiring.
Compatibility Overview
Microstepping stepper motor driver for automated window blinds 3D printers and motorized camera sliders.
Wiring A4988 Stepper Motor Driver Shield to ESP32
| Module pin | ESP32 | Note |
|---|---|---|
| STEP | GPIO16 | Free on the WROOM-32 module of an esp32dev board. On a WROVER module GPIO16 and GPIO17 are taken by the PSRAM, so move STEP and DIR elsewhere. |
| DIR | GPIO17 | To reverse the motor, set inverted: true on dir_pin instead of rewiring. |
| ENABLE | GPIO18 | Active low: low turns the outputs on. The config sets inverted: true on this pin, which is correct for ENABLE and wrong for SLEEP (see the first gotcha). |
| SLEEP / RESET | bridged to each other | RESET floats on Pololu's carrier, and Pololu suggests joining it to the neighbouring SLEEP pin, which holds both high. |
| MS1 / MS2 / MS3 | unconnected | Pulled down inside the A4988 (100kΩ on MS1 and MS3, 50kΩ on MS2). All three low means full steps, the 200 steps per revolution the button assumes. |
| VDD | 3V3 | The logic supply, 3–5.5V. The A4988 reads a high at 70% of VDD, which is 3.5V on a 5V supply and more than an ESP32 pin gives, so power the logic from 3V3. |
| GND (logic) | GND | |
| VMOT | external 12V supply | 8–35V. Pololu asks for an electrolytic capacitor of at least 47µF across VMOT and GND, close to the board, to absorb voltage spikes. |
| GND (motor) | supply GND | Joined to the ESP32's ground as well. |
| 1A / 1B | motor coil A | One coil. To find the pairs, measure with a multimeter: the two ends of one coil read a few ohms, and wires from different coils read open circuit. |
| 2A / 2B | motor coil B |
Host pins are the ones the configuration on this page uses. Move a pin here and change it in the YAML — they are documented together so they cannot disagree.
Technical Specification Matrix
| Feature / Attribute | Specification / Status |
|---|---|
| Hardware Protocol | Step/Dir GPIO / 5V-12V |
| Bridge Required | NO |
| Border Router Needed | None |
| Hardware Capabilities & Peripherals | Turn One Revolution (button) Note: these entities come from the ESPHome configuration you flash — each one needs its matching component in that YAML before it appears. |
| Pairing Complexity | Intermediate |
| Factory Reset Instruction | Hold BOOT button for 3s. |
Wire, Flash, Adopt, Check
Wire it up
Follow the wiring table above. The ESP32 pins there are the ones the configuration uses, so if you move one, change it in both places.
Flash the configuration
Create a new device in the ESPHome dashboard (the Home Assistant add-on) and paste the configuration below into it, or save it as emb_esp32_stepper_a4988.yaml and run esphome run emb_esp32_stepper_a4988.yaml. The first flash goes over USB. If it is not detected, hold BOOT button for 3s to put it in download mode. Every update after that is over the air.
Adopt it in Home Assistant
Settings → Devices & Services. A node on the same network shows up as a discovered ESPHome device within a minute of joining Wi-Fi; choose Configure and enter the API encryption key from your secrets.yaml. If discovery does not find it, add the ESPHome integration by hand with the node's IP address.
Check it works
After boot the driver outputs are off and the shaft turns freely by hand. Press Turn One Revolution: the shaft locks, turns one full revolution with a gentle start and stop, then goes free again. A shaft that stays stiff at rest and goes limp when the button is pressed means the pin is on SLEEP rather than ENABLE. One that locks but never turns points to the STEP or DIR wiring. A motor that buzzes and shakes in place has its coil pairs split across 1A/1B and 2A/2B. If it turns only a sixteenth of a revolution, check the microstep pins; if it starts stuttering as it warms up, check the current limit.
ESPHome Configuration
Starting configuration for A4988 Stepper Motor Driver Shield on ESP32. Untested on hardware — verify wiring and pins against your own board.
# ESPHome configuration for A4988 Stepper Motor Driver Shield
# Host: ESP32. Pin numbers below are host-side defaults — any free
# GPIO will do, and you should change them to match your own wiring.
esphome:
name: emb_esp32_stepper_a4988
friendly_name: "A4988 Stepper Motor Driver Shield"
esp32:
board: esp32dev
framework:
type: esp-idf
logger:
api:
encryption:
key: !secret api_encryption_key
ota:
- platform: esphome
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Wire GPIO18 to the driver's ENABLE pin. ENABLE is active-low (low turns
# the outputs on), hence inverted: true. The component switches it off once
# the target is reached, so the motor has no holding torque at rest. Bridge
# SLEEP to RESET. On SLEEP (high runs) this pin would have to lose the
# inversion, or the driver sleeps exactly while the steps are sent.
# Set the current-limit pot before the first move — the default on most
# boards will overheat a small motor.
stepper:
- platform: a4988
id: motor
step_pin: GPIO16
dir_pin: GPIO17
sleep_pin:
number: GPIO18
inverted: true
max_speed: 250 steps/s
acceleration: 500
deceleration: 500
# One revolution of a 200-step motor at full steps.
button:
- platform: template
name: "Turn One Revolution"
on_press:
then:
- stepper.set_target:
id: motor
target: !lambda 'return id(motor).current_position + 200;'
Before you flash:
the !secret values come from your
secrets.yaml, and the GPIO numbers are host-side
defaults rather than properties of this part — change them to match how you actually wired it.
What Appears in Home Assistant
Sets the target 200 steps past wherever the shaft is at that moment: one turn of a 1.8° motor at full steps. Pressed mid-move, it counts from the current position, not from the old target.
stepper: exposes nothing, not even its position. A template number whose set_action calls stepper.set_target gives Home Assistant a position slider, and a template sensor that returns id(motor).current_position reports where the motor is. Both are optional additions and not in the config.
Known Problems and Fixes
ENABLE or SLEEP: mind the polarity
The a4988 component drives sleep_pin high while the motor moves and low once it reaches the target. That matches the A4988's SLEEP input as it stands, since high runs and low sleeps. ENABLE works the other way, with low turning the outputs on, so it needs inverted: true, which is what the config has. Put an inverted pin on SLEEP and the driver sleeps exactly while the steps are sent: the position count goes up and the shaft does not turn.
Set the current limit before the first move
The trimmer sets the coil current limit to VREF / (8 × Rs), where Rs is the value of the current-sense resistors. Pololu's carriers use 0.068Ω, or 0.050Ω on boards made before 2017; a board from another maker may use a different value, so read the resistors before borrowing someone else's VREF. Measure VREF between the trimmer and GND and set it for the motor's rated current.
About 1A without a heatsink
The A4988 is rated for 2A per coil, but Pololu puts the practical figure at about 1A per phase without a heatsink or airflow. Beyond that, the thermal shutdown turns the outputs off until the chip cools, and the motor stops or loses steps.
Do not unplug the motor with power on
Pololu warns that connecting or disconnecting a stepper while the driver is powered can destroy the driver. Turn off VMOT before touching the motor connector, and use a connector that cannot shake loose.
The position is a count, not a measurement
The component counts the steps it sends. At boot the position is 0 wherever the shaft happens to be, and a step lost under load is never noticed. For blinds or a slider, add an end-stop switch and a homing routine that drives towards it, then calls stepper.report_position with 0.
Microstep jumpers change the arithmetic
With MS1–MS3 unconnected the driver takes full steps, and 200 steps is one turn. Boards and CNC shields with microstep jumpers fitted multiply that: all three high selects sixteenth steps, where the button's 200 steps is a sixteenth of a turn and max_speed: 250 steps/s is under five revolutions a minute.
The motor goes limp when it stops
Because the pin switches the outputs off once the target is reached, the motor has no holding torque at rest. That keeps it cool, but a load that can turn the motor backwards will creep, such as a vertical slider or a blind on a spring. To keep the coils powered, tie ENABLE to GND, remove sleep_pin from the YAML, and allow for the heat.
Report a Pinout Error or Submit Tested Code Snippets
Found a pin mapping quirk or built a custom ESPHome YAML driver for A4988 Stepper Motor Driver Shield? Submit a pull request or report corrections to our index.
Hardware Correction Reporter (emb-esp32-stepper-a4988)
Frequently Asked Questions
Does A4988 Stepper Motor Driver Shield work without an internet connection?
How is A4988 Stepper Motor Driver Shield powered and wired to the host board?
How does the host board reach Home Assistant (ESPHome)?
Alternatives
SG90 Micro Servo Motor Module
A servo holds an angle across about 180° with no driver board and no homing, which suits a latch or a feeder flap.
L9110S Dual DC Motor Driver
A DC motor driver, for things that only need to spin either way at a set speed, with no position to track.
AS5600 12-bit Magnetic Rotary Encoder
A magnetic angle sensor on the output shaft turns the step count into a measured angle and catches lost steps.