# 4.4. Field-Oriented Control (FOC)

FOC consists of a velocity controller, a current controller, and commutation and estmation subcomponents. A high-level block diagram of the FOC components is shown in Figure 4.3.

Figure 4.3 Block diagram of MCAF Field Oriented Control

This diagram shows a number of features that are described in the test harness.

## 4.4.1. Velocity Control

The velocity control loop is a straightforward, scalar PI controller, with managed saturation features to prevent integrator windup when either the velocity or current controller saturates.

It is preceded by a rate limiter, to provide more gentle trajectory shaping and reduce transient overshoot.

Saturation and antiwindup features are present and covered in a separate document.

## 4.4.2. Current Control

The current control loop is a vector control loop that operates in the dq reference frame, with reference transforms to convert to/from the ABC stationary reference frame in which currents are measured and duty cycles are commanded. The vector control loop itself is a straightforward pair of PI controllers, with managed saturation features to prevent integrator windup when the current controller saturates. (Saturation and antiwindup features are covered in more detail in a separate document.)

Figure 4.3 shows a filter block preceding the current controller. It is intended to slow down incoming commands from the velocity loop, which typically executes at a slower rate.

Figure 4.3 also shows DC link voltage compensation following the Inverse Park Transform.

## 4.4.3. Position and Velocity Estimator

The sensorless estimator used to estimate position and velocity is essentially the one used in AN1292.

## 4.4.4. Implementation Notes

### 4.4.4.1. FOC feature support

#### 4.4.4.1.1. Flux weakening

Flux weakening is presently disabled in MCAF R1, R2, and R3, and is being redesigned for a future version. In MCAF R1, R2, and R3, the velocity controller sets the d-axis current command to zero.

#### 4.4.4.1.2. Current command prefilter

The filter just prior to the current controller is unimplemented in MCAF R1, R2, and R3, but is reserved for a future version.

#### 4.4.4.1.3. DC link voltage compensation

DC link voltage compensation was not implemented for MCAF R1, but is implemented for MCAF R2 and R3. In MCAF R1, the multiply between \(V_{dq}\) and \(D_{dq}\) is not present.

#### 4.4.4.1.4. PWM duty cycle realization

MCAF R1 used an implementation of conventional space-vector PWM (CSVPWM) from the Microchip Motor Control Library (`MC_CalculateSpaceVectorPhaseShifted_Assembly`). Starting with MCAF R2, this has been switched to use a Zero Sequence Modulation block, which includes clipping within realizable limits (minimum and maximum duty cycle limits) in order to support overmodulation. See `MCAF_FocStepIsrForwardPath()`.

For more information on ZSM, see Microchip’s Zero Sequence Modulation Tutorial.

### 4.4.4.2. Numerical values for PWM duty cycle and dead time

It is important to understand some of the subtleties of PWM duty cycle in MCAF, in the presence of dead time. Interpretation of particular numeric duty cycles (for example, D = 0.1) can be slightly tricky. This section documents how they are used, and how to determine the correct values given known limits of the power electronics. Figure 4.4 shows several important points related to PWM duty cycle and dead time.

Figure 4.4 Interpreting duty cycle correctly

A typical PWM peripheral for use with a half-bridge circuit produces three waveforms:

- a raw generated pulse waveform G with duty cycle \(d\)
- high-side output H with the leading edge delayed by dead time \(D\),
- low-side output L inverted and with the trailing edge delayed by dead time \(D\).

Other implementations may split dead time in half symmetrically. (see note on dsPIC33 PWM)

- The intended duty cycle of the entire half-bridge is \(d\).
- The duty cycle of the high-side gate drive is \(d-D\). (with \(D\) expressed as a fraction of total PWM period)
- The duty cycle of the low-side gate drive is \(1-d-D\).
- With inductive loads, and transistor on-time and off-time roughly equal, the effective duty cycle of the entire half bridge is
  - \(d-D\) if current is flowing out of the half bridge (the low-side diode conducts during dead time),
  - \(d+D\) if current is flowing into the half bridge (the high-side diode conducts during dead time),
  - or somewhere in between if current does not stay positive or negative during the entire dead time — this represents discontinuous conduction.

Circuit designers of the half bridge should record the following quantities:

- Minimum duty cycle \(d_{HMIN}\) and maximum duty cycle \(d_{HMAX}\) of the high-side transistor
- Minimum duty cycle \(d_{LMIN}\) and maximum duty cycle \(d_{LMAX}\) of the low-side transistor
- Desired dead time \(D\)

