-T.K.- Lab Notes
  • Home
  • Convention Used
  • STM32
    • Getting Started - STM32 Edition
      • Setting up STM32CubeIDE
      • Going Through A Starter Project
      • Changing STM32CubeIDE Settings
      • Pinout Quick Reference
    • Misc
      • Using Nucleo STLink to Flash Off-board Chips
      • Changing STM32 Default Boot Option
      • STM32 Flash Option Byte Recovery
      • STM32 Systick and Timeout in Interrupt Routines
      • Telesky ST-Link V2 Upgrade Firmware
      • Some Performance Measurements on STM32 MCUs
    • System Core
      • Using GPIO on STM32
      • Setting up External Interrupt on STM32
    • Analog
      • Using ADC on STM32
      • ADC Reading Sequence with DMA on STM32
      • Using OPAMP on STM32
      • Using DAC on STM32
    • Timers
      • Using RTC on STM32
      • Using TIM on STM32
    • Connectivity
      • UART
      • USART
        • USART - CAN Dongle (Fixed Size Serializer with Robust Timeout Handling)
      • CAN
      • FDCAN
      • I2C
      • SPI
        • SPI - GC9A01A LCD Screen
        • SPI - RFID
        • SPI - SD Card
      • Ethernet
        • Ethernet - LWIP
        • Ethernet - UDP
        • Ethernet - UDP Multicast
      • USB - FS
      • USB - HS
    • Middleware
      • FreeRTOS
    • Software Pack
      • STMicroelectronics.X-CUBE-AI - Sine Approximator
  • RISC-V / SoC
    • RISC-V: Baremetal From The Ground Up (Chipyard Edition)
    • Quick Start With Chipyard on Ubuntu or WSL
    • Other Chipyard Stuff
      • Debugging OsciArty with JTAG and command line GDB
      • Debugging BearlyML with JTAG and GDB
      • Booting BearlyML With External SPI Flash
      • Setting Up SD / microSD Card for vcu118 Linux Image
      • More Chipyard Stuff
    • A Minimal Chisel Development Environment with Mill
    • Vivado Stuff
      • Installing Xilinx Vivado on Ubuntu 22.04 / 24.04
      • Arty 35T / 100T UART Pins
      • Configuring Vivado DDR MIG on Arty 35T
      • Configuring Vivado DDR MIG on Nexys Video
      • Vivado Generate Flash Config .mcs File From Bitstream
      • Vivado TCL Scripts
    • Adding Custom Instructions to RISC-V GCC Toolchain
    • Kendryte K230 Bringup
      • K230 EVB Board Resource Overview
    • Intel FPGA Quartus
    • Setting up RISC-V Toolchain on Ubuntu 24.04/22.04
    • Getting Started with Zephyr
      • Getting Start with Zephyr on RISC-V System - Windows
      • Getting Started with Zephyr on RISC-V - Ubuntu
    • C Library Compile Magic
    • Setting up ExecuTorch on Ubuntu 22.04
      • Executorch on ARM
  • Motor Control
    • Recoil FOC Motor Controller
      • 0x00. Theory of Operation
      • 0x01. Components
      • 0x02. Implementation
      • 0x03. Application
    • Recoil Documentation
    • New Controller Board Soldering & Power-on Checklist
    • MJBOTS Moteus setup
    • Failed Attempt on Acceleration- and Velocity-Limited Trajectory Generation
    • Moteus Code Analyze
    • MIT Motor Controller Code Analyze
    • ODrive Setup
    • Setting up Recoil USB-CAN Adapter
      • Setting up Recoil USB-CAN Adapter - Ubuntu
      • Setting up Recoil USB-CAN Adapter - Windows
    • NTC Temperature Sense Resistor Value Calculation
  • ML/RL
    • Setting up NVIDIA Tools
      • Setting up NVIDIA Driver on Ubuntu 22.04 / 20.04
      • Getting Started with NVIDIA Isaac Lab on Ubuntu 22.04 / 24.04
      • Setting up Omniverse on Ubuntu 24.04 (2025 Ver)
      • Creating Custom Training Environment in IsaacLab via Extensions
      • NVIDIA Isaac Gym URDF Import Notes
      • Setting up TensorRT Environment on Ubuntu 22.04 / 20.04
      • Setting up NVIDIA Omniverse Isaac Sim on Ubuntu 22.04 / 20.04
      • Setting up NVIDIA Nsight System and Nsight Compute on Ubuntu 24.04
      • Getting Started with Jetson AGX Orin
        • Getting Started with Jetson Using SDK Manager on Ubuntu 22.04
        • Using Jetson AGX Orin with Provided Ubuntu 20.04 System
        • Setting up Common Software on Jetson AGX Orin
        • Solving USB-CAN and USB CH340 Driver Issue on reComputer Mini J4012
        • [Deprecated] Upgrading Jetson AGX Orin to Ubuntu 22.04
      • Solving Torch Errors
      • [Deprecated] Setting up NVIDIA Isaac Gym on Ubuntu 22.04 / 20.04
    • RL Frameworks
      • Case Study: A Dive Into LeggedGym and RSL-RL Framework
      • Case Study: A Dive Into IsaacLab
      • Getting Started with Mujoco
      • Case Study: A Dive Into Unitree-Mujoco
      • Case Study: Setting up Berkeley Humanoid
      • Case Study: Looking into robot_lab
      • Case Study: Setting up RL-SAR
      • Case Study: Getting Started with LeRobot
      • Case Study: No-Mercy Project
        • Python Mouse and Keyboard Interaction in Game Environment
        • Detecting Phara
      • OpenAI gym + Mujoco Setup
      • Gazebo Setup
    • ROS
      • Setting up ROS on Ubuntu 20.04
      • Setting up ETH ANYbotics/elevation_mapping on Ubuntu 20.04
    • ROS 2
      • Setting up ROS 2 Humble Hawksbill on Ubuntu
      • Setting up ROS 2 Humble Hawksbill on Windows 10
      • ROS 2 Issue in Ubuntu with conda
    • Google Colab
      • Colab Resource Options
      • so-vits-svc 4.0: Colab Flow
    • URDF to MJCF Mujoco Notes
    • OnShape to URDF
    • Audio Stuff
      • Microsoft TTS
      • GPTSoVITS
      • 深入浅出理解 So-VITS-SVC 原理
      • NAI-SVC Experiment Log
      • Setting up ChatTTS on Ubuntu 22.04
    • Setting up AnythingLLM on Ubuntu 22.04
    • Setting up MineDojo Environment
    • Processing the SFU Motion Capture Dataset
    • Torch Profiling
    • Setting up Unitree A1
  • 3D Modeling
    • 3D Print Tolerancing
    • Blender to OnShape Workflow
    • Onshape to Blender Workflow
    • Setting up FBX Plugin for Python on Ubuntu 22.04
    • Install Blender on Ubuntu 22.04
    • Blender Python Related
    • VRoid, MMD, Blender Workflow
  • Tools
    • Windows
      • Install WSL 2
      • Install Make on Windows
      • Remove EFI disk partition
      • SAI Color Flip/Color Inversion
      • Microsoft Visual Studio Create Software Signature
      • Connecting the SIGLENT SDS1104X-U Oscilloscope to Computer
      • Using JADENS Thermal Label Printer
      • Getting Started with XBee (ZigBee)
    • Ubuntu
      • Ubuntu 22.04 Standard Installation Procedure
      • Protobuf
      • Setting up Docker on Ubuntu 22.04
      • Linux Mounting SD Card
      • Partitioning SD card
      • Windows Ubuntu Dual Boot Issues
      • Check Disk / Folder / File Size
      • Test Disk Read/Write Speed
      • Cannot Start Chrome in Ubuntu 22.04 After Changing Network Settings
      • Configure USB Access Permissions (udev rules) on Ubuntu
      • Screen Commands
      • Disabling the "<Application> is not responding." System Message on Ubuntu
      • Install and Configure GlobalProtect UC Berkeley VPN Service on Ubuntu 22.04
      • Solving Gamepad not Detected on Ubuntu 22.04
      • Using 3DConnexion Mouse on Ubuntu with Python
      • Install Cursor the AI Editor on Ubuntu 22.04/24.04
      • Solving the .nfsXXX file cannot be deleted issue
      • Windows Remote Desktop Issues
      • nsswitch.conf
    • Lab Automation
    • Github-Related Info
    • Python
      • Publish Python Package to PyPi
      • Python Logging Utility
      • Python converting bettwen JSON and XML
      • Retrieve Github user avatar with Github API
      • Jupyter Notebook Error
    • Raspberry Pi Setup
    • Clang-Format Style Config
    • CrazyFlie Setting Up
    • Using Oscilloscope: x1 vs x10
    • Using the BWRC 3D Printer
    • Using the Leica Microscope at BWRC
    • Pair XBoxController to Raspberry Pi with Bluetooth
    • Reading FrSky Transmitter SBUS data with STM32
    • Configuring the FrSky TARANIS X9D Plus 2019 RC Controller
    • Applying Notion for Education
    • Gitbook Errata
    • Setting up SteamVR without HMD
    • CMake Best Practices
    • Adobe Premiere Pro Audio Level Settings
  • Mechanical
    • MAD Cycloidal Actuator
    • Dog Stuff
      • Fixing the Unitree A1 Robot Dog Leg Motor
      • Fixing the Unitree A1 Robot Dog Ethernet Port
      • Fixing MIT Mini Cheetah
      • Fixing the Unitree Go1 Robot Dog Ethernet Port
    • 3D Printer Profile
  • Electrical
    • A Note on the Polarity of the Famous TT Motor
    • Wiring Pinmap Convention
    • MCU Pinmap Convention
    • PCB Design and Manufacturing Conventions
    • ESP32 Cam
    • LiPo Safety
    • AS5600 Modification
    • OpenOCD and FTDI Chips
    • FT-LINK FTDI Debugger Design Considerations
    • A Study on Reset Pin Connection
    • Note on CAN Termination Resistor
  • UW
    • Digital-Twin Communication System
    • Unreal Engine Communicate with SteamVR
    • Unreal Engine Socket Communication
    • A Note on Coordinate Systems
    • NewLine Serialization Method
    • Humanoid Design Notes
      • Robot Body Ratio Issue
      • VRM Parameters
      • Note on Face Design and Manufacture
  • Workflow Automation
    • RISC-V Toolbox Website
    • Zigbee-Based Home Automation
      • Setting up Home Assistant on Raspberry Pi to Control Zigbee IoT Devices
      • Update Sonoff Zigbee 3.0 USB Dongle Plus (CC2652P)
  • Finance
    • Finance
    • UC Berkeley Reimbursement
  • Life
    • Some Interview Questions
    • Health Insurance
