ESC Integration#

An electronic speed controller (ESC) is a self-contained BLDC driver that handles commutation, current regulation, and protection โ€” reducing the firmware interface to a single control signal. ESCs originated in the RC hobby world but are now used in drones, robots, electric vehicles, and any application where the complexity of building a custom three-phase inverter is not justified. The MCU sends a throttle command; the ESC manages everything else.

ESC Architecture#

A typical ESC contains:

  • Three-phase MOSFET bridge (6 FETs) rated for the motor’s voltage and current
  • Gate drivers with dead-time insertion
  • Microcontroller running commutation firmware (usually sensorless six-step or FOC)
  • Current sensing (shunt or MOSFET RDS(on) sensing)
  • BEC (Battery Elimination Circuit) โ€” a built-in voltage regulator (usually 5 V) to power the receiver or MCU

Control Protocols#

ESCs accept throttle commands through several protocols, all originating from the RC servo standard and evolving toward lower latency:

Standard PWM (Servo PWM)#

The original protocol. A 1โ€“2 ms pulse at 50โ€“400 Hz:

Pulse WidthThrottle
1000 ยตs0 % (motor off)
1500 ยตs50 %
2000 ยตs100 % (full throttle)
/* STM32 โ€” generate 50 Hz servo PWM on TIM3 CH1 */
htim3.Init.Prescaler = 71;         /* 72 MHz / 72 = 1 MHz tick */
htim3.Init.Period = 19999;         /* 20 ms period (50 Hz) */
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

/* Set throttle (0โ€“100 %) */
uint16_t pulse_us = 1000 + (throttle_pct * 10);  /* 1000โ€“2000 ยตs */
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pulse_us);

OneShot125#

A faster variant where the pulse width is 125โ€“250 ยตs (8ร— faster than standard PWM). The frame rate can be up to 4 kHz, reducing latency from 20 ms to ~250 ยตs.

Pulse WidthThrottle
125 ยตs0 %
250 ยตs100 %

OneShot42#

Further reduction: 42โ€“84 ยตs pulse widths, up to ~12 kHz update rate.

DShot (Digital Shot)#

A fully digital protocol that eliminates analog pulse-width ambiguity. Each frame is a 16-bit packet (11 bits throttle, 1 bit telemetry request, 4-bit CRC) sent as a serial bitstream:

VariantBit RateFrame TimeResolution
DShot150150 kbit/s106.7 ยตs11-bit (0โ€“2047)
DShot300300 kbit/s53.3 ยตs11-bit
DShot600600 kbit/s26.7 ยตs11-bit
DShot12001200 kbit/s13.3 ยตs11-bit

DShot encodes bits by pulse width: a “1” bit has a 75 % duty cycle, a “0” bit has a 37.5 % duty cycle, within each bit period.

/* DShot600 frame generation using DMA + timer */
/* Bit period: 1/600 kHz = 1.67 ยตs at 600 kbit/s */
/* '1' = 1.25 ยตs high, 0.42 ยตs low */
/* '0' = 0.625 ยตs high, 1.04 ยตs low */

#define DSHOT_T1H  (timer_period * 3 / 4)  /* 75 % */
#define DSHOT_T0H  (timer_period * 3 / 8)  /* 37.5 % */

void dshot_send(uint16_t throttle, bool telemetry) {
    uint16_t packet = (throttle << 5) | (telemetry << 4);
    packet |= crc4(packet >> 4);

    for (int i = 15; i >= 0; i--) {
        dma_buffer[15 - i] = (packet & (1 << i)) ? DSHOT_T1H : DSHOT_T0H;
    }
    /* Start DMA transfer to timer CCR */
    HAL_TIM_PWM_Start_DMA(&htim_dshot, TIM_CHANNEL_1,
                           (uint32_t *)dma_buffer, 16);
}

ESC Calibration#

Most ESCs must be calibrated to map the full throttle range:

  1. Power on with throttle at maximum (2000 ยตs / DShot 2047)
  2. ESC beeps to confirm high point
  3. Set throttle to minimum (1000 ยตs / DShot 0)
  4. ESC beeps to confirm low point
  5. ESC stores the calibration