The relevant parameters that should be entered into motorBench™ Development Suite are:

- Minimum duty cycle of the bridge \(d_{BMIN}=\max(d_{HMIN},1-d_{LMAX}-2D)\)
- Maximum duty cycle of the bridge \(d_{BMAX}=\min(1-d_{HMIN},d_{HMAX}+2D)\)

This will produce the range of duty cycles shown in Table 4.1.

Table 4.1 Duty cycle ranges for PWM waveforms
Waveform | Minimum duty cycle | Maximum duty cycle
--- | --- | ---
G | \(d_{BMIN} + D\) | \(d_{BMAX} - D\)
H | \(d_{BMIN}\) | \(d_{BMAX} - 2D\)
L | \(1-d_{BMAX}\) | \(1-d_{BMIN} - 2D\)

Usually the two minimum duty cycles \(d_{LMIN}\) and \(d_{HMIN}\) determine the duty cycle limits, not the maximum duty cycles.

To help clarify how this works, some concrete examples are given below.

#### 4.4.4.2.1. PWM peripheral in dsPIC33 devices

The PWM peripheral in dsPIC33EP parts splits the dead time in half, calculating edges for the low-side and high-side outputs so that they are centered in time around the “ideal” switching instant if there were no dead time. The widths of waveforms G, H, and L in Figure 4.4 are the same, but waveforms H and L are advanced in time by \(D/2\).

#### 4.4.4.2.2. Example 1

- High-side transistor must be limited between \(d_{HMIN}=1.2\%\) duty cycle and \(d_{HMAX} = 99\%\) duty cycle
- Low-side transistor must be limited between \(d_{LMIN}=3.0\%\) duty cycle and \(d_{LMAX} = 99.5\%\) duty cycle
- Dead time of 2%

This is a realistic case for a bootstrap gate drive, where \(d_{LMIN}\) is larger, to ensure adequate recharge time of the bootstrap capacitors.

We calculate

\[\begin{aligned} d_{BMIN} &= \max(0.012, 1 - 0.995 - 0.04) = 0.012 \cr d_{BMAX} &= \min (1 - 0.03, 0.99 + 0.04) = 0.97 \end{aligned}\]

The waveform values produced by this are shown in Table 4.2.

Table 4.2 Duty cycle ranges for Example 1
Waveform | Minimum duty cycle | Maximum duty cycle
--- | --- | ---
G | 0.032 | 0.95
H | 0.012 | 0.93
L | 0.03 | 0.948

Note that in this case, the limits are determined by the minimum duty cycles; the maximum duty cycles of the H and L waveforms are comfortably below their required maximum.

#### 4.4.4.2.3. Example 2

- High-side transistor must be limited between \(d_{HMIN} = 1.2\%\) duty cycle and \(d_{HMAX} = 90\%\) duty cycle
- Low-side transistor must be limited between \(d_{LMIN} = 3.0\%\) duty cycle and \(d_{LMAX} = 80\%\) duty cycle
- Dead time of 2%

We calculate

\[\begin{aligned} d_{BMIN} &= \max(0.012, 1 - 0.8 - 0.04) = 0.16 \cr d_{BMAX} &= \min (1 - 0.03, 0.9 + 0.04) = 0.94 \end{aligned}\]

The waveform values produced by this are shown in shown in Table 4.3.

Table 4.3 Duty cycle ranges for Example 2
Waveform | Minimum duty cycle | Maximum duty cycle
--- | --- | ---
G | 0.18 | 0.92
H | 0.16 | 0.90
L | 0.06 | 0.80

In this case, the limits are determined by the maximum duty cycles; the minimum duty cycles of the H and L waveforms are comfortably above their required minimum.

#### 4.4.4.2.4. Recommended values for use with motorBench™ Development Suite and MCLV-2

- High-side transistor must be limited between \(d_{HMIN} = 0.5\%\) duty cycle and \(d_{HMAX} = 99.5\%\) duty cycle
- Low-side transistor must be limited between \(d_{LMIN} = 2.23\%\) duty cycle and \(d_{LMAX} = 99.5\%\) duty cycle
- Dead time of 4%

We calculate

\[\begin{aligned} d_{BMIN} &= \max(0.005, 1 - 0.995 - 0.08) = 0.005 \cr d_{BMAX} &= \min (1 - 0.0223, 0.995 + 0.04) = 0.9777 \end{aligned}\]

The waveform values produced by this are shown in Table 4.4.

