Advertisement
Advanced Time: 6–8 weeks Electronics Engineering

BLDC Motor Controller (FOC)

Implement Field-Oriented Control (FOC) for a BLDC motor with real-time current sensing, encoder feedback, and position/speed/torque control modes.

BLDCFOCMotor ControlSVPWMCurrent ControlEncoder
DifficultyAdvanced
Duration6–8 weeks
Components10 items
Steps4 steps

Introduction

Implement Field-Oriented Control (FOC) for a BLDC motor with real-time current sensing, encoder feedback, and position/speed/torque control modes. This comprehensive guide covers everything from design through implementation, testing, and deployment.

Theory & Background

Field-Oriented Control: controls BLDC like a DC motor by decomposing stator current into two orthogonal components: Id (flux-producing, aligned with rotor field) and Iq (torque-producing, perpendicular to rotor field). In steady state: set Id=0 (no magnetizing current), Iq=desired_torque/Kt. Transform: Park transform converts phase currents (Ia, Ib, Ic) to rotor-oriented d-q coordinates. Inverse Park + Inverse Clarke + SVPWM convert d-q voltage commands to 3-phase PWM duty cycles. Control loops: outer (position or speed), inner (current/torque). Inner loop bandwidth: 2–10 kHz. Outer loop: 100–500 Hz.

Advertisement

Components & Requirements

10 components required for this project.

#ComponentPurposeQty
1STM32G474 MCU (CORDIC, HRTIM, op-amps)FOC algorithm host with hardware peripheralsx1
2DRV8323 Gate Driver IC (3-phase)Gate driver with integrated current sensingx1
3N-channel MOSFETs (60V, 50A, IRFS7530)3-phase inverter (2 per leg)x6
4AS5047P Magnetic Encoder (14-bit)High-resolution rotor position feedbackx1
5Current sense resistors (5mΩ per phase)Phase current measurementx3
6InlineAmp (INA240A3) current sense ampDifferential current sense amplificationx3
7BLDC Motor (gimbal or e-bike motor)Motor under controlx1
8DC power supply (24–48V, 20A)Inverter bus voltagex1
9CAN transceiver + controllerTelemetry and parameter updatex1
10ODrive V3.6 (reference design)Open-source reference FOC hardwarex1

Step-by-Step Implementation

Follow these 4 steps carefully.

1
FOC Architecture

Field-Oriented Control: controls BLDC like a DC motor by decomposing stator current into two orthogonal components: Id (flux-producing, aligned with rotor field) and Iq (torque-producing, perpendicular to rotor field). In steady state: set Id=0 (no magnetizing current), Iq=desired_torque/Kt. Transform: Park transform converts phase currents (Ia, Ib, Ic) to rotor-oriented d-q coordinates. Inverse Park + Inverse Clarke + SVPWM convert d-q voltage commands to 3-phase PWM duty cycles. Control loops: outer (position or speed), inner (current/torque). Inner loop bandwidth: 2–10 kHz. Outer loop: 100–500 Hz.

2
Clarke and Park Transforms

Clarke transform (3-phase → 2-phase stationary αβ): Iα = Ia, Iβ = (Ia + 2Ib)/√3. Park transform (stationary αβ → rotating dq): Id = Iα×cos(θ) + Iβ×sin(θ), Iq = -Iα×sin(θ) + Iβ×cos(θ). θ = electrical angle from encoder (mechanical × pole_pairs). Inverse Park: Vα = Vd×cos(θ) - Vq×sin(θ), Vβ = Vd×sin(θ) + Vq×cos(θ). Inverse Clarke + SVPWM: compute optimal 3-phase duty cycles using STM32 hardware CORDIC for sin/cos computation (< 10 cycles, critical for <5µs FOC loop time).

3
Current Sensing and ADC Synchronization

Phase current measurement: sample during PWM period when all current flows through sense resistors (at center of PWM period for center-aligned PWM). STM32 hardware synchronization: trigger ADC from TIM1 (center-aligned mode trigger output) → simultaneous sampling of all 3 phase currents. INA240A amplifies current sense signal: 5mΩ × 20A = 100mV input → 200× gain → 20V range (limited by supply). Offset calibration: at initialization, measure ADC output with zero current → store as offset, subtract from all readings. Current sign convention: positive = current into motor.

4
PI Current Controller Tuning

