Skip to the content
4 layers99.1 × 49.5 mmESC, the printed circuit board in 3D

Custom FOC ESC project

Size
99.1 × 49.5 mm
Copper layers
4
Thickness
1.6 mm
Parts
56
Nets
49
Pads
199
Tracks, vias
583, 174
Pours
9
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
12 Sep 2026
Updated
6 Nov 2026

Overview

ESC is an open-source printed circuit board by TheodorePriceParsons, from the TheodorePriceParsons/Custom-FOC-ESC repository on GitHub. It is a 4-layer board of 99.1 × 49.5 mm with 56 parts on 49 nets, routed with 583 tracks and 174 vias.

It is built around the DRV8305NPHPR, MT6701CT-STD and AON7544. Its parts include 25 capacitors, 8 resistors, 6 transistors, 2 ICs and 2 connectors. It belongs with the robots and motor control boards of this library.

Main components

3

README

README.md

Custom FOC ESC

A field-oriented-control motor controller designed from scratch: a 4-layer power board, STM32G474 firmware with cascaded current and speed loops, and an automated hardware-in-the-loop test bench that verifies the drive against written requirements.

https://github.com/user-attachments/assets/c9957159-f915-4ab0-a1e7-d9c9039c102c

First closed-loop FOC spin (Oct 2026); kept for sentimental value.

FOC ESC 3D render

Highlights

  • Hardware: DRV8305 gate driver, AON7544 MOSFETs, 5 mΩ low-side shunts on all three phases, MT6701 magnetic encoder, 4-layer stackup with dedicated ground and power planes.
  • Firmware: sensored FOC at 10.4 kHz on the STM32G474's high-resolution timer, min/max SVPWM, PI current loops with conditional-integration anti-windup, and an outer speed loop. Worst-case ISR load is 37 to 46 % of the cycle budget.
  • Verification: one command runs every test on the hardware, identifies the motor (R, L, Kt, J), predicts each result from those parameters, and reports predicted vs measured with pass/fail per requirement.
  • Safety: host watchdog in the control ISR, latched E-stop, overcurrent and gate-driver fault trips.

Test results

Results are published here from the test bench with python bench/publish.py <run folder>.

How it works

text
 NUCLEO-G474RE                                        ESC board                    GM4108H motor
 ┌──────────────────────────────────────────┐        ┌─────────────────────┐
 │ HRTIM ── 3 x PWM (center-aligned) ───────┼──────▶ │ DRV8305 → 3 half-   │ ───▶ phases A/B/C
 │   └─ ADC trigger at PWM center           │        │ bridges (AON7544)   │
 │ ADC1 + DMA ◀── 3 shunt amplifiers ───────┼─────── │ 5 mΩ shunts, 40 V/V │
 │ SPI3 (shared bus) ◀──────────────────────┼─────── │ DRV8305 config/stat │
 │                  ◀──────────────────────┼─────── │ MT6701 encoder (SSI)│ ◀── magnet on rotor
 │ foc_isr() @ 10.38 kHz                    │        └─────────────────────┘
 │ LPUART1 ◀──▶ test bench (PC)             │
 └──────────────────────────────────────────┘

Each control period:

  1. The HRTIM triggers the ADC at the PWM center, when all low-side switches are on and the shunts carry the phase currents.
  2. The ISR reads the encoder, converts the mechanical angle to the electrical angle, and transforms the phase currents into the rotor frame (Clarke, then Park), where they are DC.
  3. Two PI controllers regulate $i_d$ to 0 and $i_q$ to the torque command. Every 10th tick the speed PI sets the $i_q$ command.
  4. The voltage command is transformed back (inverse Park) and turned into three duty cycles with min/max SVPWM, which reaches the full $V_{bus}/\sqrt{3}$ phase voltage.

The derivations, including the PI design by pole-zero cancellation, the speed loop design and the expected step responses, are in docs/control-math.md.

Test bench

The bench (in bench/) drives the ESC over UART from Python:

text
python bench/run_bench.py --port COM5 --tune-current
  • The firmware injects each step at an exact control-loop sample and records 2048 samples to RAM; the PC downloads the capture and computes every metric from it.
  • It measures R and L from a d-axis voltage step, computes current-loop gains for 300 Hz bandwidth, then verifies the loop it just tuned.
  • Each result is predicted from the parameters measured in the same run, so the report checks the design math as well as the hardware.
  • Requirements have IDs and limits in bench/spec.py; each test runs N times and reports mean ± std.
  • The host software is checked against a plant simulator with the same protocol (--sim), and the metric code has unit tests.

Details: bench/README.md, wire protocol: bench/PROTOCOL.md.

Hardware

Gate driverTI DRV8305, 3-PWM mode, SPI configuration, integrated current-sense amplifiers (40 V/V)
Power stageAON7544 N-channel MOSFETs, 3 half-bridges
Current sensing5 mΩ low-side shunts on all three phases (±8 A sense range), sampled at PWM center
PositionMT6701 14-bit magnetic encoder over SSI, sharing one SPI bus with the DRV8305
Stackup4 layers: power stage, solid ground, PVDD plane, signals
Power3S LiPo (12 V), XT60; 2 mm bullet connectors for swappable motor leads
ControllerNUCLEO-G474RE (Cortex-M4F, 170 MHz)
MotorGM4108H-120T gimbal motor, 11 pole pairs

KiCad projects are in hardware/ and motor mounts in mechanical/.

Bring-up notes