Table 4.4 Recommended duty cycle ranges for MCLV-2
Waveform | Minimum duty cycle | Maximum duty cycle
--- | --- | ---
G | 0.045 | 0.9377
H | 0.005 | 0.8977
L | 0.0223 | 0.915

Note that in this case, the limits are determined by the minimum duty cycles; the maximum duty cycles of the H and L waveforms are comfortably below their required maximum.

#### 4.4.4.2.5. Affected source code files

In MCAF R3, the generated file parameters/hal_params.h contains `#define` symbols to determine minimum and maximum duty cycles. There is also a comment that appears as follows:

Listing 4.1 `parameters/hal_params.h`

    /*
     * Minimum and maximum duty cycles,
     * from the perspective of the PWM duty cycle registers.
     *
     * The actual minimum and maximum duty cycles created by the PWM generators
     * will have dead time (=0.04) added and subtracted.
     *
     * NOTE: this assumes identical dead time,
     * and no significant difference in propagation delay between gate drive channels.
     *
     * Effective limits for duty cycle as seen on the PWM outputs:
     * Minimum duty cycle on PWMxH: 0.005
     * Minimum duty cycle on PWMxL: 0.0223
     * Maximum duty cycle on PWMxH: 0.8977
     * Maximum duty cycle on PWMxL: 0.915
     */

    /* The minimum duty cycle of the half-bridge affects
     * the minimum duty cycle of upper transistors
     * and maximum duty cycle of lower transistors.
     */
    /* Minimum duty cycle register value in counts */
    #define HAL_PARAM_MIN_DUTY_COUNTS             157      // Q0(157.00000)  =  +44.85714 m           =  +45.00000 m           - 0.3175%
    /* Minimum duty cycle register value, as ratio */
    #define HAL_PARAM_MIN_DUTY_Q15               1475      // Q15(  0.04501) =  +45.01343 m           =  +45.00000 m           + 0.0298%
    /* Maximum low-side duty cycle register value in counts */
    #define HAL_PARAM_MAX_LOWER_DUTY_COUNTS       3342      // Q0(3342.00000) = +954.85714 m           = +955.00000 m           - 0.0150%

    /* The maximum duty cycle of the half-bridge affects
     * the maximum duty cycle of upper transistors
     * and minimum duty cycle of lower transistors.
     */
    /* Maximum duty cycle register value in counts */
    #define HAL_PARAM_MAX_DUTY_COUNTS            3282      // Q0(3282.00000) = +937.71429 m           = +937.70000 m           + 0.0015%
    /* Maximum duty cycle register value, as ratio */
    #define HAL_PARAM_MAX_DUTY_Q15              30727      // Q15(  0.93771) = +937.71362 m           = +937.70000 m           + 0.0015%
    /* Minimum low-side duty cycle register value in counts */
    #define HAL_PARAM_MIN_LOWER_DUTY_COUNTS        218      // Q0(218.00000)  =  +62.28571 m           =  +62.30000 m           - 0.0229%

#### 4.4.4.2.6. Support for full on/off time in MCAF

MCAF does not support full on-time or off-time of either high-side or low-side transistor. This is a tricky feature to implement, because it represents a small jump discontinuity of the intended duty cycle.

### 4.4.4.3. Modules

#### 4.4.4.3.1. Core FOC

Module | Files | Description | Comments
--- | --- | --- | ---
`parameters/foc_params` | `parameters/foc_params.h` | FOC control parameters |
`parameters/init_params` | `parameters/init_params.c` `parameters/init_params.h` | Initialization of FOC control parameters |
`parameters/sat_PI_params` | `parameters/sat_PI_params.h` | PI Saturation parameters |
`foc` | `foc.c` `foc.h` `foc_types.h` | Top-level FOC | These functions are called from the state machine modules, as described in the implementation notes.
`sat_PI` | `sat_PI.c` `sat_PI.h` `sat_PI_types.h` | PI loop saturation management |

The `field_weak` module, covering flux weakening and not included in the above table, is presently disabled in MCAF R1, R2, and R3, and is being redesigned for a future version.

#### 4.4.4.3.2. Commutation

Module | Files | Description | Comments
--- | --- | --- | ---
`parameters/pll_params` | `parameters/pll_params.h` | PLL estimator parameters |
`commutation` | `commutation.c` `commutation.h` `commutation_types.h` | Top-level commutation / estimation |
`pll` | `pll.c` `pll.h` | PLL (AN1292 sensorless estimator) |
`qei` | `qei.c` `qei.h` | Quadrature encoder estimator | The quadrature encoder is used to obtain a reference position for testing estimator performance.