# ESP32-Bit-Pirate Stepper Motor Example: Complete Guide to GPIO Control and Hardware Integration

> Control stepper motors with the ESP32-Bit-Pirate firmware. This guide shows GPIO control and hardware integration for precise pin sequencing in your projects.

- Repository: [Geo/ESP32-Bit-Pirate](https://github.com/geo-tp/ESP32-Bit-Pirate)
- Tags: example-project
- Published: 2026-08-02

---

**The ESP32-Bit-Pirate firmware transforms ESP32-S3 boards into multi-protocol development tools, controlling stepper motors through GPIO-based DIO commands with precise pin sequencing.**

The **ESP32-Bit-Pirate** repository (geo-tp/ESP32-Bit-Pirate) provides a production-ready demonstration of embedded hardware abstraction. This article walks through a practical stepper motor example, revealing how the firmware's **dependency-injection architecture** separates hardware services from controller logic—enabling the same CLI interface to drive motors, sniff buses, or scan wireless protocols.

## Boot Architecture and Hardware Initialization

Understanding the ESP32-Bit-Pirate's startup sequence clarifies how stepper motor control becomes available to users.

### Board Selection and Peripheral Setup

The `setup()` function in [`src/main.cpp`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/main.cpp) initiates hardware detection through conditional compilation. Each supported board (StickS3, Cardputer, T-Embed, etc.) exposes standardized interfaces for views, inputs, and serial communication:

```cpp
// src/main.cpp
#if defined(DEVICE_STICKS3)
    StickS3Board board;  // selects the hardware variant
    board.initialize();
    IDeviceView& deviceView = board.getDeviceView();
#endif

```

This abstraction allows identical stepper motor commands across physically different ESP32-S3 implementations.

### Terminal Configuration and Dependency Injection

After hardware selection, `TerminalTypeConfigurator` presents a `HorizontalSelector` for choosing **Serial**, **Web (Wi-Fi)**, or **Standalone** terminal modes. The selected configuration instantiates `DependencyProvider`:

```cpp
DependencyProvider* provider = new DependencyProvider(
    terminalView, deviceView,
    terminalInput, deviceInput,
    littleFsService);

```

All subsequent stepper motor commands route through this container's **DIO controller** and **Pin service**.

## Core Components for Stepper Control

The firmware's modularity centers on `DependencyProvider` ([`src/Providers/DependencyProvider.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Providers/DependencyProvider.h)), which coordinates eight component categories.

### Services and Controllers

| Component | Responsibility | Stepper Motor Relevance |
|-----------|--------------|------------------------|
| **Services** | Hardware-specific APIs (GPIO, UART, SPI, I²C) | `PinService` configures output pins |
| **Controllers** | Command logic implementation | `DioController` executes step sequences |
| **Transformers** | CLI input parsing | `TerminalCommandTransformer` parses `step 200` |
| **Shells** | Pre-built command collections | DIO shell groups motor commands |

All components expose getter methods—controller code retrieves `PinService` without direct instantiation, maintaining **loose coupling**.

### PinService and DioController Implementation

Stepper motor control flows through two primary files:

- **[`src/Services/PinService.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Services/PinService.h)** — Configures GPIO direction, pull-ups, and state
- **[`src/Controllers/DioController.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Controllers/DioController.h)** — Implements `step`, `setdir`, `setmode`, and stepping sequence generation

The `DioController` translates high-level step commands into timed pin toggles according to **full-step**, **half-step**, or **microstep** patterns.

## Stepper Motor Control: Practical Examples

These verified command sequences operate from Serial or Web terminals.

### Basic DIO Mode Setup

```text

# Enter DIO mode for GPIO control

mode dio

# Assign motor driver pins (A, B, C, D coils)

pinout set A 23 B 19 C 18 D 5

# Select stepping resolution

dio mode full

# Execute rotation

dio step 200

```

### Direction Control and Reversal

```text

# Change rotation direction

dio dir reverse

# Execute counter-clockwise rotation

dio step 200

```

The `pinout set` command persists until reset, allowing scriptable motor automation.

### Python Automation via Serial Interface

For programmatic control, the onboard **Python Lab** or external scripts leverage the same command protocol:

```python
import serial
import time

ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)

def send(cmd):
    ser.write((cmd + '\n').encode())
    time.sleep(0.1)
    response = ser.readline().decode().strip()
    print(response)
    return response

# Initialize motor control

send('mode dio')
send('pinout set A 23 B 19 C 18 D 5')
send('dio mode full')

# Perform synchronized movements

send('dio step 200')
time.sleep(1.0)
send('dio dir reverse')
send('dio step 200')

```

This script demonstrates how **ESP32-Bit-Pirate's** unified CLI enables rapid hardware prototyping without firmware recompilation.

## Multi-Protocol Flexibility

The same architectural pattern supporting stepper motors extends across **15+ protocols**:

- **Wired buses**: I²C, SPI, UART, 1-Wire, 2-Wire, 3-Wire, CAN
- **Wireless**: Bluetooth, Wi-Fi, Sub-GHz, RFID, RF24, Infrared

Switching from motor control to **I²C bus sniffing** requires only a mode change—`mode i2c`—because each protocol implements identical service/controller contracts within `DependencyProvider`.

## Key Source Files

| File Path | Purpose |
|-----------|---------|
| [`src/main.cpp`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/main.cpp) | Boot sequence, board selection, terminal initialization |
| [`src/Providers/DependencyProvider.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Providers/DependencyProvider.h) | Service locator for all hardware abstractions |
| [`src/Controllers/DioController.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Controllers/DioController.h) | Stepper motor command implementation |
| [`src/Services/PinService.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Services/PinService.h) | GPIO configuration and manipulation |
| [`src/Views/SerialTerminalView.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Views/SerialTerminalView.h) | UART CLI rendering |
| [`src/Views/WebTerminalView.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Views/WebTerminalView.h) | WebSocket-based browser terminal |
| [`src/Dispatchers/ActionDispatcher.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Dispatchers/ActionDispatcher.h) | Main loop routing user input to controllers |
| [`src/Configurators/TerminalTypeConfigurator.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Configurators/TerminalTypeConfigurator.h) | Terminal mode selection wizard |
| [`src/Services/LittleFsService.h`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/Services/LittleFsService.h) | Filesystem access for automation scripts |

## Summary

- **ESP32-Bit-Pirate** implements stepper motor control through layered abstractions: `DependencyProvider` → `DioController` → `PinService`.
- **GPIO pin assignment** uses flexible `pinout set` commands—no firmware rebuild required for wiring changes.
- **Three stepping modes** (full, half, micro) accommodate different torque and precision requirements.
- **Python scripting** enables external automation via serial or network interfaces.
- Identical CLI patterns across protocols reduce learning curve for multi-mode projects.

## Frequently Asked Questions

### How does ESP32-Bit-Pirate differ from dedicated stepper motor libraries?

Dedicated libraries like AccelStepper optimize for motion profiles and acceleration curves. **ESP32-Bit-Pirate** prioritizes **interactive hardware exploration**—immediate command execution, cross-protocol consistency, and no compile-flash cycles. For simple positioning tasks or protocol bridging, the integrated approach proves faster to deploy.

### What ESP32-S3 boards are compatible with the stepper motor example?

Verified boards include **M5Stack StickS3**, **M5Stack Cardputer**, **LilyGo T-Embed**, and **LilyGo T-Deck**. The `StickS3Board`, `CardputerBoard`, and `TEmbedBoard` classes in the source handle pin mapping and peripheral initialization automatically.

### Can I control multiple stepper motors simultaneously?

The current `DioController` implementation sequences one motor per DIO mode instance. For simultaneous control, instantiate multiple `DependencyProvider` contexts with distinct pin assignments, or extend `DioController` to maintain multiple stepper state machines—both approaches leverage the existing `PinService` abstraction.

### Is real-time step timing guaranteed for precise motor control?

Timing accuracy depends on the **ActionDispatcher** loop latency and any concurrent protocol operations. For critical real-time applications, consider dedicating an ESP32 core to stepping logic or using the **RMT peripheral** (supported in underlying ESP-IDF but not currently exposed through DIO commands).