Powered by GitBook
On this page
  • 0. 无刷电机 Brushless DC Motor
  • 1. 最基础的: 六步换向 The Most Basic: Six-Step Commutation
  • 2. 增加效率: 矢量驱动 Efficiency Improved: Vector Control
  • 3. 参考系变换 Frame Transform
  • Alpha Beta Transform
  • DQ Transform
  • Inv DQ Transform
  • SVPWM
  • 4. 电流环 Current Loop
  • 电机模型 Model of Motor
  • PI Controllers
  • System Model
  • Reference
  • 5. 扭矩控制 Torque Control
  • 6. 位置环 Position Loop
  • 7. 总结 Result

Was this helpful?

  1. Motor Control
  2. Recoil FOC Motor Controller

0x00. Theory of Operation

Last updated 3 months ago

Was this helpful?

0. 无刷电机 Brushless DC Motor

一个直流无刷电机由许多的线圈和磁铁组成。为了能够让我们更容易理解它是怎么运行的,我们可以把它化简为最简单的形式 —— 三组线圈,一对磁铁,按这种方式排列。

A brushless direct-current (BLDC) motor is composed of magnets and phase winding coils. To understand the operating principle, we can simplify the motor down to one magnet pole pair and three coils.

线圈被固定在电机的定子上面。当电流流经线圈,就会产生磁场,吸引或排斥这个线圈正对着的磁铁磁极,从而使转子转动。

