Hardware Matrix

Is A4988 Stepper Motor Driver Shield Compatible with Home Assistant (ESPHome)?

Verdict Badge
VERDICT: [ COMPATIBLE (MANUAL CONFIG REQUIRED) ]
Protocol: Step/Dir GPIO / 5V-12V
Bridge Needed: NO

Electrical Specifications

Always confirm pin assignments against the manufacturer datasheet before wiring.

Not yet documented. Electrical specifications for this device have not been confirmed against a manufacturer datasheet, so none are shown here rather than showing estimates. Submit verified specifications if you have the datasheet to hand.

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

1

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.

2

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.

3

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.

4

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

Turn One Revolution
button

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
not an entity

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.

🛠️ Hardware Correction & Field Contributions

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.

Frequently Asked Questions

Does A4988 Stepper Motor Driver Shield work without an internet connection?
100% local step/dir pulse generation.
How is A4988 Stepper Motor Driver Shield powered and wired to the host board?
12V motor supply on VMOT; STEP=GPIO16 DIR=GPIO17 ENABLE=GPIO18; SLEEP bridged to RESET; logic VDD from 3.3V.
How does the host board reach Home Assistant (ESPHome)?
Wi-Fi 2.4GHz.

Alternatives

Guides for this part

Related Compatibility Matrix Guides