Without calibration, the ESC may not start until 20โ€“30 % throttle input, or may not reach full speed at 100 %.

Bidirectional ESCs (3D Mode)#

Standard ESCs spin the motor in one direction only. Bidirectional (3D) ESCs map the throttle range symmetrically:

Throttle RangeMotor
0โ€“47 % (1000โ€“1480 ยตs)Reverse, full โ†’ zero
48โ€“52 % (1480โ€“1520 ยตs)Dead band (motor off)
53โ€“100 % (1520โ€“2000 ยตs)Forward, zero โ†’ full

Telemetry (ESC โ†’ MCU)#

Many modern ESCs (running BLHeli_32 or AM32 firmware) support bidirectional DShot telemetry, returning RPM data to the flight controller. The ESC sends an eRPM (electrical RPM) packet back on the signal line after each throttle command:

Mechanical RPM = eRPM / pole_pairs

UART-based telemetry (KISS protocol, BLHeli telemetry) provides additional data: current, voltage, temperature, and RPM over a separate serial link.

Tips#

  • Use DShot600 for new designs. It eliminates calibration issues (digital throttle values are absolute), provides CRC error detection, and supports bidirectional telemetry for RPM feedback.
  • Keep the signal wire between the MCU and ESC under 30 cm. Longer runs require a ground wire alongside the signal to maintain edge integrity โ€” DShot600 has ~833 ns bit periods that degrade with capacitive loading.
  • Arm the ESC by sending minimum throttle (1000 ยตs or DShot 0) for at least 2 seconds after power-on. Most ESCs will not spin the motor until they see a valid low-throttle signal first.
  • For applications requiring braking, select an ESC with active braking or regenerative braking support. Standard ESCs coast to a stop when throttle is reduced.

Caveats#

  • Not all ESCs support all protocols. BLHeli_S firmware supports DShot up to 600; BLHeli_32 and AM32 support DShot1200 and bidirectional telemetry. Standard PWM ESCs (older hobby ESCs) often have no DShot support.
  • ESC timing advance (typically configurable: low/medium/high) affects efficiency and startup behavior. High timing advance increases high-speed efficiency but can cause stuttering at low throttle.
  • The BEC output of an ESC is often a noisy switching regulator. Using it to power sensitive analog circuits (ADCs, sensors) can introduce noise. A separate LDO or filtered supply is preferred for logic power.
  • ESC current ratings are often optimistic โ€” specified at 25 ยฐC with direct airflow (propwash). Derate by 30โ€“50 % for enclosed installations without forced cooling.

In Practice#

  • Motor stutters at low throttle instead of spinning smoothly. The ESC’s minimum speed threshold is above the commanded throttle. This commonly appears with high-KV motors on high-timing ESCs โ€” the commutation timing is too aggressive for low-speed operation. Reducing timing advance or switching to an ESC with FOC-based low-speed control resolves the stuttering.

  • Motor spins at different speeds on two “identical” ESCs at the same throttle input. Calibration offsets differ between the two ESCs. With analog PWM, small variations in the internal reference voltage cause different throttle mappings. Recalibrating both ESCs or switching to DShot (absolute digital values) eliminates the mismatch.

  • ESC does not arm โ€” motor beeps error codes on power-up. The throttle signal is not at minimum during the arming window. Common causes: the MCU starts with the PWM output in an undefined state, the ESC receives no signal during its 2-second arming timeout, or DShot frames have CRC errors. Ensuring the correct minimum-throttle signal is sent immediately on power-up resolves the arming failure.

  • Reported RPM via DShot telemetry does not match actual RPM. The telemetry reports electrical RPM, which must be divided by the number of pole pairs to get mechanical RPM. A 14-pole motor (7 pole pairs) showing 70,000 eRPM is actually spinning at 10,000 mechanical RPM.

Page last modified: March 2, 2026