The coils form the stator of the motor. When current passes through the coil, a magnetic field will be produced, which then attracts or repels the magnet facing this coil. The magnet, which forms the rotor of the motor, then rotates.

1. 最基础的: 六步换向 The Most Basic: Six-Step Commutation

我们将这三组线圈的六个端子连接起来,形成三个接线端连接电机的驱动电路。我们有两种连接的方式 —— 星接 (star connection / wye connection) 或 角接 (delta connection)。常见的航模无刷电机都采用星接的方法,三组线圈的一端各引出一根引线,而另一端在内部互相连接到一起,构成中性极。

The end of the three coils are tied together to form three terminals, connecting to the driving circuit. There are two ways to do the connection —— the star connection (sometimes called wye connection), or the delta connection. The star connection is the more common one, where one end of the three coils is exposed as external wire, while the other end of the three coils is tied together to form an internal neutral point.

我们使用名为三相逆变器的电路来驱动这三根引线。如图所示,这个电路由三个半桥驱动器构成,每个半桥又有两个开关,这两个开关可以构成如下四种状态

  • 上开下关 (1)

  • 上关下开 (0)

  • 上开下开 (X)

  • 上关下关 (N)

其中,X 为无效状态,会直接将 VCC 和 GND 短路;我们这里也不考虑 N 状态,因为这样会将这相线圈悬空,电流无法流过,电机驱动效率就会下降 (这里我们不考虑正常六步换向法需要观测反电动势的需求)。剩下的两种状态里,1 状态下会将引线连接 VCC,而 0 状态会将引线连接 GND。

