DAB 电感电流有效值最优化调制:嵌入式工程师实战指南
关键词:双有源桥(DAB)、三重移相(TPS)、电流有效值优化、嵌入式控制、C2000、STM32
前言:为什么我们要"折腾"调制策略?
做数字电源的工程师都知道,双有源桥(DAB)是个好东西:双向能量流动、天然的软开关(ZVS)潜力、高功率密度。传统的单移相(SPS)控制非常简单,一个移相角 DssD_{ss}Dss 走天下。
但是,SPS 有个致命伤:
当输入输出电压不匹配(M≠1M \neq 1M=1)或者轻载时,电感电流有效值(IrmsI_{rms}Irms)会急剧增大。电流大了意味着什么?意味着 MOSFET 的导通损耗(I2RI^2RI2R)飙升,变压器发热,效率断崖式下跌。
为了解决这个问题,学术界提出了三重移相(TPS/DRM),增加了两个自由度(Dp0,Ds0D_{p0}, D_{s0}Dp0,Ds0)。然而,大多数论文推导极其复杂,满篇的 KKT 条件和四阶方程,让人望而生畏。
这篇博客的目的,就是把复杂的数学包装撕掉,告诉你作为一个嵌入式软件工程师,如何在 MCU(如 TI C2000 或 STM32)上,用最简单的 if-else 逻辑和查表法,实现 DAB 的电感电流有效值最优化调制。

