# Relays, Motors, and Drivers — Engineering Handbook

> A practical reference for computer engineering students and engineers working with electromechanical control systems. This handbook bridges the gap between theory and real-world design, covering the intuition, implementation details, failure modes, and decision-making frameworks you need in production work.

---

## Table of Contents

1. [Relay Control](#1-relay-control)
2. [Flyback Diodes](#2-flyback-diodes)
3. [Motor Drivers](#3-motor-drivers)
4. [PWM — Pulse Width Modulation](#4-pwm--pulse-width-modulation)
5. [Servo Control](#5-servo-control)
6. [Stepper Motor Basics](#6-stepper-motor-basics)

---

## 1. Relay Control

### 1.1 What a Relay Actually Is — First Principles

A relay is an electrically-controlled mechanical switch. It uses electromagnetism to physically move a contact from one position to another, allowing a low-power signal circuit to switch a completely separate, high-power load circuit.

This separation is the key insight: **galvanic isolation**. The control side and the load side share no direct electrical connection. This is why relays are used to switch mains voltage (120V/240V AC) from a 3.3V or 5V microcontroller GPIO.

Think of a relay like a remote-controlled light switch. The switch mechanism is physical metal-on-metal contact. The "remote" is the electromagnet.

**Internal anatomy:**

```
CONTROL SIDE                 LOAD SIDE
                             
┌──────────┐                 ┌─────────────────┐
│          │                 │ Common (COM)     │
│  Coil    │── Flux ──►  [Armature pulls down] │
│          │                 │ Normally Open    │
│  12mA    │                 │   (NO) contact   │
└──────────┘                 │ Normally Closed  │
                             │   (NC) contact   │
                             └─────────────────┘
```

**Contact types:**
- **COM (Common):** The moving contact — always connected to this.
- **NO (Normally Open):** Open when coil is de-energized. Closes when coil is energized.
- **NC (Normally Closed):** Closed when coil is de-energized. Opens when coil is energized.

In most switching applications (turning something ON with a signal), you wire: **COM → NO**, so the load is off by default and turns on when you energize the coil.

### 1.2 Relay Coil Parameters

The coil is essentially an inductor with a DC resistance. To energize it, you push current through it. Key parameters:

| Parameter | Meaning | Typical values |
|---|---|---|
| Coil voltage | Voltage the coil is rated for | 5V, 12V, 24V |
| Coil resistance | DC resistance of the coil wire | 50Ω–500Ω |
| Coil current | Voltage ÷ Resistance | 20mA–200mA |
| Pull-in voltage | Minimum voltage to close the contacts | ~75% of rated |
| Drop-out voltage | Voltage at which contacts release | ~10–30% of rated |
| Pick-up time | Time from energize to contacts closing | 5–15ms |
| Release time | Time from de-energize to contacts opening | 2–10ms |

**Critical insight:** The coil current is too high for most microcontroller GPIO pins, which typically source/sink only 8–40mA. You must use a transistor or MOSFET driver between the GPIO and the coil.

### 1.3 Relay Drive Circuit — The Canonical Design

```
MCU GPIO ──── R_base ──── BJT Base
                               │
                           BJT Collector ──── Relay Coil (+) ──── VCC
                               │
                           BJT Emitter ──── GND
                           
                   Across coil: Flyback diode (cathode to VCC)
```

**Step by step:**
1. GPIO goes HIGH → current flows through R_base into BJT base
2. BJT saturates → collector-emitter effectively short-circuits
3. Current flows: VCC → Coil → Collector → Emitter → GND
4. Coil is energized → relay pulls in
5. GPIO goes LOW → BJT cuts off → coil current collapses → **flyback spike** (handled by diode — see Section 2)

**MOSFET variant (preferred in modern designs):**

```
MCU GPIO ──── R_gate (10kΩ) ──── MOSFET Gate
                                        │
                                  MOSFET Drain ──── Relay Coil (+) ──── VCC
                                        │
                                  MOSFET Source ──── GND
                                  
              R_gate_pulldown (100kΩ) between Gate and Source (prevents floating gate)
```

MOSFETs are preferred because:
- Higher input impedance → negligible current draw from GPIO
- Lower on-state voltage drop (R_DS_on) → less heat
- Faster switching (not needed for relays, but good practice)

**N-channel MOSFET selection checklist:**
- V_GS threshold < GPIO voltage (look for logic-level MOSFETs: V_GS_th ~ 1–2V for 3.3V systems)
- V_DS_max > your coil supply voltage with margin (e.g., 30V for a 12V relay)
- I_D_max > coil inrush current (typically 2–3× steady-state)

### 1.4 Relay Types

**Electromechanical Relay (EMR):**
- Physical moving contacts
- True galvanic isolation
- Handles AC and DC loads
- Slow (5–15ms switching)
- Wears out over time (rated contact cycles: 100K–10M)
- Generates audible click
- Can arc at contact break (especially inductive loads)

**Solid State Relay (SSR):**
- No moving parts — uses triacs or SCRs for AC, or MOSFETs for DC
- Fast switching (microseconds)
- Silent
- No mechanical wear
- Higher on-state voltage drop (generates heat under load)
- Cannot handle short-circuit current surge well
- More expensive per ampere

```mermaid
flowchart TD
    A[Need to switch a load with a microcontroller?] --> B{Is the load AC or DC?}
    B -->|AC mains 120V/240V| C{Switching frequency?}
    B -->|DC low voltage| D{Current level?}
    C -->|On/Off control only| E[Electromechanical Relay]
    C -->|Need phase control or fast switching| F[Solid State Relay with Triac]
    D -->|< 2A| G[MOSFET or BJT direct drive]
    D -->|2A–30A| H{Isolation required?}
    H -->|Yes| I[SSR DC type]
    H -->|No| J[H-bridge or gate driver IC]
    D -->|> 30A| K[Contactor + relay pilot circuit]
```

### 1.5 Contact Ratings and Load Types

Relay datasheets list contact ratings that must be respected — and the load type matters enormously.

**Resistive load (e.g., heater, incandescent bulb):**  
Current is in phase with voltage. This is the easiest case and what the relay's nominal rating refers to.

**Inductive load (e.g., motor, solenoid, transformer):**  
When an inductive load is switched off, the collapsing magnetic field generates a voltage spike. This spike causes arcing at the contacts, which erodes them. **Derate the relay by 30–50% for inductive loads.** Add a snubber circuit (RC across the contacts) to suppress arcing.

**Capacitive load (e.g., power supply input, long cables):**  
At the moment of switching ON, a capacitor looks like a short circuit → enormous inrush current spike. This can weld the contacts shut. Derate heavily or use a current-limiting NTC thermistor in series.

**Motor load:**  
Worst case. Has both inrush current (capacitive behavior at startup) AND back-EMF on shutdown (inductive behavior). Size the relay for 6–10× the running current.

### 1.6 Snubber Circuits

A snubber is an RC network placed across relay contacts to suppress arcing on inductive load switching.

```
         Contact
    ──────/ ──────────────────
                    │
                    ├── R_snubber (100Ω) ── C_snubber (100nF)
                    │                             │
    ───────────────────────────────────────────────
```

**Typical values:** 100Ω + 100nF for 120VAC. Values are tuned based on load inductance.

**Why it works:** The RC network provides a low-impedance path for the high-frequency arc energy, limiting the voltage spike and reducing arc duration.

### 1.7 Relay Control from a Microcontroller — Full Example

A typical Arduino/ESP32/STM32 relay control circuit uses a relay module (pre-built), but understanding the internals prevents wiring mistakes:

```mermaid
flowchart LR
    MCU["MCU GPIO (3.3V/5V)"] --> |"Signal"| OptoCoupler
    OptoCoupler --> |"Isolated signal"| TransistorDriver["NPN BJT or N-FET"]
    TransistorDriver --> |"Coil current"| RelayCoil["Relay Coil"]
    RelayCoil --> |"Electromagnetism"| Contacts["NO/NC Contacts"]
    Contacts --> |"Switches"| Load["High-voltage Load"]
    FlybackDiode["Flyback Diode"] -. "Suppresses spike" .-> RelayCoil
```

Many commercial relay modules use an **optocoupler** (e.g., PC817) between the MCU and the transistor driver. This provides additional isolation, protecting the MCU from noise coupling back from the relay coil. It also makes the module work with both 3.3V and 5V logic.

**Active-high vs active-low modules:**  
Many popular relay modules are **active-low** — the relay energizes when the GPIO goes LOW. This is counterintuitive and causes many beginner bugs. Check your module's schematic. The reason is that the optocoupler input is connected to VCC, so pulling the signal pin LOW enables current flow.

### 1.8 Common Mistakes with Relays

1. **Not using a flyback diode:** The inductive spike will eventually destroy your transistor or corrupt your MCU. Always use one.

2. **Driving the relay coil directly from a GPIO pin:** Most coils need 50–200mA. A GPIO can supply 8–40mA. The pin will current-limit, overheat, and possibly latch up.

3. **Ignoring contact ratings for the actual load type:** A 10A relay might handle only 3A of motor load due to inrush.

4. **Not decoupling the relay power supply:** When a relay coil energizes, it creates a current spike on the supply rail. Without a 100µF (or larger) bypass capacitor near the relay, this spike can cause MCU resets or ADC errors.

5. **Floating the relay coil supply:** If your relay runs on a separate 12V rail and that rail is unregulated, it can sag during coil energization, causing unreliable pull-in.

6. **Switching AC loads without understanding arc suppression:** Each make/break arc deposits carbon on the contacts, increasing contact resistance over time.

### 1.9 Debugging Relay Problems

```mermaid
flowchart TD
    A[Relay not working] --> B{Does the LED indicator light up?}
    B -->|No LED| C{Check control signal at transistor base/gate}
    C -->|Signal present| D[Transistor failed - measure Vce or Vds]
    C -->|No signal| E[Check MCU GPIO - measure with multimeter or logic probe]
    B -->|LED on| F{Can you hear the relay click?}
    F -->|No click| G[Measure voltage across coil - should match rated voltage]
    G -->|Voltage OK, no click| H[Coil is open - replace relay]
    G -->|Voltage low| I[Check supply rail - too much voltage drop under load]
    F -->|Click, but load not switching| J{Measure voltage at COM and NO contacts}
    J -->|Contacts not conducting| K[Contact welding or contamination - replace relay]
    J -->|Contacts conducting, load not on| L[Check load wiring and load itself]
```

---

## 2. Flyback Diodes

### 2.1 The Problem: Inductive Kickback From First Principles

Any coil — relay coil, motor winding, solenoid — is an inductor. An inductor's fundamental property is:

$$V = L \frac{dI}{dt}$$

This means: **the voltage across an inductor is proportional to the rate of change of current through it.**

When you energize a coil, current builds up gradually (the inductor resists sudden changes). When you cut off the current suddenly (transistor switches off), the current was flowing and now you're trying to stop it instantaneously. The inductor "fights back" by generating whatever voltage is necessary to keep the current flowing.

With a transistor switching off a 12V relay coil carrying 100mA:

$$V_{spike} = L \frac{\Delta I}{\Delta t} = L \times \frac{0.1A}{1\mu s} = \text{potentially hundreds of volts}$$

That spike appears at the collector/drain of your transistor — which is only rated for 20–60V. The spike exceeds the breakdown voltage, avalanche conduction occurs, and eventually the transistor is destroyed (or degrades silently until it fails later).

**Visualization of the spike:**

```
Collector voltage (V)
     │
 300 │   ▲ Inductive spike (can exceed 100-300V!)
     │   │
  12 │───┘           ─────────────
     │  transistor
     │  switches OFF
  0  │───────────────────────────── time
```

Without protection, this spike is real and damaging. With a flyback diode, it is clamped.

### 2.2 How a Flyback Diode Works

A flyback diode (also called a freewheeling diode, snubber diode, or catch diode) is placed **in parallel with the inductor**, with the cathode pointing toward the positive supply and the anode pointing toward the transistor collector.

```
VCC ──────────────────┬────────────────
                      │
                  [Relay Coil]
                      │
               ┌──────┤
               │      │
            [Diode]  [Transistor]
            (flyback) │
               │      │
               └──────┘
                      │
GND ──────────────────┴────────────────

Diode orientation: Cathode → VCC, Anode → Coil bottom/Collector
```

**What happens during normal operation (transistor ON):**  
Current flows: VCC → Coil → Transistor → GND. The diode is reverse-biased (cathode at VCC, anode at ~0V) — it does nothing.

**What happens when transistor switches OFF:**  
The collapsing magnetic field tries to maintain current flow. The current wants to continue flowing through the coil in the same direction. The only path available is now through the flyback diode (current flows: Coil bottom → Diode → VCC → Coil top → back to Coil bottom). The diode clamps the voltage at one forward diode drop (~0.7V) above VCC, limiting the spike to VCC + 0.7V instead of hundreds of volts.

The stored energy dissipates as heat in the coil resistance and the diode, rather than as a destructive spike.

### 2.3 Flyback Diode Selection

**Standard silicon diode (1N4001–1N4007):**  
- Works well for relays and solenoids where switching speed is not critical
- Forward voltage: ~0.7V
- Max reverse voltage: 50V–1000V (select based on supply)
- Recovery time: slow (~1µs) — acceptable for coil frequencies < 100kHz

**Schottky diode (e.g., 1N5819, SS34):**  
- Forward voltage: ~0.3V
- Faster recovery time: ~10–50ns
- Preferred for high-frequency switching (PWM motor drivers, boost converters)
- Lower power loss during commutation

**Zener diode in series with normal diode:**  
Advanced technique for faster coil de-energization. Instead of clamping at VCC + 0.7V, the Zener clamps at VCC + V_zener. Higher clamp voltage = faster energy dissipation = faster release time.

```
[Coil] ── [Zener Cathode → Anode] ── [Diode Anode → Cathode] ── VCC
```

The clamp voltage equals VCC + V_zener. The coil releases faster because the stored energy dissipates against a higher voltage. Used in pneumatic valve systems and braking circuits where fast release is critical.

### 2.4 Placement and Layout Rules

**Rule 1: Place the diode physically close to the coil.**  
The diode needs to intercept the spike before it propagates along PCB traces to the transistor. Long traces have parasitic inductance that adds to the spike.

**Rule 2: Observe polarity carefully.**  
A reversed flyback diode will short-circuit your power supply when the transistor turns ON. It will present a dead short: VCC → Diode → Transistor → GND. The transistor and/or fuse will fail immediately.

**Rule 3: Use a diode rated for the supply voltage.**  
The PIV (peak inverse voltage) rating of the diode must exceed VCC. For a 12V supply, a 1N4001 (50V PIV) is fine. For a 24V supply, use a 1N4002 or better.

**Rule 4: For motor H-bridges, four diodes are needed.**  
Each switching transistor needs its own flyback diode (or the IC integrates them internally — most modern H-bridge ICs do).

### 2.5 Flyback Diodes in H-Bridge Motor Drivers

In an H-bridge, current flows through motor windings in both directions. All four transistors need protection:

```
VCC
 │
[Q1]──────┬──────[Q2]
 │        │        │
[D1]↑   Motor    [D2]↑
 │        │        │
[Q3]──────┴──────[Q4]
 │                  │
[D3]↑            [D4]↑
 │                  │
GND
```

When Q1 and Q4 are ON, current flows left-to-right through the motor. When they switch OFF, the motor's back-EMF drives current through D2 and D3 (freewheeling path). This is why integrated H-bridge ICs (L298N, DRV8833, TB6612) include body diodes or dedicated freewheeling diodes.

### 2.6 Common Mistakes with Flyback Diodes

1. **Omitting the diode entirely:** Will damage the driver sooner or later. The transistor's datasheet may show an avalanche energy rating that appears sufficient, but cumulative stress degrades junction integrity.

2. **Reversed polarity:** Immediately destructive. Short circuit to supply.

3. **Using a diode with insufficient current rating:** During the flyback event, peak current through the diode equals the coil current at the moment of switch-off. For a relay coil at 100mA, a 1A diode is fine. For a 5A motor, use a diode rated for ≥ 5A peak.

4. **Using a slow rectifier diode in a PWM motor driver:** At 20kHz PWM, the diode turns on/off 20,000 times per second. A slow diode (recovery time > 500ns) will conduct during both forward and reverse phase → heating, reduced efficiency, possible destruction.

5. **Not accounting for parasitic inductance in PCB layout:** Even 10mm of trace can add significant inductance at fast switching speeds. Keep the diode as close as physically possible to the inductive load.

---

## 3. Motor Drivers

### 3.1 Why You Need a Dedicated Motor Driver

A motor is a current-hungry, inductively-loaded, back-EMF-generating device. Directly connecting it to a microcontroller GPIO would:
- Demand far more current than the pin can supply (motors draw 0.5A–50A vs GPIO 8–40mA)
- Subject the MCU to inductive kickback voltage spikes
- Expose the MCU to motor-generated electrical noise
- Prevent bidirectional control without a complex circuit

A motor driver IC sits between the MCU and the motor. It accepts low-current logic signals and drives the motor with full supply current, handling all the power electronics internally.

### 3.2 The H-Bridge — Core Concept

The H-bridge is the fundamental circuit for bidirectional DC motor control. Named for its shape in circuit diagrams:

```
         VCC
          │
    ┌─────┴─────┐
   [Q1]        [Q2]
    │           │
    ├─── Motor ─┤
    │           │
   [Q3]        [Q4]
    └─────┬─────┘
         GND
```

**Forward rotation:** Q1 + Q4 ON. Current flows: VCC → Q1 → Motor left-to-right → Q4 → GND.

**Reverse rotation:** Q2 + Q3 ON. Current flows: VCC → Q2 → Motor right-to-left → Q3 → GND.

**Braking (short brake):** Q3 + Q4 ON (both low-side). Motor terminals are both connected to GND. Back-EMF drives current through the motor winding against itself → regenerative braking, fast stop.

**Coasting (high-Z):** All transistors OFF. Motor spins freely from inertia, decelerating slowly due to friction only.

```mermaid
stateDiagram-v2
    [*] --> Stopped
    Stopped --> Forward : Q1+Q4 ON
    Stopped --> Reverse : Q2+Q3 ON
    Forward --> Braking : Q3+Q4 ON (fast stop)
    Reverse --> Braking : Q3+Q4 ON (fast stop)
    Forward --> Coasting : All OFF
    Reverse --> Coasting : All OFF
    Braking --> Stopped : Current decays
    Coasting --> Stopped : Friction stops motor
    Forward --> Reverse : Deadtime required!
    Reverse --> Forward : Deadtime required!
```

**Critical: Shoot-through / Cross-conduction**

If Q1 and Q3 (or Q2 and Q4) are ON simultaneously, you create a dead short from VCC to GND through both transistors. This is called shoot-through and can instantly destroy the transistors with an enormous current spike.

When transitioning from forward to reverse (or vice versa), you must ensure the outgoing transistors have fully turned off before the incoming ones turn on. The required dead time is typically 100ns–2µs depending on transistor characteristics. **All quality motor driver ICs handle this automatically in hardware.**

### 3.3 Common Motor Driver ICs

**L298N (legacy, still popular for learning):**
- Dual H-bridge, 2A per channel (4A peak)
- 5V–46V motor supply
- Logic supply separate from motor supply
- Significant voltage drop (~2V across transistors) due to BJT output stage
- Gets hot at higher currents — needs heatsink above 1A
- No current sensing, no protection features
- Good for: prototyping, low-current DC motors, stepper motors (see Section 6)

**L293D:**
- Dual H-bridge, 600mA per channel
- Integrated flyback diodes
- Good for small hobby motors, teaching environments

**DRV8833 (modern, preferred for small motors):**
- Dual H-bridge, 1.5A per channel (2A peak)
- 2.7V–10.8V
- Internal flyback diodes
- Low R_DS_on MOSFET output → very little heat at low currents
- I2C-controllable fault reporting
- Sleep mode for low power
- Good for: small robots, drones, IoT motor control

**TB6612FNG:**
- Dual H-bridge, 1.2A continuous (3.2A peak)
- 2.5V–13.5V
- Internal flyback diodes
- MOSFET output stage (lower voltage drop than L298N)
- Very clean design, popular in robotics

**DRV8871 (single channel, medium power):**
- 3.6A peak
- Single H-bridge
- Overcurrent protection, thermal shutdown
- Good for: single brushed DC motor in industrial products

**BTS7960 (high power):**
- 43A rated
- Used in automotive applications, electric bicycles
- Separate high-side/low-side half-bridges — combine two for a full H-bridge
- Overcurrent and thermal protection

### 3.4 Current Sensing and Control

For precise motor control, you need to know how much current the motor is drawing. Current tells you load (torque), stall condition, and enables current-limiting to protect the motor and driver.

**Sense resistor method:**
Place a small-value, high-power resistor (e.g., 0.1Ω, 1W) in series with the motor ground path. Measure the voltage across it. V = I × R → I = V/R.

```
Motor ── Driver ── [0.1Ω sense resistor] ── GND
                           │
                    ADC of MCU (via op-amp buffer or INA219 IC)
```

For 0.1Ω at 2A: V_sense = 0.2V → needs amplification before ADC.

**Integrated current sense ICs:**
- **INA219:** I2C, bidirectional, 26V max, 3.2A. Read current and bus voltage digitally.
- **INA226:** More precise, supports higher currents with external shunt.
- **ACS712 (Hall effect):** No sense resistor needed. Galvanically isolated measurement. Better for high-current and AC applications.

**Why current sensing matters in practice:**
- Stall detection: motor current spikes when mechanically blocked. If you don't detect and respond, the motor overheats.
- Current-mode PID control: faster response, better torque control than speed-only loops.
- Battery management: know exactly how much power you're consuming.

### 3.5 Motor Driver Selection Framework

```mermaid
flowchart TD
    A[Selecting a motor driver] --> B{Motor type?}
    B -->|Brushed DC| C{Current requirement?}
    B -->|Brushless DC| D[Need BLDC/ESC driver - DRV8302, VESC]
    B -->|Stepper| E[See Section 6 - A4988, DRV8825, TMC2209]
    B -->|Servo| F[See Section 5 - PWM direct control]
    C -->|< 1A| G[DRV8833, L293D, TB6612]
    C -->|1A–3A| H[TB6612, DRV8871, L298N]
    C -->|3A–10A| I[BTS7960, DRV8874, VNH2SP30]
    C -->|> 10A| J[Discrete MOSFET H-bridge with gate drivers]
    G --> K{Bidirectional?}
    H --> K
    I --> K
    K -->|Yes| L[H-bridge driver]
    K -->|No, one direction only| M[Simple low-side MOSFET or half-bridge]
```

### 3.6 Thermal Management

Motor drivers dissipate power as heat in their output transistors. Power dissipation:

$$P_{loss} = I^2 \times R_{DS(on)}$$

For a DRV8833 at R_DS_on = 0.6Ω driving 1A:

$$P_{loss} = 1^2 \times 0.6 = 0.6W \text{ per H-bridge}$$

This requires attention to PCB copper area for heat spreading, or an external heatsink for TO-220 packages.

**Thermal shutdown:** Most modern ICs include a thermal shutdown at ~150°C junction temperature. The IC will disable outputs and assert a fault flag. This protects the device but means your motor suddenly stops — which can be dangerous in moving systems.

**Best practices:**
- Check the power dissipation calculation before selecting a package
- Maximize copper area (copper planes, thermal vias to bottom layer)
- Derate: if the motor will stall briefly, the peak current × R_DS_on must stay below thermal limits
- Add a temperature sensor (NTC thermistor) near high-power drivers in production systems

### 3.7 Common Mistakes with Motor Drivers

1. **Powering the motor and MCU from the same supply without decoupling:** Motors create large current transients that cause supply voltage dips, leading to MCU resets. Use a 100µF + 100nF capacitor close to the motor supply pins of the driver IC.

2. **Running L298N at full 2A without a heatsink:** The BJT output stage has ~2V drop per transistor. At 2A, the IC dissipates 4–8W of heat. Without a heatsink, thermal shutdown occurs quickly.

3. **Not enforcing deadtime when building a discrete H-bridge:** The shoot-through condition destroys transistors within microseconds.

4. **Forgetting that the driver's logic supply and motor supply may be separate:** The motor's high-voltage supply should be isolated from the 3.3V/5V logic supply. Many driver ICs require a separate logic supply pin even when driving higher-voltage motors.

5. **Wiring motor supply voltage in reverse polarity:** This will destroy the driver (and sometimes the motor). Always verify polarity before first power-on. Use a schottky diode in series with the supply for reverse polarity protection in production.

---

## 4. PWM — Pulse Width Modulation

### 4.1 What PWM Is — From First Principles

PWM (Pulse Width Modulation) is a technique where a digital signal is switched rapidly between HIGH and LOW to simulate an analog output value. The key insight is:

> **By controlling how long the signal stays HIGH versus LOW within each period, you control the average power delivered to a load.**

The average voltage of a PWM signal equals:

$$V_{avg} = V_{supply} \times \text{Duty Cycle}$$

where Duty Cycle = (time HIGH) / (total period), expressed as a percentage.

```
100% duty cycle:  ──────────────────── (always HIGH = V_supply)
 75% duty cycle:  ───────╮  ╭──────── 
                          ╰──╯       
 50% duty cycle:  ──────╮   ╭──────
                         ╰───╯       
 25% duty cycle:  ───╮      ╭──────
                      ╰──────╯       
  0% duty cycle:  ─────────────────── (always LOW = 0V)
```

Why does this work for motor control? Because motors (and most electromagnetic loads) are inherently low-pass filters due to their inductance. The high-frequency PWM switching is filtered by the motor's electrical time constant (L/R), and the motor only "sees" the average voltage.

### 4.2 Key PWM Parameters

**Frequency (f):**
How many on/off cycles occur per second.
- Too low → the motor experiences each pulse as a discrete jerk → audible noise, torque ripple, current ripple
- Too high → switching losses in transistors increase (each transistor transition dissipates energy), inductor cores can saturate in DC-DC converters

**Typical frequency choices:**
| Application | Typical PWM Frequency | Reason |
|---|---|---|
| Hobby servo | 50 Hz | Legacy analog servo timing |
| Brushed DC motor | 1–20 kHz | Balance of smoothness and switching loss |
| Brushless DC (BLDC) | 8–32 kHz | Smooth commutation, above audible range |
| Stepper motor | 10–200 kHz (microstepping) | Current regulation |
| DC-DC converter | 100 kHz–10 MHz | Inductor/capacitor size tradeoff |
| LED dimming | 200 Hz–10 kHz | Above flicker perception threshold |
| Heating elements | 1–10 Hz | Thermal mass is the filter |

**Duty Cycle:**
The percentage of the period that the signal is HIGH. Range: 0%–100%.

**Resolution:**
How many discrete duty cycle steps exist. An 8-bit PWM has 256 steps (0–255). A 16-bit PWM has 65,536 steps (0–65535). Higher resolution allows finer speed control.

$$\text{Duty Cycle} = \frac{\text{compare value}}{\text{period register value}}$$

### 4.3 Hardware vs Software PWM

**Hardware PWM (preferred):**
Generated by a dedicated timer peripheral in the microcontroller. The timer counts up to a period value and resets, while a compare register triggers the output toggle. This runs entirely in hardware with zero CPU involvement.
- Precise timing
- Multiple independent channels
- No CPU overhead
- Can be phase-shifted (useful for multi-motor control)

**Software PWM:**
Generated by the CPU toggling a GPIO pin in code (timer interrupt or busy-wait loop).
- Consumes CPU cycles
- Timing jitter due to interrupt latency, other tasks
- Any interrupt with higher priority can cause a glitch in the PWM output
- Acceptable only for very low-frequency applications (e.g., LED dimming at 200Hz)

**When you run out of hardware PWM channels:**
- Dedicated PWM expander ICs: PCA9685 (16-channel, I2C) — extremely common in robotics for controlling many servos
- Accept the jitter of software PWM for non-critical loads (LEDs)

### 4.4 PWM Configuration in Microcontrollers

**STM32 (ARM Cortex-M) example:**
```
Timer configuration:
  - APB clock: 72MHz
  - Prescaler: 72-1 = 71 → Timer clock = 1MHz
  - Period (ARR): 1000-1 = 999 → PWM frequency = 1MHz / 1000 = 1kHz
  - Duty cycle: set CCR (capture compare register) from 0 to 999
  
For 50% duty: CCR = 500
For 75% duty: CCR = 750
```

**Arduino equivalent:**
```cpp
// Configure Timer1 for fast PWM, pin 9
// Default 8-bit, ~490Hz on pin 9 and 10, ~980Hz on pin 3 and 11
analogWrite(9, 128);  // 50% duty (128/255)
```

**ESP32:**
```cpp
// Setup channel, frequency, resolution
ledcSetup(0, 20000, 8);   // Channel 0, 20kHz, 8-bit
ledcAttachPin(16, 0);     // GPIO16 → channel 0
ledcWrite(0, 128);         // 50% duty
```

### 4.5 PWM for Motor Speed Control

Connecting PWM to an H-bridge gives you proportional speed control:

```
MCU PWM Output ──── Motor Driver IN1/IN2 pins
                         │
                     H-Bridge
                         │
                       Motor
```

**Common PWM-to-driver connection schemes:**

**Scheme A (Sign-Magnitude):** One direction pin + one PWM pin.
- IN1 = direction (HIGH = forward, LOW = reverse)
- PWM = speed (0%–100%)
- Simple, widely used

**Scheme B (PWM both channels):** PWM on IN1, inverted PWM on IN2.
- More complex, but allows active braking at 0% and 100% in both directions
- Some ICs require this

**Speed control with feedback (closed-loop):**

```mermaid
flowchart LR
    SetPoint["Target Speed\n(RPM)"] --> Controller["PID Controller\nin MCU"]
    Controller --> |"PWM Duty Cycle"| Driver["Motor Driver"]
    Driver --> Motor
    Motor --> Encoder["Encoder /\nHall Sensor"]
    Encoder --> |"Measured Speed"| Controller
```

Without feedback, motor speed varies with load. A loaded motor draws more current and slows down. A PID controller measures actual speed (from encoder) and adjusts PWM to maintain the target.

### 4.6 PWM Frequency Effects on Motor Behavior

**At 1 kHz:**
- Audible motor whine (in the audible frequency range)
- Significant current ripple in windings
- Motor feels "rough" at low speeds

**At 20 kHz:**
- Above human hearing — silent operation
- Lower current ripple — smoother torque at low speeds
- Higher switching losses in driver transistors
- Still practical for most BJT and MOSFET drivers

**At > 100 kHz:**
- Very low current ripple — used in precision position control
- High switching losses — driver may need heatsinking even at moderate currents
- Gate drive power increases (P = Q_g × V_gs × f)

**Rule of thumb:** Use 20kHz for most brushed DC motor applications. It's above audible range and switching losses are manageable.

### 4.7 PWM and EMI Considerations

PWM signals are rich in harmonics. The fast edges (sub-100ns rise/fall times of MOSFETs) generate electromagnetic interference that can:
- Corrupt ADC readings
- Interfere with wireless communication (WiFi, BLE, Zigbee)
- Cause issues with SPI/I2C communication
- Create regulatory compliance problems (FCC, CE)

**Mitigation strategies:**
- Slow down MOSFET gate drive (series gate resistor 10Ω–100Ω)
- Add a small ferrite bead or inductor in series with motor leads
- Keep PWM traces short and away from analog circuitry
- Use ground planes to provide a low-impedance return path
- Add ceramic capacitors (100nF) as close as possible to the motor driver supply pins

---

## 5. Servo Control

### 5.1 What a Servo Is — Architecture Overview

A servo motor is not just a motor — it is a closed-loop position control system in a small package. Inside a standard RC hobby servo:

```
┌─────────────────────────────────────────────────┐
│                  SERVO UNIT                      │
│                                                  │
│  PWM Signal ──► Control Board                   │
│                      │                           │
│              Error Signal                        │
│                      ▼                           │
│              H-Bridge Driver                     │
│                      │                           │
│               DC Motor ───► Gearbox ───► Output  │
│                                  │               │
│               Potentiometer ◄────┘               │
│                      │                           │
│              Feedback to Control Board           │
└─────────────────────────────────────────────────┘
```

The internal control board reads the potentiometer (which measures output shaft angle), compares it to the commanded position (from PWM), and drives the motor to eliminate the error. This is a proportional controller in a small IC.

### 5.2 The PWM Signal Protocol

Standard hobby servo control uses a specific PWM format:

- **Period:** 20ms (50Hz)
- **Pulse width:** 1ms = 0° (full left), 1.5ms = 90° (center), 2ms = 180° (full right)

```
20ms (50Hz period)
│←────────────────────────────────────────────────→│
┌──────┐                                            ┌
│      │                                            │
│ 1ms  │         18.5ms LOW (ignore duration)       │
│(0°)  │                                            │
┘      └────────────────────────────────────────────┘

┌─────────┐
│         │
│  1.5ms  │        18ms LOW
│  (90°)  │
┘         └─────────────────────────────────────────

┌────────────┐
│            │
│    2ms     │      17.5ms LOW
│   (180°)   │
┘            └──────────────────────────────────────
```

**Important nuance:** The actual angle range and pulse width limits vary by manufacturer. Many servos work from 0.5ms to 2.5ms for a wider 270° range. Always check the datasheet or experimentally determine the limits before mechanically hard-stopping the servo.

### 5.3 Generating Servo Pulses

**Using hardware PWM:**
```
Period = 20ms = 20,000 µs
At 1MHz timer clock with period register = 20,000:
  - Compare value for 0°:   1,000  (1ms)
  - Compare value for 90°:  1,500  (1.5ms)
  - Compare value for 180°: 2,000  (2ms)
```

**Arduino example (using Servo library):**
```cpp
#include <Servo.h>
Servo myservo;

void setup() {
  myservo.attach(9);    // PWM pin
}

void loop() {
  myservo.write(0);     // 0 degrees
  delay(1000);
  myservo.write(90);    // 90 degrees
  delay(1000);
  myservo.write(180);   // 180 degrees
  delay(1000);
}
```

The Servo library reconfigures Timer1 for 50Hz and maps angle (0–180) to pulse width (1–2ms). It uses one hardware timer per 12 servos by multiplexing the pulse generation in software within the timer ISR.

**PCA9685 for many servos:**
The PCA9685 is a 16-channel PWM driver on I2C. It has its own 25MHz internal oscillator and can drive 16 servos simultaneously with no MCU timer overhead. Essential for humanoid robots, hexapods, and any project with > 4 servos.

```
MCU ──I2C──► PCA9685 ──PWM ch0──► Servo 0
                      ──PWM ch1──► Servo 1
                      ──PWM ch2──► Servo 2
                         ...
                      ──PWM ch15─► Servo 15
```

### 5.4 Continuous Rotation Servos

A continuous rotation servo has its internal potentiometer feedback loop physically disabled or replaced. Instead of position control, the PWM signal controls **speed and direction:**
- 1ms = full reverse
- 1.5ms = stop
- 2ms = full forward

These are used in robots where simple proportional speed control in both directions is needed without encoder complexity.

**Calibration:** The exact "stop" pulse width varies per unit. A new servo must be calibrated — send 1.5ms and adjust ±0.05ms until the servo truly stops. This is done once and stored in firmware.

### 5.5 Servo Power Considerations

Servos draw significant current — especially during startup or when fighting a mechanical load:
- Small 9g servo: stall current ~700mA
- Standard servo (MG996R): stall current ~2.5A
- Large digital servo: stall current 3–5A

**Never power servos from the MCU's 5V regulator or USB power.** USB is typically limited to 500mA (USB 2.0) or 900mA (USB 3.0). Multiple servos under load will cause a brownout and crash the MCU.

**Production rule:** Use a dedicated servo power supply rail. Decouple it from the MCU supply. Connect grounds.

```
Battery / Power Brick
       │
       ├──── [5V Regulator or BEC] ──── Servo Power Rail (shared by all servos)
       │
       └──── [3.3V MCU Regulator] ──── MCU Power
       
GND common to all circuits.
MCU controls servos via PWM signal lines only (low current, not power).
```

### 5.6 Digital vs Analog Servos

**Analog servo:**  
Control board samples the PWM input at 50Hz. Control loop updates at 50Hz. Response to load changes is slow (20ms per update cycle).

**Digital servo:**  
Control board samples at 200–400Hz. Faster response, higher holding torque, less dead zone, smoother movement. Accepts the same PWM protocol — fully backward compatible. Draws slightly more current at idle due to higher PWM refresh rate of internal drive.

For robotics and precision applications, digital servos are worth the premium.

### 5.7 Position Control and Slew Rate Limiting

Sending a servo from 0° to 180° instantly causes:
- Mechanical shock to the servo gearbox (strip gears over time)
- Large current spike as the motor accelerates at maximum power
- Physical danger if a robotic arm moves unexpectedly fast

**Slew rate limiting** is the practice of interpolating commands:

```python
def move_servo_smoothly(current_angle, target_angle, step_size=1, delay_ms=15):
    """Move servo in steps to avoid mechanical shock"""
    if current_angle < target_angle:
        for angle in range(current_angle, target_angle + 1, step_size):
            servo.write(angle)
            time.sleep(delay_ms / 1000)
    else:
        for angle in range(current_angle, target_angle - 1, -step_size):
            servo.write(angle)
            time.sleep(delay_ms / 1000)
```

This is a first-order approach. More sophisticated systems use trapezoidal velocity profiles (accelerate → cruise → decelerate) for even smoother motion.

### 5.8 Common Servo Mistakes

1. **Powering servos from MCU 5V pin:** Brownout, MCU reset, corrupted firmware execution. Always use a separate supply.

2. **Setting pulse width outside the servo's mechanical limits:** The servo motor will hit the hard stop and continue trying to move. It will draw stall current indefinitely, overheating and burning the internal drive circuitry.

3. **Forgetting that servo position is absolute, not relative:** Sending `write(90)` doesn't move the servo 90 degrees from its current position — it moves it TO 90 degrees from its zero point.

4. **Using software PWM for servos in real-time systems:** Jitter in software PWM can cause servo jitter (buzzing/vibration at a fixed position). Use hardware PWM or PCA9685.

5. **Not accounting for servo dead band:** Most servos have a ±2–3° dead zone where they won't respond to small position changes. Feedback systems must account for this or they oscillate.

---

## 6. Stepper Motor Basics

### 6.1 What a Stepper Motor Is — First Principles

A stepper motor is a brushless DC motor designed to rotate in precise, discrete angular steps. Unlike a servo (which uses feedback to reach a target), a stepper motor is an **open-loop position device** — you command steps, and the motor moves that many steps (assuming it doesn't skip).

**Why discrete steps?** The stator has multiple poles arranged at specific angular intervals. By energizing different coil combinations, you attract the rotor to specific positions. The number of steps per revolution is determined by the physical pole geometry.

Common step angles: 1.8°/step = 200 steps/revolution (most common), 0.9°/step = 400 steps/revolution (higher resolution).

### 6.2 Internal Structure

A typical stepper motor (bipolar, 2-phase) has two independent coil windings:

```
     Phase A+  ─────[Coil A]───── Phase A-
     Phase B+  ─────[Coil B]───── Phase B-
     
     4 wire connections total for bipolar stepper
```

The rotor is a permanent magnet. The stator has electromagnets arranged around the rotor. By energizing phase A to attract the rotor to position 0, then energizing phase B to attract it to position 90°, then reversing A to attract it to 180°, then reversing B to attract it to 270°, the rotor advances one full electrical cycle.

Due to the fine-toothed pole geometry, one electrical cycle corresponds to 4 mechanical steps (for a 1.8° motor: 4 × 1.8° = 7.2° per electrical cycle).

### 6.3 Step Modes

**Full step (2-phase):**
Both coils energized at all times. Energizes A+B, -A+B, -A-B, A-B → 4 positions per electrical cycle.
- Maximum torque (full coil current in both phases)
- 200 steps per revolution (1.8° each)
- Significant positional vibration at low speeds

**Full step (1-phase):**
Only one coil energized at a time. A, B, -A, -B → lower torque but less heating.

**Half step:**
Alternates between one and two coils energized. A, A+B, B, B-A, -A, -A-B, -B, -B+A → 8 positions per electrical cycle.
- 400 steps per revolution (0.9° each) for a 1.8° motor
- Smoother than full step
- Torque is uneven (alternates between single-coil and dual-coil energization)

**Microstepping:**
The driver varies the current in both phases simultaneously using sinusoidal waveforms:
- Phase A current: $I_A = I_{max} \times \cos(\theta)$
- Phase B current: $I_B = I_{max} \times \sin(\theta)$

This creates intermediate rotor positions between the physical pole positions, effectively multiplying the resolution:
- 1/8 microstepping: 1600 steps/revolution
- 1/16 microstepping: 3200 steps/revolution
- 1/32 microstepping: 6400 steps/revolution
- 1/256 microstepping: 51200 steps/revolution

```mermaid
graph TD
    A[Step Mode Selection] --> B{Priority?}
    B -->|Maximum torque, don't care about smoothness| C[Full Step - 2 phase]
    B -->|Balance of torque and resolution| D[Half Step or 1/8 microstepping]
    B -->|Smoothest motion, lowest vibration| E[1/16 or 1/32 microstepping]
    B -->|Ultra-precision positioning| F[1/256 microstepping - TMC2209]
    C --> G[Note: audible at low speeds, check for resonance]
    D --> H[Note: uneven torque in half-step]
    E --> I[Note: reduced holding torque vs full step]
    F --> J[Note: very low torque - not for loads, only positioning]
```

**Important caveat about microstepping:** Higher microstepping gives smoother motion but **does not meaningfully increase positional accuracy**. The rotor position accuracy is still limited by the mechanical pole geometry. The intermediate positions are "soft" — under load, the rotor may not precisely reach each microstep. Microstepping is primarily for vibration and noise reduction, not accuracy.

### 6.4 Stepper Driver ICs

**A4988 (Allegro):**
- Bipolar stepper, up to 2A per phase
- 8V–35V motor supply
- Selectable microstep: 1, 1/2, 1/4, 1/8, 1/16
- Step + Direction interface (STEP pin, DIR pin)
- Overcurrent protection (sets peak current limit via Vref resistor)
- Extremely widely used in 3D printers (original RAMPS setup)

**DRV8825 (TI):**
- Up to 2.5A per phase
- Higher microstepping: up to 1/32
- Better thermal performance than A4988
- Same STEP/DIR interface → drop-in compatible

**TMC2209 (Trinamic/ADI):**
- Up to 2A (RMS) per phase
- Up to 1/256 microstepping
- **StallGuard:** sensorless homing — detects motor stall by monitoring back-EMF
- **SpreadCycle and StealthChop:** advanced current control modes for silent operation
- UART interface for configuration
- Used in modern 3D printers (Prusa, Voron, Bambu Lab)
- Most sophisticated stepper driver for motion control applications

### 6.5 STEP/DIR Interface — How It Works

The STEP/DIR interface is the standard protocol for stepper drivers:

```
MCU GPIO ──── DIR  ──► Driver (sets direction: HIGH=CW, LOW=CCW)
MCU GPIO ──── STEP ──► Driver (each LOW→HIGH transition = one microstep)
MCU GPIO ──── EN   ──► Driver (LOW=enabled, HIGH=disabled / coils de-energized)
```

**Generating STEP pulses in software:**
```python
import RPi.GPIO as GPIO
import time

STEP_PIN = 18
DIR_PIN = 16
EN_PIN = 22

GPIO.setup(STEP_PIN, GPIO.OUT)
GPIO.setup(DIR_PIN, GPIO.OUT)
GPIO.setup(EN_PIN, GPIO.OUT)

GPIO.output(EN_PIN, GPIO.LOW)    # Enable driver
GPIO.output(DIR_PIN, GPIO.HIGH)  # Clockwise

# Move 200 steps (1 full revolution at full step, 1/16 of a revolution at 1/16 microstep)
for step in range(200):
    GPIO.output(STEP_PIN, GPIO.HIGH)
    time.sleep(0.001)    # Step pulse high time (minimum 1µs for most drivers)
    GPIO.output(STEP_PIN, GPIO.LOW)
    time.sleep(0.001)    # Step rate = 500 steps/second
```

**Important timing:**  
Most drivers require a minimum pulse width on STEP (typically 1µs) and a minimum setup time for DIR changes (typically 200ns before STEP). Exceeding the maximum step rate will cause missed steps.

**In production:** Use hardware timer + DMA for step generation, not software GPIO toggling. Software GPIO has jitter that causes timing variations at high step rates, leading to missed steps or resonance-induced stalls.

### 6.6 Current Setting and Vref

The A4988 and DRV8825 set peak phase current via an external resistor and reference voltage on the current sense pins:

**A4988:**
$$I_{peak} = \frac{V_{ref}}{8 \times R_{sense}}$$

Where R_sense is typically 0.1Ω or 0.05Ω on the driver module.

For a typical A4988 module with R_sense = 0.068Ω:
$$V_{ref} = I_{peak} \times 8 \times 0.068$$

For 1A peak: $V_{ref} = 1 \times 8 \times 0.068 = 0.544V$

Adjust with a trimpot on the module. Measure Vref with a multimeter between the trimpot center and GND.

**Setting current correctly is critical:**
- Too high: motor overheats, driver overheats, potential demagnetization of permanent magnet rotor
- Too low: insufficient torque → missed steps under load

**Running current vs holding current:** Many drivers (especially TMC series) support reducing current when the motor is stopped. Full current isn't needed to hold position — typically 50–70% is sufficient — and reducing it lowers heat and power consumption significantly.

### 6.7 Stepper Motor Torque Characteristics

```
Torque
  │
  │\
  │ \  Pull-out torque curve
  │  \────────
  │           \
  │            \
  │             \
  └──────────────────────────── Speed (steps/sec)
```

Stepper motors have high torque at low speeds and dramatically lower torque at high speeds. This is because at higher speeds, there is less time per step for the current to build up in the inductive coil — the coil's inductance limits how quickly current can change (recall V = L × dI/dt). Less current → less magnetic force → less torque.

**Maximum speed is limited by:**
$$f_{max} \approx \frac{V_{supply}}{L \times I_{rated}} \times \frac{1}{2\pi}$$

Higher supply voltage allows current to build faster, extending the useful speed range. This is why 3D printers use 24V even for 12V-rated steppers — the higher voltage drives faster step rates.

**Resonance:** Stepper motors have a natural resonance frequency (typically 100–200 steps/second for a 200-step motor). Operating near resonance causes violent vibration and stall. In open-loop systems, ramp the step rate through the resonance zone quickly. Microstepping mitigates resonance significantly.

### 6.8 Acceleration and Deceleration Profiles

Stepping too fast at the start causes the motor to stall — the mechanical inertia prevents the rotor from jumping to the new position before the next step comes.

All stepper motion must use an acceleration profile:

```
Speed
  │         ┌──────────────────────┐
  │        /│                      │\
  │       / │                      │ \
  │      /  │                      │  \
  │─────/───┴──────────────────────┴───\─────► time
   Accel │      Constant speed        │ Decel
```

**Trapezoidal profile:** Linearly accelerate to cruise speed, hold, then linearly decelerate. Simple, good for most applications.

**S-curve (jerk-limited) profile:** Smooth the transitions between acceleration phases. Reduces mechanical shock and vibration. More complex to implement, used in precision CNC and 3D printing.

**Practical implementation:** Libraries like AccelStepper (Arduino) and GRBL (CNC) handle this in firmware. In production systems, dedicated motion controller ICs (e.g., Trinamic TMCM modules) or FPGAs generate step pulses with precise timing.

### 6.9 Sensorless Homing (StallGuard)

In systems without limit switches, the TMC2209 can detect motor stalls by monitoring back-EMF. When the motor hits a mechanical stop, it stalls — the back-EMF pattern changes, and the driver can signal a stall to the MCU.

This is how modern 3D printers (e.g., some Bambu Lab models) perform homing:
1. Move toward the endstop at a slow speed with low current
2. Driver reports stall event when axis hits the frame
3. MCU uses this as the zero position
4. No physical limit switch wiring needed

**Limitations:** StallGuard is sensitive to speed (works best in a specific speed range), load, and current settings. It requires careful calibration. Not suitable as a safety stop in industrial machinery.

### 6.10 Wiring Identification — Finding Coil Pairs

A bipolar stepper has 4 wires, but they're often unlabeled on off-the-shelf motors. Use a multimeter:

1. Measure resistance between each pair of wires
2. The two pairs with continuity are the two coil pairs
3. If a pair has ~1–10Ω continuity, those are coil ends
4. If there's no continuity between two wires, they're from different coils

**Alternative:** Short two wires together. Try to rotate the motor shaft by hand. If it has significantly more resistance than when unconnected, those two wires are from the same coil (shorted coil resists rotation via back-EMF braking).

### 6.11 Common Stepper Motor Mistakes

1. **Disconnecting motor wires while the driver is powered:** This causes voltage spikes that immediately destroy the driver IC. Always power down before disconnecting motor leads. Many driver datasheets explicitly state: "Never disconnect motor while powered."

2. **Setting current too high:** The motor gets hot enough to burn. A properly set stepper should be warm (~40–50°C) under load, not untouchably hot. Lower the Vref.

3. **No acceleration ramp:** The motor stalls on the first step of a fast move. Always ramp up from low speed.

4. **Assuming missed steps are visible:** In open-loop systems, missed steps accumulate silently. Your print/CNC job drifts. Add limit switches and re-home periodically, or use encoders (closed-loop stepper = servo).

5. **Microstepping for accuracy:** As explained, 1/32 microstepping doesn't give you 32× more positional accuracy. It gives smoother motion. If you need accuracy, use an encoder.

6. **Operating near resonance frequency without microstepping:** Catastrophic vibration. Use microstepping or adjust step rate to cross through resonance quickly.

7. **Using 5V supply for 12V-rated motors:** The torque at any meaningful speed will be severely reduced. Use the rated voltage or higher.

### 6.12 Debugging Stepper Issues

```mermaid
flowchart TD
    A[Stepper not moving] --> B{Any coil current when enabled?}
    B -->|No| C[Check EN pin - must be LOW for most drivers]
    C --> C2[Check motor wiring - continuity between correct pairs]
    B -->|Yes - motor vibrates but won't turn| D[Step rate too high - add acceleration ramp]
    D --> D2[Check motor coil pairs wired correctly to A1/A2/B1/B2]
    A2[Motor moves wrong direction] --> E[Swap DIR pin logic or swap one coil pair wires]
    A3[Motor misses steps] --> F{Under load or unloaded?}
    F -->|Unloaded| G[Step rate too high or resonance - slow down]
    F -->|Under load| H[Current set too low - increase Vref]
    H --> H2[Microstepping too fine - try full or half step for more torque]
    A4[Motor overheating] --> I[Current set too high - reduce Vref]
    I --> I2[Enable current decay/idle current reduction if driver supports it]
    A5[Motor makes noise but no movement] --> J[Check motor coupling - is shaft mechanically bound?]
    J --> J2[Is driver in fault state? Check fault/diag pin]
```

---

## Appendix A: Quick Reference Tables

### Relay Selection

| Load Type | Relay Size Rule | Notes |
|---|---|---|
| Resistive (heaters, lamps) | 1× rated current | Nominal rating applies |
| Inductive (motors, solenoids) | 3–5× rated current | Derate due to inrush and arcing |
| Capacitive (PSUs, cables) | 5–10× rated current | Extremely high inrush |

### Flyback Diode Selection

| Supply Voltage | Minimum PIV Rating | Recommended Diode |
|---|---|---|
| 5V | 25V | 1N4001, SS14 |
| 12V | 50V | 1N4001, 1N5819 |
| 24V | 100V | 1N4002, SS24 |
| 48V | 200V | 1N4003, SS34 |

### PWM Frequency Guidelines

| Load | Minimum | Recommended |
|---|---|---|
| Hobby servo | 50Hz | 50Hz (fixed) |
| Brushed DC motor | 1kHz | 20kHz |
| BLDC motor | 5kHz | 20–32kHz |
| LED dimming | 100Hz | 1–5kHz |

### Stepper Step Mode Comparison

| Mode | Steps/Rev (1.8°) | Torque | Smoothness | Best For |
|---|---|---|---|---|
| Full step (2-phase) | 200 | 100% | Low | High-torque slow moves |
| Half step | 400 | 70% | Medium | Moderate speed, decent torque |
| 1/16 microstep | 3200 | 50% | High | 3D printing, CNC routing |
| 1/256 microstep | 51200 | Low | Excellent | Silent positioning systems |

---

## Appendix B: Design Checklist

### Before Powering a New Motor Control Circuit

- [ ] Flyback diodes in place on all inductive loads
- [ ] Motor driver sized for peak (inrush) current, not just running current
- [ ] Decoupling capacitors (100µF + 100nF) on motor power supply near driver
- [ ] Separate power rails for motor and MCU logic
- [ ] Ground planes connected; no ground loops
- [ ] Current limit set correctly on stepper drivers (Vref measured)
- [ ] Hardware PWM used for servo/stepper control, not software bit-bang
- [ ] No GPIO driving relay coil or motor directly without a driver stage
- [ ] EN pin verified (active LOW on most drivers)
- [ ] Motor wire polarity and coil pairing verified before first power-on

---

*Last updated: April 2026*