To drive these three wires, we use a three-phase inverter circuit. The circuit is composed of three half-bridge drivers, and we can see it as six switches connecting across VDD and GND. There are four states for each of the half-bridge:

  • High-side ON, low-side OFF (1)

  • High-side OFF, low-side ON (0)

  • High-side ON, low-side ON (X)

  • High-side OFF, low-side OFF (N)

Among the states, X is an invalid state. It directly connects VCC to GND. N states is not used here, as in this state, the phase coil is in float state, which harms the maximum output capability of the driver. In the remaining two states, state 1 will connect the phase to VCC, while state 0 will connect the phase to GND.

将三组半桥驱动器组合起来,我们就获得以下八种三相逆变器的状态

  • 000

  • 100

  • 110

  • 010

  • 011

  • 001

  • 101

  • 111

其中,000 和 111 为无驱动状态,这时电机的三相全部连接 VCC 或 GND,线圈之间没有电压差。

剩下的六种状态都会使线圈中有电流流动,我们可以来分析一下。

首先,我们将驱动器设定为 100 状态。在这个状态中,A 相线圈连接 VCC,电流经 A 流向中点,然后经 B 和 C 流向 GND。假设线圈产生的磁场指向 A 线圈方向 (0°),转子的磁铁因此被磁铁吸引,也指向 A 线圈。

接下来,切换到 110 状态。A B 线圈都连接 VCC,电流经 A 和 B 流向中点,然后经 C 流向 GND。线圈产生的磁场叠加指向 A 和 B 线圈的中间 (30°),转子因此也转向 30° 方向。

以此类推,010 状态使转子转向 60° 方向;011 状态使转子转向 90° 方向;001 状态使转子转向 120° 方向;101 状态使转子转向 150° 方向;最后回到 100 状态,转子旋转一周返回原点。

因此,将这六种驱动状态按顺序排列,我们就实现了六步换向。