Current control PI tuning using bandwidth approach: target bandwidth = 2kHz (2×10³ rad/s = 12,566 rad/s). Motor electrical time constant: τ_e = L/R (L=300µH, R=0.5Ω → τ_e = 600µs). PI current controller: Kp = L × ω_c = 300×10⁻⁶ × 12566 = 3.77, Ki = R × ω_c = 0.5 × 12566 = 6283. Voltage limit: clamp PI output to (V_bus / √3) for SVPWM. Anti-windup: clamp integral term when output saturated. Test: step response of Iq should reach setpoint in ~0.5ms with < 10% overshoot.

Code & Implementation

Core code for foc_controller.c:

foc_controller.c C
// Field-Oriented Control core algorithm // Runs in 20kHz interrupt (50µs period) on STM32G474  #include "arm_math.h" #include "foc.h"  typedef struct { float d, q; } dq_t; typedef struct { float a, b; } ab_t;  // Park/Clarke transforms ab_t clarke(float ia, float ib) {     return (ab_t){ ia, (ia + 2*ib) * 0.577350f };  // 1/sqrt(3) }  dq_t park(ab_t ab, float sin_t, float cos_t) {     return (dq_t){ ab.a*cos_t + ab.b*sin_t, -ab.a*sin_t + ab.b*cos_t }; }  ab_t inv_park(dq_t dq, float sin_t, float cos_t) {     return (ab_t){ dq.d*cos_t - dq.q*sin_t, dq.d*sin_t + dq.q*cos_t }; }  void foc_update(FOC_Handle *h) {     // 1. Read encoder angle     h->angle = AS5047P_Read() * (2*M_PI / 16384) * h->pole_pairs;     float s = sinf(h->angle), c = cosf(h->angle);      // 2. Read and transform phase currents     dq_t I = park(clarke(h->Ia, h->Ib), s, c);      // 3. Current PI controllers (d-axis: zero flux, q-axis: torque)     float Vd = PI_Update(&h->pid_d, 0 - I.d);     // Id reference = 0     float Vq = PI_Update(&h->pid_q, h->Iq_ref - I.q); // Iq = torque command      // 4. Inverse transforms     ab_t Vab = inv_park((dq_t){Vd, Vq}, s, c);      // 5. Space Vector PWM - compute duty cycles     float Va = Vab.a;     float Vb = (-Vab.a + 1.732f*Vab.b) * 0.5f;     float Vc = (-Vab.a - 1.732f*Vab.b) * 0.5f;          float Vmax = fmaxf(fmaxf(Va, Vb), Vc);     float Vmin = fminf(fminf(Va, Vb), Vc);     float Vzero = -(Vmax + Vmin) * 0.5f;  // Zero sequence injection          float duty_a = (Va + Vzero + h->Vbus/2) / h->Vbus;     float duty_b = (Vb + Vzero + h->Vbus/2) / h->Vbus;     float duty_c = (Vc + Vzero + h->Vbus/2) / h->Vbus;          Set_PWM_Duty(duty_a, duty_b, duty_c); }

Testing & Troubleshooting

Test BLDC Motor Controller (FOC) by verifying each subsystem individually before full integration.

!
Troubleshooting Tips

Verify power voltages, check ground connections, use serial monitor for debug.

Real-World Applications

*Electric vehicle motor drive
*Industrial servo drive
*Drone propulsion BLDC speed controller
*CNC axis servo controller
*Camera gimbal stabilization motor
*Robot joint torque control
*E-bike motor controller
*HVAC compressor variable speed drive

Extensions & Next Steps

  • Implement sensorless FOC using BEMF observer
  • Add auto-calibration for resistance and inductance measurement
  • Build a dynamometer for motor characterization
  • Implement position control for servo application
  • Add CAN bus interface for multi-axis robot control

Interactive Playground

Coming Soon

An interactive simulator will be available here — simulate circuits and run code in-browser without hardware.

Frequently Asked Questions

What is the difference between BLDC and PMSM motors and how does FOC control them?
BLDC (Brushless DC): trapezoidal back-EMF waveform, 6-step (block) commutation. Simple control, current efficient at rated speed. Torque ripple at 6 commutation events per revolution. PMSM (Permanent Magnet Synchronous Motor): sinusoidal back-EMF, sinusoidal current required. Requires FOC for proper operation. Smooth torque (minimal ripple). FOC controls both BLDC and PMSM: for BLDC, FOC eliminates the 6-step commutation torque ripple (like a gimbal motor improvement). For PMSM: FOC is essential for efficiency and smooth operation. Same algorithm, same hardware — difference is in the motor's back-EMF and the resulting current waveform shape.
Advertisement