Four wiring and configuration mistakes took most of the bring-up time:

  1. The board ground was on the bench supply's earth terminal, so PVDD was never powered. The Nucleo back-fed 3.3 V into the DRV8305's regulator pin, which made PWRGD look healthy while SPI read all zeros.
  2. The nFAULT jumper was on the wrong Nucleo pin, so the MCU read a floating input.
  3. PWM went to the INL inputs; in 3-PWM mode the DRV8305 ignores INL, so every low-side gate sat on.
  4. One ADC pin on the Nucleo gave a large drifting offset. Swapping channels proved the board signal was clean, and moving phase C to another pin fixed it.

Repository

FolderContents
firmware/STM32CubeIDE project. Control code in App/foc/, drivers in App/drivers/, bench interface in App/bench/
hardware/KiCad projects for each board revision
mechanical/Motor and encoder mounts (STEP)
bench/Automated test bench, requirements, reports
docs/Control math and figures

Parts

56
QtyValueFootprintReferences
810uFCapacitor_SMD:C_1206_3216MetricC16, C17, C18, C19, C20, C21, C22, C23
71uFCapacitor_SMD:C_0603_1608MetricC1, C2, C3, C6, C8, C9, C12
6AON7544GS_MOSFETs:DFN-8_L3.3-W3.3-P0.65-BL-2Q1, Q2, Q3, Q4, Q5, Q6
31000 pFCapacitor_SMD:C_0603_1608MetricC4, C5, C7
310kResistor_SMD:R_0402_1005MetricR4, R5, R7
35mOhmResistor_SMD:R_2512_6332MetricR1, R2, R3
3NetTie_2NetTie:NetTie-2_SMD_Pad0.5mmNT1, NT2, NT3
20.047uFCapacitor_SMD:C_0603_1608MetricC10, C11
10.1uFCapacitor_SMD:C_0603_1608MetricC15
1100 RGS_Resistors:R_0603_1608MetricR6
1100uFCapacitor_SMD:CP_Elec_6.3x5.9C24
11nFCapacitor_SMD:C_0402_1005MetricC25
12.2uFCapacitor_SMD:C_0805_2012MetricC14
13.3KResistor_SMD:R_0402_1005MetricR8
14.7uFCapacitor_SMD:C_0805_2012MetricC13
16V, unidirectionalDiode_SMD:D_SOD-323D1
1Conn_01x02Connector_AMASS:AMASS_XT60-F_1x02_P7.20mm_VerticalJ2
1Conn_02x13_Odd_EvenConnector_PinHeader_2.54mm:PinHeader_2x13_P2.54mm_VerticalJ1
1DRV8305NPHPRGS_Gate_Drivers:HTQFP-48_L7.0-W7.0-P0.50-LS9.0-BL-EP5.1U2
1LOGOGM4108H_Motor_Mount:Otter_footprint1G***
1LOGOGM4108H_Motor_Mount:ENPHG***
1MT6701CTPackage_SO:SO-8_3.9x4.9mm_P1.27mmU1
1P1TestPoint:TestPoint_THTPad_D2.0mm_Drill1.0mmTP10
1P2TestPoint:TestPoint_THTPad_D2.0mm_Drill1.0mmTP11
1P3TestPoint:TestPoint_THTPad_D2.0mm_Drill1.0mmTP12
1PHASE 1TestPoint:TestPoint_THTPad_2.0x2.0mm_Drill1.0mmTP1
1PHASE 2TestPoint:TestPoint_THTPad_2.0x2.0mm_Drill1.0mmTP2
1PHASE 3TestPoint:TestPoint_THTPad_2.0x2.0mm_Drill1.0mmTP3

The 55 most common of 56 parts.

More from TheodorePriceParsons/Custom-FOC-ESC

1
  • 4 layers114.3 × 49.5 mmESC, the printed circuit board in 3D

    ESC

    TheodorePriceParsons/Custom-FOC-ESC

    Custom FOC ESC project

    54 parts

Similar boards

  • 4 layers140 × 100 mmDc usv, the printed circuit board in 3D

    Dc usv

    TobleMiner/DC-UPS

    A small DC UPS, designed to keep small appliances like consumer network equipment running during power outages

    351 parts223CERN-OHL-P-2.0
  • 12 layers280 × 111.2 mmFpga candelabra, the printed circuit board in 3D

    Fpga candelabra

    chipsalliance/rocket-pcb

    PCB libraries and templates for rocket-chip based FPGA/ASIC designs

    738 parts21Apache-2.0
  • 4 layers60 × 130 mmParsnip, the printed circuit board in 3D

    Parsnip

    LimesKey/parsnip-node

    A portable LoRa communicator. Custom 4-layer PCB (ESP32-S3 + E22P-915M30S LoRa + NEO-M9N GNSS), designed in KiCad for 915 MHz.

    481 parts6
  • 2 layers50 × 64 mmI2current, the printed circuit board in 3D

    I2current

    cr1tbit/i2current

    The Raison d'être of this board is to be a powerful, extensible, and affordable replacement for hotglueing a random powerbank into your next portable small-scale electronic project.

    158 parts2
  • 2 layers40 × 60 mmStripController, the printed circuit board in 3D

    StripController

    RainbowLabsDE/LightInstallationController

    PCB and Firmware of our first universal RGB light installation controller.

    73 parts4MIT

Questions

How big is the ESC PCB?

It measures 99.1 × 49.5 mm and has 4 copper layers, 1.6 mm thick.

What parts does the ESC use?

56 parts, built around the DRV8305NPHPR, MT6701CT-STD and AON7544. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the ESC KiCad files?

From the TheodorePriceParsons/Custom-FOC-ESC repository on GitHub, at the commit this page was made from: the board is hardware/ESC_FINAL_rev/ESC.kicad_pcb and its schematic hardware/ESC_FINAL_rev/ESC.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the ESC design in my own project?

Its repository states no licence, so its author keeps all rights: ask TheodorePriceParsons before reusing the design.