Combining the two states of three phases together, we have the following eight inverter states.

  • 000

  • 100

  • 110

  • 010

  • 011

  • 001

  • 101

  • 111

States 000 and 111 are non-driving states. The phases are all connected to VCC or GND, and there’s no voltage differential between phases.

The rest 6 states are driving states.

Assume the motor is in state 100. Phase A will be connected to VCC, and B and C are connected to GND. Current will flow from phase A, through the neutral point, to B and C, and finally to GND. The phases will generate a magnetic field pointing at phase A’s direction (0°). The magnets on the rotor will be attracted, turning the rotor to 0°.

Next, by switching to state 110, phase A and B are connected to VCC, while phase C is connected to GND. The resulting magnetic field will point between phase A and B (30°), thus turning the rotor to 30° direction.

Similarly, in the rest of the state, the rotor will be turned to 60°, 90°, 120°, 150°, respectively, and finally back to 0° in state 100.

As a result, when the states are switched in this order, the motor can be driven correctly.

2. 增加效率: 矢量驱动 Efficiency Improved: Vector Control

在任一转子角度下,我们都可以将线圈产生的力分解为垂直于转子方向的分力 FdF_dFd​,和平行于转子方向的分力 FqF_qFq​ 。

垂直于转子方向的分力 FdF_dFd​ 并不会驱动转子转动。换句话说,FdF_dFd​ 是浪费的。因此,我们需要想办法减小 FdF_dFd​,将所有的电流都集中产生 FqF_qFq​ 驱动转子转动。

If we analyze the magnetic force on posed on the rotor, at any moment, there is a force FdF_dFd​ vertical to the rotor magnet and a force FqF_qFq​ parallel to the rotor magnet.

FdF_dFd​ will not contribute to the rotation of the rotor, and thus is a loss. To drive the motor efficiently, we want to minimize FdF_dFd​ and maximize FqF_qFq​.

3. 参考系变换 Frame Transform

由于电机的项电压总是浮动的,没有一个标准的参考地,我们不便添加功率电阻进行采样。更简单的方案是在低端 MOSFET 下面添加电阻进行采样,获得三个近似 sine 波的相电流 IaI_aIa​、IbI_bIb​ 和 IcI_cIc​。但是,我们没办法直接使用这三个非线性电流读数作为对于电压的控制输入。因此,我们需要对电流进行一些数学变换,将他转换为简单的线性变量来控制。

Alpha Beta Transform

电机的相电流,IaI_aIa​、IbI_bIb​ 和 IcI_cIc​,是三个互成 120° 夹角的近似于 sine 波的旋转矢量。三相电流都处于一个平面内,因此我们可以使用 Clark 变换将它们转化为两个互相垂直的矢量 IalphaI_{alpha}Ialpha​ 和 IbetaI_{beta}Ibeta​。

The three phase currents, IaI_aIa​、IbI_bIb​ and IcI_cIc​, are three sine-like rotating vectors that are at a 120° offset with each other. Because they share a same plane, Clark transform can be used to convert them to two orthogonal vectors IalphaI_{alpha}Ialpha​ and IbetaI_{beta}Ibeta​.