一、核心思想:把负载切成三段
论文通过复杂的数学推导(GOC 全局优化条件),最终得出了一个对我们写代码非常友好的结论:
不需要实时解复杂的优化方程。只需要在不同的功率区间,采用固定的简化策略即可。
这个功率区间由电压传输比 MMM 和 控制量 DcD_cDc 决定。
1.1 两个关键变量
在写代码前,你必须先算好这两个全局变量:
① 电压传输比 MMM
M=N⋅VrefVinM = \frac{N \cdot V_{ref}}{V_{in}}M=VinN⋅Vref
| 符号 | 含义 | 来源 |
|---|---|---|
| NNN | 变压器匝比 | 硬件常量 |
| VrefV_{ref}Vref | 输出电压设定值 | 系统参数 |
| VinV_{in}Vin | 输入电压采样值 | ADC 实时采样 |
物理意义:MMM 决定了系统是工作在降压(M<1M<1M<1)还是升压(M>1M>1M>1)状态。
② 控制量 DcD_cDc
| 属性 | 说明 |
|---|---|
| 来源 | 电压环 PI 控制器的输出 |
| 范围 | 通常归一化到 [0,1.5][0, 1.5][0,1.5] |
| 物理意义 | 代表当前的功率需求。DcD_cDc 越大,负载越重 |
一句话理解 DcD_cDc:它就是电压环 PI 控制器输出的"归一化占空比指令",反映了"当前负载有多重"。
1.2 三段式最优策略(核心结论)
无论 MMM 是多少,最优策略都可以归纳为以下三种:
| 工况 | 判断条件 | 核心动作 | 一句话解释 |
|---|---|---|---|
| 重载 HLS | Dc≥1D_c \ge 1Dc≥1 | 退化为 SPS (Dp0=0,Ds0=0D_{p0}=0, D_{s0}=0Dp0=0,Ds0=0) |
功率太大,复杂的调制反而增加损耗,老老实实用传统单移相 |
| 中载 MLS | M≤Dc<1M \le D_c < 1M≤Dc<1(M<1M<1M<1) 或 1/M≤Dc<11/M \le D_c < 11/M≤Dc<1(M>1M>1M>1) |
固定一边 (Ds0=0D_{s0}=0Ds0=0 或 Dp0=0D_{p0}=0Dp0=0) |
牺牲一点点自由度,换取电流的大幅降低,性价比最高 |
| 轻载 LLS | Dc<MD_c < MDc<M(M<1M<1M<1) 或 Dc<1/MD_c < 1/MDc<1/M(M>1M>1M>1) |
消除环流 (满足特定等式) |
轻载时主要敌人是环流(不做功的电流),通过特定组合消除它 |
二、公式速查表(直接复制用)
下面的表格总结了所有你需要用到的公式。公式已经过工程简化,去掉了复杂的推导过程。
2.1 降压工况 M<1M < 1M<1(如电池放电、正向传输)
| 工况 | 判断条件 | Dp0D_{p0}Dp0 | Ds0D_{s0}Ds0 | DssD_{ss}Dss | 论文式号 |
|---|---|---|---|---|---|
| 重载 | Dc≥1D_c \ge 1Dc≥1 | 000 | 000 | 12M∗[(2Dc−3)∗(1−1−M2)+M]\dfrac{1}{2M}*[(2D_c-3)*(1-\sqrt{1-M^2})+ M]2M1∗[(2Dc−3)∗(1−1−M2)+M] | (3-21) |
| 中载 | M≤Dc<1M \le D_c < 1M≤Dc<1 | 1−Dc1-D_c1−Dc | 000 | Dp0−1+M+MDp0+(1−M)2+M2(1−Dp02)2M\dfrac{D_{p0}-1 +M+ MD_{p0} + \sqrt{(1-M)^2+ M^2(1-D_{p0}^2)}}{2M}2MDp0−1+M+MDp0+(1−M)2+M2(1−Dp02) | (3-19) |
| 轻载 | Dc<MD_c < MDc<M | 1−Dc1 - D_c1−Dc(示例映射) | 1−1−Dp0M1 - \dfrac{1 - D_{p0}}{M}1−M1−Dp0 | (1−M)(1−Dp0)M\dfrac{(1-M)(1-D_{p0})}{M}M(1−M)(1−Dp0) | (3-13) |
中载公式辅助函数(M<1M<1M<1):
float calc_MLS_lt1(float Dp0, float M) {
float t1 = (Dp0 - 1.0f + M + Dp0 * M) / (2.0f * M);
float sq = (1.0f - M)*(1.0f - M) + M*M*(Dp0*Dp0 - 1.0f);
if (sq < 0) sq = 0;
return t1 + sqrtf(sq) / (2.0f * M);
}
2.2 升压工况 M>1M > 1M>1(如电池充电、反向传输)
| 工况 | 判断条件 | Dp0D_{p0}Dp0 | Ds0D_{s0}Ds0 | DssD_{ss}Dss | 论文式号 |
|---|---|---|---|---|---|
| 重载 | Dc≥1D_c \ge 1Dc≥1 | 000 | 000 | 12∗[(2Dc−3)∗(M−M2−1)+1]\dfrac{1}{2}*[(2D_c-3)*(M-\sqrt{M^2-1})+ 1]21∗[(2Dc−3)∗(M−M2−1)+1] | (3-27) |
| 中载 | 1/M≤Dc<11/M \le D_c < 11/M≤Dc<1 | 000 | 1−Dc1-D_c1−Dc(示例映射) | 1−Ds0−M+MDs0+Ds02−1+M2(1−Ds0)22\dfrac{1 - D_{s0} - M + M D_{s0} + \sqrt{D_{s0}^2 - 1 + M^2(1-D_{s0})^2}}{2}21−Ds0−M+MDs0+Ds02−1+M2(1−Ds0)2 | (3-25) |
| 轻载 | Dc<1/MD_c < 1/MDc<1/M | 1−Dc1-D_c1−Dc | 1−M(1−Ds0)1-M(1-D_{s0})1−M(1−Ds0) | 000 | (3-23) |
中载公式辅助函数(M>1M>1M>1):
float calc_MLS_gt1(float Ds0, float M) {
float t1 = (1.0f - Ds0 - M + M * Ds0) / 2.0f;
float sq = Ds0*Ds0 - 1.0f + M*M*(1.0f - Ds0)*(1.0f - Ds0);
if (sq < 0) sq = 0;
return t1 + sqrtf(sq) / 2.0f;
}
2.3 升压/降压对偶关系(验证用)
| 对象 | M<1M < 1M<1 侧 | M>1M > 1M>1 侧 | 替换规则 |
|---|---|---|---|
| 电压比 | MMM | 1/M1/M1/M | M↔1/MM \leftrightarrow 1/MM↔1/M |
| 原/副边角 | Dp0D_{p0}Dp0 | Ds0D_{s0}Ds0 | Dp0↔Ds0D_{p0} \leftrightarrow D_{s0}Dp0↔Ds0 |
| 轻载最大范围 | M=0.5M=0.5M=0.5 时 Pn,t∈[0,0.5]P_{n,t}\in[0,0.5]Pn,t∈[0,0.5] | M=2M=2M=2 时 Pn,t∈[0,0.5]P_{n,t}\in[0,0.5]Pn,t∈[0,0.5] | 完全对称 |
| 中载公式 | 式 (3-19) 含 Dp0D_{p0}Dp0 | 式 (3-25) 含 Ds0D_{s0}Ds0 | 互换后形式一致 |
注:所有公式中的占空比均归一化到 [0,1][0,1][0,1],DssD_{ss}Dss 建议限幅到 [0,0.5][0, 0.5][0,0.5]。中载公式含根号项,实现时需保证根号内非负(正常工作域内自然满足,但代码里加个
max(0, x)保护更安全)。
三、嵌入式代码逻辑框架
下面是一个基于 C 语言的完整伪代码结构,展示了如何在中断服务函数(ISR)中实现该算法。
// ============================================================
// 全局变量
// ============================================================
float M, Dc;
float Dss, Dp0, Ds0;
// ============================================================
// 辅助函数:限幅
// ============================================================
float clamp(float x, float lo, float hi) {
if (x < lo) return lo;
if (x > hi) return hi;
return x;
}
// ============================================================
// 重载区 Dss 计算(SPS 模式,轻重载统一)
// ============================================================
float calc_Dss_HLS(float Dc, float M) {
float Dss =(1/2*M)*((2*Dc-3)*(1-sqrt(1-M*M))+M);
return clamp(Dss, 0.0f, 0.5f);
}
// ============================================================
// 主控制函数(在 PWM 中断或定时器中调用)
// ============================================================
void DAB_Control_Loop(void) {
// ---------- 1. 采样与计算 ----------
float Vin = ADC_Read(VC_IN); // 输入电压采样
float Vout = ADC_Read(VC_OUT); // 输出电压采样
M = (N * Vout_Target) / Vin; // 电压传输比
// ---------- 2. 电压环 PI 计算 Dc ----------
float error = Vout_Target - Vout;
Dc = PI_Controller(error);
Dc = clamp(Dc, 0.0f, 1.5f); // 限制 Dc 范围
// ---------- 3. 模式判断与计算 ----------
if (M < 1.0f) {
// ===== 降压模式 =====
if (Dc >= 1.0f) {
// 重载 HLS: 式(3-21),退化为 SPS
Dp0 = 0; Ds0 = 0;
Dss = calc_Dss_HLS(Dc, M);
} else if (Dc >= M) {
// 中载 MLS: 式(3-19),固定 Ds0=0
Ds0 = 0;
Dp0 = Dc; // 示例映射,可标定
Dss = calc_MLS_lt1(Dp0, M);
} else {
// 轻载 LLS: 式(3-13),消除环流
Dp0 = 1.0f - Dc; // 示例映射,可标定
Ds0 = 1.0f - (1.0f - Dp0) / M;
Dss = Dp0 - Ds0; // 满足 Dss + Ds0 = Dp0
}
} else {
// ===== 升压模式 =====
float invM = 1.0f / M;
if (Dc >= 1.0f) {
// 重载 HLS: 式(3-27),退化为 SPS
Dp0 = 0; Ds0 = 0;
Dss = calc_Dss_HLS(Dc, M);
} else if (Dc >= invM) {
// 中载 MLS: 式(3-25),固定 Dp0=0
Dp0 = 0;
Ds0 = Dc * invM; // 示例映射,可标定
Dss = calc_MLS_gt1(Ds0, M);
} else {
// 轻载 LLS: 式(3-23),消除环流
Dss = 0;
Ds0 = Dc * M; // 示例映射,可标定
Dp0 = 1.0f - M * (1.0f - Ds0);
}
}
// ---------- 4. 最终限幅保护 ----------
Dss = clamp(Dss, 0.0f, 0.5f);
Dp0 = clamp(Dp0, 0.0f, 1.0f);
Ds0 = clamp(Ds0, 0.0f, 1.0f);
// ---------- 5. 更新 PWM ----------
Update_PWM(Dss, Dp0, Ds0);
}
四、工况判断流程图
┌──────────────────┐
│ 采样 Vin, Vout │
└────────┬─────────┘
▼
┌──────────────────┐
│ 计算 M = N·Vref/Vin │
└────────┬─────────┘
▼
┌──────────────────┐
│ 电压环 PI → Dc │
└────────┬─────────┘
▼
┌─────────────┴─────────────┐
▼ ▼
M < 1 ? ─── 是 否 ──── M ≥ 1
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Dc ≥ 1 ? │ │ Dc ≥ 1 ? │
└──┬───────┬─────┘ └──┬───────┬───────┘
▼ ▼ ▼ ▼
是 否 是 否
│ │ │ │
▼ ▼ ▼ ▼
重载 Dc ≥ M ? 重载 Dc ≥ 1/M ?
SPS │ SPS │
▼ ▼
是 否 是 否
│ │ │ │
▼ ▼ ▼ ▼
中载 轻载 中载 轻载
MLS LLS MLS LLS
(Ds0=0) (消环流) (Dp0=0) (消环流)
五、调试与标定技巧
5.1 分步验证 checklist
| 步骤 | 操作 | 预期结果 |
|---|---|---|
| 1 | 设定 M=1M=1M=1(输入输出电压经匝比匹配) | 全范围应走重载分支,输出标准 SPS 方波 |
| 2 | 观察重载波形 | Dp0=Ds0=0D_{p0}=D_{s0}=0Dp0=Ds0=0,DssD_{ss}Dss 随负载平滑变化,电流波形正弦度好 |
| 3 | 逐步减小负载进入中载区 | Ds0D_{s0}Ds0(或 Dp0D_{p0}Dp0)变为 0,电流有效值明显下降 |
| 4 | 进入轻载区 | 出现零电流区间(ZCS),环流被抑制 |
5.2 边界滞环防抖
在 Dc=MD_c = MDc=M 或 Dc=1/MD_c = 1/MDc=1/M 的边界处,负载的微小抖动可能导致模式频繁切换。建议加入 0.02~0.05 的滞环:
#define HYST 0.02f
// 降压模式边界
if (mode_last == LIGHT && Dc > M + HYST) switch_to_medium();
if (mode_last == MEDIUM && Dc < M - HYST) switch_to_light();
// 升压模式边界
if (mode_last == LIGHT && Dc > invM + HYST) switch_to_medium();
if (mode_last == MEDIUM && Dc < invM - HYST) switch_to_light();
5.3 性能优化:查表法替代开根号
如果你的 MCU 算力有限(比如主频较低的 STM32F1),中载区的开根号运算可能会成为瓶颈。此时可以离线将中载公式的计算结果制成二维查找表:
# Python 离线生成查找表
import numpy as np
M_range = np.linspace(0.3, 0.9, 20) # M 采样点
Dp0_range = np.linspace(0.0, 1.0, 50) # Dp0 采样点
lut = np.zeros((20, 50))
for i, M in enumerate(M_range):
for j, Dp0 in enumerate(Dp0_range):
sq = Ds0**2 - 1.0f + M**2*(1.0f - Ds0)**2
if sq < 0: sq = 0
Dss =( (Dp0 - 1.0f + M + Dp0 * M) + np.sqrt(sq)) / (2*M)
lut[i, j] = Dss
# 导出为 C 数组
print("const float lut_Dss[20][50] = {")
for i in range(20):
print(" { " + ", ".join(f"{v:.6f}" for v in lut[i]) + " },")
print("};")
在 MCU 中用双线性插值查表,速度比实时开根号快一个数量级。
5.4 示波器观测要点
| 观测信号 | 正常表现 | 异常表现 |
|---|---|---|
| vp(t)v_p(t)vp(t) 原边电压 | 三电平波形(轻载/中载)或两电平(重载) | 波形畸变、占空比异常 |
| iL(t)i_L(t)iL(t) 电感电流 | 轻载有零电流区间,中载梯形波,重载接近正弦 | 电流尖峰过大、有直流偏置 |
| vp×iLv_p \times i_Lvp×iL 瞬时功率 | 正负面积比反映传输功率方向 | 大量负面积 = 环流严重 |
六、总结
DAB 的电流有效值最优化调制听起来很高大上,但对于嵌入式工程师来说,落地其实很简单:
| 步骤 | 动作 | 一句话 |
|---|---|---|
| 1 | 算 MMM | 定方向:降压还是升压 |
| 2 | 算 DcD_cDc | 定档位:轻载、中载还是重载 |
| 3 | 查表/套公式 | 重载必 SPS,中载固定一边,轻载消环流 |
| 4 | 限幅保护 | 防异常,保安全 |
| 5 | 写 PWM | 完事 |
核心口诀:
MMM 定方向,DcD_cDc 定档位。重载一律用 SPS,中载固定一边调,轻载消除环流最省电。
把复杂的数学留给论文,把简洁的代码留给工程。希望这篇博客能帮助你在项目中快速实现高效的 DAB 控制。
附录:完整公式汇总表
A.1 降压工况 M<1M < 1M<1
(1−M)(1−Dp0)M\dfrac{(1-M)(1-D_{p0})}{M}M(1−M)(1−Dp0)
| 工况 | 完整公式 | 约束条件 |
|---|---|---|
| 轻载 (3-13) | {Dss,opt=(1−M)(1−Dp0)MDs0,opt=1−1−Dp0,optM\begin{cases} D_{ss,opt} = \dfrac{(1-M)(1-D_{p0})}{M} \\ D_{s0,opt} = 1 - \dfrac{1 - D_{p0,opt}}{M} \end{cases}⎩ ⎨ ⎧Dss,opt=M(1−M)(1−Dp0)Ds0,opt=1−M1−Dp0,opt | Dp0∈[1−M,1]D_{p0} \in [1-M, 1]Dp0∈[1−M,1] |
| 中载 (3-19) | {Ds0,opt=0Dss,opt=Dp0−1+M+MDp0+(1−M)2+M2(1−Dp02)2M\begin{cases} D_{s0,opt} = 0 \\ D_{ss,opt} = \dfrac{D_{p0}-1 +M+ MD_{p0} + \sqrt{(1-M)^2+ M^2(1-D_{p0}^2)}}{2M}\end{cases}⎩ ⎨ ⎧Ds0,opt=0Dss,opt=2MDp0−1+M+MDp0+(1−M)2+M2(1−Dp02) | Dp0∈[0,1−M]D_{p0} \in [0, 1-M]Dp0∈[0,1−M] |
| 重载 (3-21) | {Dp0,opt=0Ds0,opt=0\begin{cases} D_{p0,opt} = 0 \\ D_{s0,opt} = 0 \end{cases}{Dp0,opt=0Ds0,opt=0(仅 DssD_{ss}Dss 有效,SPS 调制) | Dss∈[0.25,0.5]D_{ss} \in [0.25, 0.5]Dss∈[0.25,0.5] |
A.2 升压工况 M>1M > 1M>1
| 工况 | 完整公式 | 约束条件 |
|---|---|---|
| 轻载 (3-23) | {Dss,opt=0Dp0,opt=1−M(1−Ds0,opt)\begin{cases} D_{ss,opt} = 0 \\ D_{p0,opt} = 1 - M(1 - D_{s0,opt}) \end{cases}{Dss,opt=0Dp0,opt=1−M(1−Ds0,opt) | Ds0∈[1−1/M,1]D_{s0} \in [1-1/M, 1]Ds0∈[1−1/M,1] |
| 中载 (3-25) | {Dp0,opt=0Dss,opt=1−Ds0−M+MDs0+Ds02−1+M2(1−Ds0)22\begin{cases} D_{p0,opt} = 0 \\ D_{ss,opt} = \dfrac{1 - D_{s0} - M + M D_{s0} + \sqrt{D_{s0}^2 - 1 + M^2(1-D_{s0})^2}}{2}\end{cases}⎩ ⎨ ⎧Dp0,opt=0Dss,opt=21−Ds0−M+MDs0+Ds02−1+M2(1−Ds0)2 | Ds0∈[0,1−1/M]D_{s0} \in [0, 1-1/M]Ds0∈[0,1−1/M] |
| 重载 (3-27) | {Dp0,opt=0Ds0,opt=0\begin{cases} D_{p0,opt} = 0 \\ D_{s0,opt} = 0 \end{cases}{Dp0,opt=0Ds0,opt=0(仅 DssD_{ss}Dss 有效,SPS 调制) | Dss∈[0.25,0.5]D_{ss} \in [0.25, 0.5]Dss∈[0.25,0.5] |
如果这篇博客对你有帮助,欢迎点赞/收藏/转发。有任何问题或建议,欢迎在评论区交流!
更多推荐



所有评论(0)