{Iα=Ia+cos(23π)Ib+cos(43π)IbIβ=sin(23π)Ib+sin(43π)Ic\begin{cases} I_\alpha = I_a + cos(\frac{2}{3}\pi)I_b + cos(\frac{4}{3}\pi)I_b \\ I_\beta = sin(\frac{2}{3}\pi) I_b + sin(\frac{4}{3}\pi)I_c \end{cases}{Iα​=Ia​+cos(32​π)Ib​+cos(34​π)Ib​Iβ​=sin(32​π)Ib​+sin(34​π)Ic​​

OR,

[IαIβ]=[1cos(23π)cos(43π)0sin(23π)sin(43π)][IaIbIc]\begin{bmatrix} I_\alpha \\ I_\beta \end{bmatrix} = \begin{bmatrix} 1 & cos(\frac{2}{3}\pi) & cos(\frac{4}{3}\pi) \\ 0 & sin(\frac{2}{3}\pi) & sin(\frac{4}{3}\pi) \\ \end{bmatrix} \begin{bmatrix} I_a \\ I_b \\ I_c \\ \end{bmatrix}[Iα​Iβ​​]=[10​cos(32​π)sin(32​π)​cos(34​π)sin(34​π)​]​Ia​Ib​Ic​​​

DQ Transform

接下来,我们可以使用 Park 变换将 IalphaI_{alpha}Ialpha​ 和 IbetaI_{beta}Ibeta​ 相对于转子角度反向旋转,这样就可以将两个 sine 波转换为两个 DC 的电流信号,IqI_qIq​ 和 IdI_dId​。

Then, Park transform can be used to convert the rotating IalphaI_{alpha}Ialpha​ and IbetaI_{beta}Ibeta​ to two stationary vectors IqI_qIq​ and IdI_dId​.

{Iq=−sin(θ)Iα+cos(θ)IβId=cos(θ)Iα+sin(θ)Iβ\begin{cases} I_q = -sin(\theta)I_\alpha + cos(\theta)I_\beta \\ I_d = cos(\theta)I_\alpha + sin(\theta)I_\beta \end{cases}{Iq​=−sin(θ)Iα​+cos(θ)Iβ​Id​=cos(θ)Iα​+sin(θ)Iβ​​

OR,

[IqId]=[−sin(θ)cos(θ)cos(θ)sin(θ)][IαIβ]\begin{bmatrix} I_q \\ I_d \end{bmatrix} = \begin{bmatrix} -sin(\theta) & cos(\theta) \\ cos(\theta) & sin(\theta) \\ \end{bmatrix} \begin{bmatrix} I_\alpha \\ I_\beta \\ \end{bmatrix}[Iq​Id​​]=[−sin(θ)cos(θ)​cos(θ)sin(θ)​][Iα​Iβ​​]

Inv DQ Transform

同样地,我们可以将我们希望的电压 VqV_qVq​ 和 VdV_dVd​ 通过逆 Park 变换转化为和转子一起旋转的信号 ValphaV_{alpha}Valpha​ 和 VbetaV_{beta}Vbeta​。

SVPWM

这里我们和电流的变换操作有些不同,因为我们的电压最终控制的是数字量 0 或者 1,对应上下桥臂的 MOSFET 的开关,而不是电流采样的模拟量。因此,我们需要用另一套方法将我们希望的电压离散化。

由上文,我们知道我们的驱动器有六种基础状态。我们可以将这六种状态视为六个基础矢量,从原点分别指向 0°,30°,60°…

而如果我们在两种状态之间快速切换,并且控制每种状态的时间占比,我们就可以合成出一个指向某一方向的叠加矢量。

更进一步,我们还可以添加上之前的两种无驱动状态 000 和 111。他们在上图中就是幅值为 0 的零矢量。因此,通过控制他们的时间占比,我们便可以控制合成矢量的幅值。

From the six-step commutation scheme, we know that the motor driver can generate forces pointing in six different directions. We can view these forces as six fundamental vectors, pointing from the origin to 0°,30°,60°…

If we control the motor driver such that it switches between two states in a short time and controls the percentage of each state, we can form a resulting force pointing in between the two fundamental vectors.

Moreover, by including the two non-driving states, which are two zero vectors, we can also change the magnitude of the resulting vector.

4. 电流环 Current Loop

由上面的框图得知,我们的被控量是 VqV_qVq​ 和 VdV_dVd​,控制量是 IqI_qIq​ 和 IdI_dId​。相对简单的方法是使用一个 PI 控制器。

The variable we want to control is voltage Vq and Vd, and we need to regulate Iq and Id to achieve this. A simple way to do this is using a PI controller.

电机模型 Model of Motor

我们可以将电机简化为串联的电阻和电感,由此我们可以得出如下关系式。

The motor can be seen as a resistor and inductor in series, and therefore we have the following equation.

V=IR+LdIdt+kemfωV = IR + L\frac{dI}{dt} + k_{emf}\omegaV=IR+LdtdI​+kemf​ω

由于我们只关注相对低转速的情况,电机产生的反电动势可以忽略不计。

Since we are focusing on low-rpm scenario, the back-EMF term can be ignored.

V=IR+LdIdtV = IR + L\frac{dI}{dt}V=IR+LdtdI​

将上面的公式进行拉普拉斯变换,我们得到

performing Laplace transform, we get

V(s)=I(s)R+LsI(s)−LI(0)V(s) = I(s)R + LsI(s) - LI(0)V(s)=I(s)R+LsI(s)−LI(0)

assuming initial condition I(0) = 0, we get

V(s)=I(s)R+LsI(s)V(s) = I(s)R + LsI(s)V(s)=I(s)R+LsI(s)

As result, the model of motor is

M(s)=I(s)V(s)=1R+Ls=1R1+LRsM(s) = \frac{I(s)}{V(s)} = \frac{1}{R + Ls} = \frac{\frac{1}{R}}{1 + \frac{L}{R}s}M(s)=V(s)I(s)​=R+Ls1​=1+RL​sR1​​

PI Controllers

There are two configurations of PI controller, the parallel configuration (the most common one) and the series configuration.

Parallel PI Controller

For parallel configuration, we have

c(t)=kpe(t)+ki∫e(t)dtc(t) = k_p e(t) + k_i \int e(t) dtc(t)=kp​e(t)+ki​∫e(t)dt
C(s)=kp+kis=kps+kisC(s) = k_p + \frac{k_i}{s} = \frac{k_p s + k_i}{s}C(s)=kp​+ski​​=skp​s+ki​​

Serial PI Controller

For series configuration, we have

c(t)=kp′e(t)+kp′ki′∫e(t)dtc(t) = k_p' e(t) + k_p' k_i' \int e(t) dtc(t)=kp′​e(t)+kp′​ki′​∫e(t)dt
C(s)=kp′(1+kis)=kp′s+kp′ki′sC(s) = k_p' (1 + \frac{k_i}{s}) = \frac{k_p's + k_p'k_i'}{s}C(s)=kp′​(1+ski​​)=skp′​s+kp′​ki′​​

The C implementation is

float kp, ki;
float target, measured;
float limit;  // integrator anti-windup value
float dt;     // loop execution time
float integrator;

float error = target - measured;
integrator = clampf(integrator + kp * ki * error * dt, -limit, limit);
float result = kp * error + integrator;

System Model

For open loop control, we have the transfer function as

Gopen(s)=M(s)C(s)=1R1+LRskp′s+kp′ki′sG_{open}(s) = M(s)C(s) = \frac{\frac{1}{R}}{1 + \frac{L}{R}s} \frac{k_p's + k_p'k_i'}{s}Gopen​(s)=M(s)C(s)=1+RL​sR1​​skp′​s+kp′​ki′​​
Gopen(s)=1R1+LRskp′ki′ski′+1sG_{open}(s) = \frac{\frac{1}{R}}{1 + \frac{L}{R}s} k_p'k_i' \frac{\frac{s}{k_i'} + 1}{s}Gopen​(s)=1+RL​sR1​​kp′​ki′​ski′​s​+1​

In order to simplify the equation, we need

1+LRs=ski′+11 + \frac{L}{R}s = \frac{s}{k_i'} + 11+RL​s=ki′​s​+1
ki′=RLk_i' = \frac{R}{L}ki′​=LR​

Setting ki′=RLk_i' = \frac{R}{L}ki′​=LR​, we can simplify the equation as

Gopen(s)=kp′ki′1RsG_{open}(s) = k_p'k_i' \frac{\frac{1}{R}}{s}Gopen​(s)=kp′​ki′​sR1​​

For closed-loop feedback control, we have the transfer function as

Gclosed(s)=Gopen(s)1+Gopen(s)G_{closed}(s) = \frac{G_{open}(s)}{1 + G_{open}(s)}Gclosed​(s)=1+Gopen​(s)Gopen​(s)​

Therefore,

Gclosed=kp′ki′1Rs1+kp′ki′1RsG_{closed} = \frac{k_p'k_i' \frac{\frac{1}{R}}{s}}{1 + k_p'k_i' \frac{\frac{1}{R}}{s}}Gclosed​=1+kp′​ki′​sR1​​kp′​ki′​sR1​​​

substitute ki′=RLk_i' = \frac{R}{L}ki′​=LR​ into the equation, we can get

Gclosed=kp′RL1Rs1+kp′RL1Rs=kp′1Ls+kp′1L=1skp′L+1G_{closed} = \frac{k_p'\frac{R}{L} \frac{\frac{1}{R}}{s}}{1 + k_p'\frac{R}{L} \frac{\frac{1}{R}}{s}} = \frac{k_p' \frac{1}{L}}{s + k_p '\frac{1}{L}} = \frac{1}{\frac{s}{\frac{k_p'}{L}} + 1}Gclosed​=1+kp′​LR​sR1​​kp′​LR​sR1​​​=s+kp′​L1​kp′​L1​​=Lkp′​​s​+11​

The coefficient kp′L\frac{k_p'}{L}Lkp′​​ determines the frequency where the system response decreases by 3dB, or, the response cutoff bandwidth ω. The unit is rad/s.

In other words, we have

kp′=L∗ωcutoffk_p' = L * \omega_{cutoff}kp′​=L∗ωcutoff​
ωcutoff=kp′L\omega_{cutoff} = \frac{k_p'}{L}ωcutoff​=Lkp′​​

with ω=2πf\omega = 2\pi fω=2πf,

fcutoff=12πkp′Lf_{cutoff} = \frac{1}{2\pi}\frac{k_p'}{L}fcutoff​=2π1​Lkp′​​

Usually in practice, we want to ensure that the current sampling rate is 10% of the switching frequency, i.e. 20% of the Nyquist rate.

kp,max′=2π10TsampleL=2π10fsampleLk_{p, max}' = \frac{2\pi}{10} T_{sample} L = \frac{2\pi}{10} f_{sample} Lkp,max′​=102π​Tsample​L=102π​fsample​L

For example, if the switching frequency is 20kHz, the maximum bandwidth would be 2kHz.

kp,2kHz′=2πL∗2∗103k_{p, 2kHz}' = 2 \pi L * 2*10^3kp,2kHz′​=2πL∗2∗103

Reference

5. 扭矩控制 Torque Control

一般情况下,我们想控制电机的输出扭矩,而不是电流。因此,我们需要建立 IqI_qIq​ 与输出扭矩 τ\tauτ 的关系。

Usually, we want to control the motor's output torque, instead of the current. Therefore, we must establish the relation between current IqI_qIq​ and the output torque τ\tauτ.

扭矩又和相电流成正比,有如下比例关系:

τ=Kτ×I\tau = K_\tau \times Iτ=Kτ​×I
Kτ=602πKVK_\tau = \frac{60}{2\pi K_V}Kτ​=2πKV​60​

其中,KτK_\tauKτ​ 为扭矩常数,KVK_VKV​ 为电机速度常数 (kRPM/VkRPM / VkRPM/V)

We demonstrated how switching between different driving states can create an arbitrary vector. However, the control input of the motor driver is voltage, while we want to control the output torque. Output torque is proportional to phase current, in following relationship:

KτK_\tauKτ​ is the torque constant witth unit N/A. KVK_VKV​ is the motor KV constant with unit kRPM/V.

6. 位置环 Position Loop

同样,通过传感器的位置读数,我们可以在电流环的基础上搭建位置环,进行指定位置的控制。

7. 总结 Result

我们由此得出如下控制框图

Reference:

Digital PI Controller Equations

Six Step Commutation - MathWorks
https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/902/PI-controller-equations.pdf