电机驱动开发学习20. 霍尔有感 SVPWM FOC 速度闭环

电机驱动开发学习20. 霍尔有感 SVPWM FOC 速度闭环(对齐野火官方)

  • 一、本章在系列中的位置
    • [1.1 与前面章节的衔接](#1.1 与前面章节的衔接)
    • [1.2 本章目标](#1.2 本章目标)
    • [1.3 本章新增知识点(前面章节未展开的)](#1.3 本章新增知识点(前面章节未展开的))
  • 二、官方算法详解(本章核心)
    • [2.1 ST `MCM_Clarke` / `MCM_Park` / `MCM_Rev_Park`](#2.1 ST MCM_Clarke / MCM_Park / MCM_Rev_Park)
      • [2.1.1 与 lesson15「经典」公式对照](#2.1.1 与 lesson15「经典」公式对照)
      • [2.1.2 为什么不能混用](#2.1.2 为什么不能混用)
      • [2.1.3 物理直觉(简记)](#2.1.3 物理直觉(简记))
    • [2.2 ST 电压 s16 标度](#2.2 ST 电压 s16 标度)
      • [2.2.1 官方在算什么](#2.2.1 官方在算什么)
      • [2.2.2 与 lesson18 的差异](#2.2.2 与 lesson18 的差异)
      • [2.2.3 `SQRT3FACTOR` 从哪来](#2.2.3 SQRT3FACTOR 从哪来)
    • [2.3 β 取反(发生在 SVPWM,不是 RevPark 之外再翻一次)](#2.3 β 取反(发生在 SVPWM,不是 RevPark 之外再翻一次))
    • [2.4 CCR 公式(`PWMC_SetPhaseVoltage`)](#2.4 CCR 公式(PWMC_SetPhaseVoltage))
      • [2.4.1 周期约定](#2.4.1 周期约定)
      • [2.4.2 中间量](#2.4.2 中间量)
      • [2.4.3 和 lesson18 七段式的关系](#2.4.3 和 lesson18 七段式的关系)
    • [2.5 霍尔相移 `HALL_PHASE_SHIFT = 240°`](#2.5 霍尔相移 HALL_PHASE_SHIFT = 240°)
      • [2.5.1 定义](#2.5.1 定义)
      • [2.5.2 扇区角怎么算(对齐 `HALL_Clear`)](#2.5.2 扇区角怎么算(对齐 HALL_Clear))
      • [2.5.3 调相移的正确姿势](#2.5.3 调相移的正确姿势)
    • [2.6 `HALL_CalcElAngle`:边沿锚定 + 速度积分](#2.6 HALL_CalcElAngle:边沿锚定 + 速度积分)
      • [2.6.1 官方在做什么](#2.6.1 官方在做什么)
      • [2.6.2 本课对应实现](#2.6.2 本课对应实现)
      • [2.6.3 和 lesson17/18「TIM5 插值」的对比](#2.6.3 和 lesson17/18「TIM5 插值」的对比)
    • [2.7 一条必须成套的链路(排障用)](#2.7 一条必须成套的链路(排障用))
  • 三、移植了官方的哪些功能
  • 四、硬件与铭牌
    • [4.1 引脚(Motor1 / 接口 1)](#4.1 引脚(Motor1 / 接口 1))
    • [4.2 电机铭牌(本机)](#4.2 电机铭牌(本机))
  • 五、程序设计
    • [5.1 相对 lesson18/19 的目录变更](#5.1 相对 lesson18/19 的目录变更)
    • [5.2 控制链路](#5.2 控制链路)
    • [5.3 启动状态机(`bsp_foc_boot`)](#5.3 启动状态机(bsp_foc_boot))
      • [5.3.1 本章启动方式](#5.3.1 本章启动方式)
      • [5.3.2 默认路径(`FOC_BOOT_USE_ALIGN = 0`)](#5.3.2 默认路径(FOC_BOOT_USE_ALIGN = 0))
      • [5.3.3 Run 内的「软衔接」(不是 Drag,但是启动关键)](#5.3.3 Run 内的「软衔接」(不是 Drag,但是启动关键))
      • [5.3.4 可选路径(`FOC_BOOT_USE_ALIGN = 1`,教学/标定)](#5.3.4 可选路径(FOC_BOOT_USE_ALIGN = 1,教学/标定))
      • [5.3.5 与 lesson19 / 官方启动对照](#5.3.5 与 lesson19 / 官方启动对照)
    • [5.4 与官方 / lesson19 运行对照](#5.4 与官方 / lesson19 运行对照)
    • [5.5 按键功能(骄阳板)](#5.5 按键功能(骄阳板))
  • 六、实验步骤
    • [6.1 先烧官方 hex 验证硬件](#6.1 先烧官方 hex 验证硬件)
    • [6.2 本课固件](#6.2 本课固件)
    • [6.3 变量曲线解析](#6.3 变量曲线解析)
      • [6.3.1 电角度](#6.3.1 电角度)
      • [6.3.2 目标转速](#6.3.2 目标转速)
      • [6.3.3 g_fm_target_iq Q轴电流给定 I q ∗ I q ∗ I^*_qIq* Iq∗Iq∗](#6.3.3 g_fm_target_iq Q轴电流给定 I q ∗ I q ∗ I^_qIq Iq∗Iq∗)
      • [6.3.4 比较寄存器CCR g_fm_ccr_*](#6.3.4 比较寄存器CCR g_fm_ccr_*)
      • 数值怎么理解
      • 和扇区的关系
      • 看曲线时注意
  • 七、小结与下一章

一、本章在系列中的位置

1.1 与前面章节的衔接

章节 前节已经掌握的 本章如何用到
14 FOC 架构 双环 + 坐标变换总览 控制框图不变
15 Clark/Park/InvPark 经典等幅值变换公式 本章改为 ST MCSDK 同款公式(见 1.3)
16 DQ 电流环 Id/Iq PI 保留;环路搬到 ADC 注入 ISR
17 速度外环 速度 PI → Iq* 保留(约 50 ms 慢环)
18 SVPWM 自研七段式:扇区→Ta/Tb→CCR 替换为官方 PWMC_SetPhaseVoltage(关键差异)
19 三段式启动 Align→Drag→Run,接口 2 六步桥 本章换 接口 1 ;默认 无 Align/Drag,对齐官方 Charge→Offset→Run

一句话:

lesson19 在六步板上教「怎么从静止爬起来」;

lesson20 在三相全桥上教「怎么按野火官方 Hall FOC 把正弦电机真正 SVPWM 闭环转起来」。

1.2 本章目标

无刷驱动接口 1 + 正弦反电动势霍尔电机 上,对照官方工程

improve_part/PMSM_FOC_V5.44_Hall_speed_control,跑通:

复制代码
ChargeCap → OffsetCal → Run(霍尔θ + Id/Iq 双环 + 官方同款 SVPWM + 速度外环)

本机实测:串口 t 500 / w 1 后转速可平滑爬到 约 500 RPM (空载电流数百 mA 量级);运行中可用板载 K3/K4 以 50 RPM 步进加减目标转速。

排线必须用驱动板 「无刷电机驱动接口 1」(TIM1 三相互补),不是 lesson19 的接口 2。

1.3 本章新增知识点(前面章节未展开的)

# 新知识点 lesson15~18 差异 本课落点
1 ST MCSDK 坐标变换约定 lesson15 教的是教科书 Clark/Park;官方 MCM_Clarke/Park/Rev_Park 的 β、Id/Iq 投影不同 bsp_foc.c
2 电流极性 I = Offset − ADC 早期课常用 ADC − Offset;与 ST 链混用会整环反号 bsp_adc.c
3 同 PWM 周期双相采样 + 第三相重构 lesson6 三相轮询/断续注入时刻不一致 ADC1 注入 rank1/2 连采 U+V,W=-U-V
4 官方 SVPWM:PWMC_SetPhaseVoltage lesson18 七段式公式与 ST 的 s16 标度、β 取反、CCR 公式不同;混用必堵转过流 bsp_svpwm.c
5 电压 s16 标度:32767 ↔ Vbus/√3 lesson18 用伏特直接算时间;官方先数字化再算 CCR svpwm_calc() 内转换
6 霍尔相移 HALL_PHASE_SHIFT=240° 与 ST 变换、扇区表绑定;不能拿经典 Park 去扫 60° 冒充 MOTOR_HALL_PHASE_SHIFT_DEG
7 PWM 频率电流环(≈15 kHz) lesson16/17 主循环 ~25 ms 太慢,跟不上正弦调制 dq_current_loop_hf() @ ADC JEOS
8 霍尔 θ:边沿锚定 + ω·Ts 积分 + 扇区钳位 lesson17/18 偏 TIM5 插值;官方是 HALL_CalcElAngle 风格 foc_theta_hf_*
9 启动:Charge 自举 + Offset 零偏(低边 ON) lesson19 强调 Align/Drag;正弦+霍尔官方可直接 Offset→Run bsp_foc_boot.c

下面 第二节 把表中第 1、4、5、6、8 条展开讲透;读代码时请对照 bsp_foc.c / bsp_svpwm.c


二、官方算法详解(本章核心)

官方源文件:

  • 变换:PMSM_control/Src/mc_math.cMCM_Clarke / MCM_Park / MCM_Rev_Park
  • SVPWM:MCLib/.../pwm_curr_fdbk.cPWMC_SetPhaseVoltage
  • 霍尔:MCLib/.../hall_speed_pos_fdbk.cHALL_CalcElAngle / HALL_Clear
  • 参数:pmsm_motor_parameters.hHALL_PHASE_SHIFT = 240

2.1 ST MCM_Clarke / MCM_Park / MCM_Rev_Park

2.1.1 与 lesson15「经典」公式对照

lesson15 常用的经典等幅值写法是:

I α = I a I β = I a + 2 I b 3 I d = I α cos ⁡ θ + I β sin ⁡ θ I q = − I α sin ⁡ θ + I β cos ⁡ θ V α = V d cos ⁡ θ − V q sin ⁡ θ V β = V d sin ⁡ θ + V q cos ⁡ θ \begin{aligned} I_\alpha &= I_a \\ I_\beta &= \frac{I_a + 2I_b}{\sqrt{3}} \\ I_d &= I_\alpha\cos\theta + I_\beta\sin\theta \\ I_q &= -I_\alpha\sin\theta + I_\beta\cos\theta \\ V_\alpha &= V_d\cos\theta - V_q\sin\theta \\ V_\beta &= V_d\sin\theta + V_q\cos\theta \end{aligned} IαIβIdIqVαVβ=Ia=3 Ia+2Ib=Iαcosθ+Iβsinθ=−Iαsinθ+Iβcosθ=Vdcosθ−Vqsinθ=Vdsinθ+Vqcosθ

官方 ST MCSDK(注释与实现一致)是另一套约定:

I α = I a I β = − I a + 2 I b 3 I d = I α sin ⁡ θ + I β cos ⁡ θ I q = I α cos ⁡ θ − I β sin ⁡ θ V α = V q cos ⁡ θ + V d sin ⁡ θ V β = − V q sin ⁡ θ + V d cos ⁡ θ \begin{aligned} I_\alpha &= I_a \\ I_\beta &= -\frac{I_a + 2I_b}{\sqrt{3}} \\ I_d &= I_\alpha\sin\theta + I_\beta\cos\theta \\ I_q &= I_\alpha\cos\theta - I_\beta\sin\theta \\ V_\alpha &= V_q\cos\theta + V_d\sin\theta \\ V_\beta &= -V_q\sin\theta + V_d\cos\theta \end{aligned} IαIβIdIqVαVβ=Ia=−3 Ia+2Ib=Iαsinθ+Iβcosθ=Iαcosθ−Iβsinθ=Vqcosθ+Vdsinθ=−Vqsinθ+Vdcosθ

本课浮点实现(bsp_foc.c):

c 复制代码
/* Clarke */
Ialpha = Ia;
Ibeta  = -(Ia + 2*Ib) / sqrt(3);

/* Park */
Id = Ialpha*sinθ + Ibeta*cosθ;
Iq = Ialpha*cosθ - Ibeta*sinθ;

/* RevPark */
Valpha = Vq*cosθ + Vd*sinθ;
Vbeta  = -Vq*sinθ + Vd*cosθ;

2.1.2 为什么不能混用

混用方式 典型现象
经典 Park + ST RevPark / 官方 SVPWM Id、Iq 对调或反号,PI 顶饱和
ST Park + lesson18 旧七段式 SVPWM 转矩方向错,堵转/过流
经典变换 + 官方相移 240 相当于再偏约 90°,扫相移也救不回来

本课从采样极性 → 变换 → SVPWM → 霍尔相移,必须整条链路用 ST 约定;lesson15 公式只作对照,不要抄回本工程。

2.1.3 物理直觉(简记)

  • Clarke:ST 的 ( I β ) (I_\beta) (Iβ)相对经典多一个负号(β 轴朝向约定不同)。
  • Park:ST 把 (d) 轴投影写成 ( α sin ⁡ + β cos ⁡ ) (\alpha\sin+\beta\cos) (αsin+βcos),等价于把电角度零点定义在与经典差约 90° 的参考上。
  • RevPark:与 ST Park 互逆,保证 ( V d , V q ) (V_d,V_q) (Vd,Vq) 能还原到同一 ( α β ) (\alpha\beta) (αβ)。
  • 官方霍尔角、HALL_PHASE_SHIFT、SVPWM 都按这套零点标定。

2.2 ST 电压 s16 标度

2.2.1 官方在算什么

MCSDK 内部电流、电压多用 int16(s16)

  • 角度:q1.15, ( 32768 ↔ 360 ∘ ) (32768 \leftrightarrow 360^\circ) (32768↔360∘) 电角度;
  • 电压:满量程与母线相关------数字量 32767 对应相电压幅值 ( V b u s / 3 ) (V_{bus}/\sqrt{3}) (Vbus/3 )
    (SVPWM 六边形内切圆半径,即线性区内最大可用相电压)。

因此伏特 → s16:

u s 16 = s a t ( V v o l t ⋅ 32767 ⋅ 3 V b u s ) u_{s16} = \mathrm{sat}\left(\frac{V_{\mathrm{volt}}\cdot 32767\cdot\sqrt{3}}{V_{bus}}\right) us16=sat(VbusVvolt⋅32767⋅3 )

本课(bsp_svpwm.c):

c 复制代码
scale = 32767.0f * sqrt(3) / Vbus;
alpha_s16 = Valpha_volt * scale;
beta_s16  = Vbeta_volt  * scale;

反算: ( V v o l t = u s 16 ⋅ V b u s / ( 32767 ⋅ 3 ) ) (V_{\mathrm{volt}} = u_{s16}\cdot V_{bus}/(32767\cdot\sqrt{3})) (Vvolt=us16⋅Vbus/(32767⋅3 ))。

2.2.2 与 lesson18 的差异

lesson18 自研 SVPWM 官方 / 本课
输入 直接用伏特算 (T_a,T_b) 先换成 s16,再进 CCR 整数公式
限幅 ( V m a x = V b u s × 2 / 3 ) (V_{max}=V_{bus}\times 2/3) (Vmax=Vbus×2/3) 内切圆 ( V m a x = V b u s / 3 ) (V_{max}=V_{bus}/\sqrt{3}) (Vmax=Vbus/3 )
FOC_SVPWM_VMAX_MUL=2/3 现为 1/√3

PI 限幅、圆限幅必须与这一标度一致,否则「电压数字很大但实际占空比不对」或提前饱和。

2.2.3 SQRT3FACTOR 从哪来

官方:

c 复制代码
#define SQRT3FACTOR  0xDDB4  /* = 16384 * √3 * 2 = 56756 */
hT_Sqrt3 = (PWM_PERIOD_CYCLES * SQRT3FACTOR) / 16384;

即 ( h T _ S q r t 3 ≈ P W M _ P E R I O D × 2 3 ) (hT\_Sqrt3 \approx PWM\_PERIOD \times 2\sqrt{3}) (hT_Sqrt3≈PWM_PERIOD×23 )。后面与 alpha_s16 相乘再除以 ( 2 18 ) (2^{18}) (218) 等,把「电压数字 × 周期」压回 CCR 量级。


2.3 β 取反(发生在 SVPWM,不是 RevPark 之外再翻一次)

官方 PWMC_SetPhaseVoltage 核心两行:

c 复制代码
wUAlpha = Valfa_beta.alpha * hT_Sqrt3;
wUBeta  = -(Valfa_beta.beta * PWMperiod) * 2;   /* 注意负号 */

本课对应:

c 复制代码
wUAlpha = alpha_s16 * hT_Sqrt3;
wUBeta  = -(beta_s16 * pwm_period) * 2;

含义:

  1. RevPark 已经给出 ST 约定下的 (V_\alpha,V_\beta);
  2. 进入占空比几何时,ST 对 β 再取负,与扇区判别 (wX,wY,wZ) 的定义配套;
  3. 若在调用 svpwm_calc 前再手动 Ubeta = -Vbeta(旧 FOC_SVPWM_NEGATE_BETA=1),等于取反两次,转矩方向再次弄反。

因此本课:FOC_SVPWM_NEGATE_BETA = 0,取反只保留在 svpwm_calc 内部。


2.4 CCR 公式(PWMC_SetPhaseVoltage

2.4.1 周期约定

  • 中心对齐 PWM:ARR = PeriodArr(本课 5600)。
  • 官方 PWM_PERIOD_CYCLES = 上下计数一整周 = 2 * ARR
  • 本课:pwm_period = PeriodArr * 2

50% 占空附近:CCR ≈ pwm_period/4 = ARR/2

2.4.2 中间量

text 复制代码
wX = wUBeta
wY = (wUBeta + wUAlpha) / 2
wZ = (wUBeta - wUAlpha) / 2

按 (wY,wZ,wX) 符号分成 6 个扇区(官方 SECTOR_1...6,下标 0...5),每扇给出 wTimePhA/B/C,例如扇区 1:

text 复制代码
wTimePhA = pwm_period/4 + (wX - wZ) / 262144
wTimePhB = wTimePhA + wZ / 131072
wTimePhC = wTimePhB - wX / 131072

其中 (262144=2{18})、(131072=2{17}),与前面 hT_Sqrt3、s16 相乘的位宽配套。

最后:

text 复制代码
CCR_A = clamp(wTimePhA, 0, ARR)
CCR_B = clamp(wTimePhB, 0, ARR)
CCR_C = clamp(wTimePhC, 0, ARR)

写入 TIM1 CH1/2/3。低调制时采样可固定采 U/V(官方亦常落在 SECTOR_4 采 AB),与本课「同拍 U+V、重构 W」一致。

2.4.3 和 lesson18 七段式的关系

lesson18:先判扇区 → 算 ( T a , T b ) (T_a,T_b) (Ta,Tb) → 再映射到中央对齐 CCR。

官方:在 s16 电压空间 里用 ( w X , w Y , w Z ) (wX,wY,wZ) (wX,wY,wZ) 一次算出三相时间。

二者在理想连续域可等价,但定点标度、β 符号、扇区编号任一不一致就会错;本课不再维护两套公式,只保留官方这一套。


2.5 霍尔相移 HALL_PHASE_SHIFT = 240°

2.5.1 定义

官方 pmsm_motor_parameters.h

c 复制代码
#define HALL_PHASE_SHIFT  240  /* degrees */

本课:MOTOR_HALL_PHASE_SHIFT_DEG = 240.0f

FOC_HALL_ANGLE_OFFSET = 240° × π/180

相移补偿的是:霍尔开关边沿时刻d 轴(或 ST 约定下的电角度零点) 之间的机械/电气安装偏差,必须与 MCM_Park 使用同一角度定义。

2.5.2 扇区角怎么算(对齐 HALL_Clear

霍尔 6 态映射到扇区号 sec ∈ [0..5](本课 foc_hall_to_sector,与官方正转序一致):

霍尔态 sec 中心角(PhaseShift=240 时)
5 0 270°
1 1 330°
3 2 30°
2 3 90°
6 4 150°
4 5 210°

公式:

  • 扇区起点(边沿锚定) : ( θ b o u n d = P H A S E _ S H I F T + s e c × 60 ∘ ) (\theta_{bound} = PHASE\_SHIFT + sec\times 60^\circ) (θbound=PHASE_SHIFT+sec×60∘)
  • 扇区中心(静止/超时) : ( θ c e n t e r = P H A S E _ S H I F T + ( s e c + 0.5 ) × 60 ∘ ) (\theta_{center} = PHASE\_SHIFT + (sec+0.5)\times 60^\circ) (θcenter=PHASE_SHIFT+(sec+0.5)×60∘)

2.5.3 调相移的正确姿势

  • 只允许在 整条 ST 链路已对齐 后,按电机/霍尔安装 ±60° 微调;
  • 不要用「经典 Park + 扫相移」去凑官方 240------那是在补偿另一套零点,会把问题掩盖成随机最佳角(本课调试中曾出现假象最优 60°)。

2.6 HALL_CalcElAngle:边沿锚定 + 速度积分

2.6.1 官方在做什么

霍尔每 60° 电角度才跳变一次,若 θ 只取扇区中心,Park 会呈 60° 台阶。官方做法:

  1. 霍尔边沿 IRQ :根据新霍尔态写入 MeasuredElAngle(含 PhaseShift),并更新扇区电角速度估计(捕获周期 → hElSpeedDpp,单位:每个速度环周期转过的 s16 角增量)。
  2. 每个 PWM/FOC 节拍调用 HALL_CalcElAngle
c 复制代码
/* 伪代码,对应 hall_speed_pos_fdbk.c */
MeasuredElAngle += hElSpeedDpp;
hElAngle        += hElSpeedDpp + CompSpeed;
return hElAngle;

即:在两次边沿之间,用最近测得的电角速度做开环积分,得到近似连续的电角度;下一边沿再拉回真实边界,消除积分漂移。

速度过低或捕获无效时置 HALL_MAX_PSEUDO_SPEED,避免用噪声速度空转角度。

2.6.2 本课对应实现

官方 本课
边沿写 MeasuredElAngle foc_theta_hf_on_hall_edge()foc_hall_boundary_theta()
捕获估速 → hElSpeedDpp 捕获周期 → s_hf_omega(rad/s)
HALL_CalcElAngle 每拍积分 foc_theta_hf_step(dt)θ += ω·Ts
扇区内限制 foc_theta_hf_clamp_sector()
静止/超时 ω 衰减,回落到 foc_hall_center_theta()

电流环在 ADC 注入完成 ISR 里跑(≈15 kHz),每拍调用一次 foc_theta_hf_step,效果对齐官方「FOC 节拍更新电角度」。

2.6.3 和 lesson17/18「TIM5 插值」的对比

TIM5 扇区插值(lesson17/18) HALL_CalcElAngle 风格(本章)
边沿间 θ 用本扇区已走时间 / 上扇区周期 × 60° 用估得的 ω 积分
与官方 不同实现 同思路
堵转风险 周期陈旧时可能插到错误位置 超时强制 ω→0 并钉中心,避免 θ 空转

2.7 一条必须成套的链路(排障用)

text 复制代码
I = Offset − ADC
  → ST Clarke / Park
  → Id/Iq PI(伏特)
  → ST RevPark
  → s16 标度(32767 ↔ Vbus/√3)
  → PWMC 同款 CCR(内部 β 取反)
  → θ = PhaseShift(240) + 边沿/ω积分

任一环节改回「经典 / lesson18 旧式 / 二次取反 β」,就会回到堵转、过流、Id 饱和。


三、移植了官方的哪些功能

对照路径:PMSM_FOC_V5.44_Hall_speed_control(ST MCSDK 5.4.4 + 野火骄阳)。

官方模块 / 文件 官方函数或定义 本课对应 说明
mc_math.c MCM_Clarke / MCM_Park / MCM_Rev_Park foc_clark / foc_park / foc_inv_park 公式对齐,浮点实现
pwm_curr_fdbk.c PWMC_SetPhaseVoltage svpwm_calc 整段 CCR 算法移植(含内部 β 取反)
pwm_curr_fdbk.h SQRT3FACTOR、电压满量程约定 SVPWM_SQRT3FACTOR32767↔Vbus/√3 标度必须一致
r3_2_*.c(思想) 低调制固定采 A/B,第三相重构;I=Offset−ADC ADC1 同拍 U+V + W=-U-V;Offset−ADC 未完整搬双 ADC 扇区 JSQR(留 lesson21)
hall_speed_pos_fdbk.c HALL_CalcElAngle / HALL_Clear、扇区表 foc_theta_hf_*foc_hall_to_sector 边沿+ω积分+钳位;相移 240
pmsm_motor_parameters.h HALL_PHASE_SHIFT = 240 MOTOR_HALL_PHASE_SHIFT_DEG 同值
mc_tasks.c Charge / Offset / FOC @ PWM bsp_foc_boot + ADC ISR FOC 启停改串口,逻辑同构
电流环调度 TSK_HighFrequencyTask @ PWM HAL_ADCEx_InjectedConvCpltCallbackdq_current_loop_hf 同为 PWM 量级

刻意未完整移植

  • R3_2 按扇区切换 ADC1/ADC2 JSQR(高调制采样窗)
  • MCSDK 整套故障状态机 / UI

四、硬件与铭牌

4.1 引脚(Motor1 / 接口 1)

*本章改用反电动势为正弦的PMSM电机。*型号是 : 42JSF840AS-1000-8,接线:

规格参数:

复制代码
PWM U/V/W     : PA8/PA9/PA10   TIM1 CH1/2/3
PWM UL/VL/WL  : PB13/14/15     TIM1 CH1N/2N/3N
ADC 触发      : TIM1 CH4 → ADC1 注入(同拍 U+V)
霍尔 HU/HV/HW : PC6/7/8        TIM3 Hall
电流 IU/IV/IW : PA3/PA4/PA6
母线 / 温度   : PB0 / PB1      ADC2 轮询
SD 使能       : PG12

PWM ≈ 15 kHz 中心对齐(MOTOR_PWM_PERIOD_COUNT=5600)。官方 Demo 约 16 kHz,控制结构一致。

4.2 电机铭牌(本机)

项目 数值
额定 24 V / 4 A / 3000 rpm(电源建议 24 V--10 A)
极对数 4
反电动势 正弦波
霍尔 5 V,120°

关键宏见 User/foc/bsp_motor_params.hMOTOR_POLE_PAIRSMOTOR_HALL_PHASE_SHIFT_DEG=240MOTOR_STARTUP_IQ_MA


五、程序设计

5.1 相对 lesson18/19 的目录变更

复制代码
User/
├── foc/
│   ├── bsp_foc.c/h          ★ ST 变换 + foc_theta_hf(官方霍尔角)
│   ├── bsp_svpwm.c/h        ★ 官方 PWMC_SetPhaseVoltage 移植
│   ├── bsp_foc_boot.c/h     ★ Charge→Offset→Run(默认同官方,无 Align)
│   └── bsp_motor_params.h   ★ 相移 240、极对数、起步 Iq
├── adc/
│   └── bsp_adc.c/h          ★ 同拍 U+V、Offset−ADC、JEOS 调 HF FOC
├── pid/
│   └── bsp_pid_app.c/h      ★ 速度慢环 + 串口;电流环在 ISR
├── tim/
│   └── bsp_motor_tim.c/h    ★ 接口1 互补 PWM + 霍尔捕获
├── key/
│   └── bsp_key.c/h          ★ 骄阳板按键 GPIO(SW2~SW5)
└── bldcm_control/
    └── bsp_bldcm_control.c  ★ `deal_key_input()`:启停后按键调速/调 Iq

5.2 控制链路

#mermaid-svg-9jhljOB8PXZixYrp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9jhljOB8PXZixYrp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9jhljOB8PXZixYrp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9jhljOB8PXZixYrp .error-icon{fill:#552222;}#mermaid-svg-9jhljOB8PXZixYrp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9jhljOB8PXZixYrp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9jhljOB8PXZixYrp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9jhljOB8PXZixYrp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9jhljOB8PXZixYrp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9jhljOB8PXZixYrp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9jhljOB8PXZixYrp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9jhljOB8PXZixYrp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9jhljOB8PXZixYrp .marker.cross{stroke:#333333;}#mermaid-svg-9jhljOB8PXZixYrp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9jhljOB8PXZixYrp p{margin:0;}#mermaid-svg-9jhljOB8PXZixYrp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9jhljOB8PXZixYrp .cluster-label text{fill:#333;}#mermaid-svg-9jhljOB8PXZixYrp .cluster-label span{color:#333;}#mermaid-svg-9jhljOB8PXZixYrp .cluster-label span p{background-color:transparent;}#mermaid-svg-9jhljOB8PXZixYrp .label text,#mermaid-svg-9jhljOB8PXZixYrp span{fill:#333;color:#333;}#mermaid-svg-9jhljOB8PXZixYrp .node rect,#mermaid-svg-9jhljOB8PXZixYrp .node circle,#mermaid-svg-9jhljOB8PXZixYrp .node ellipse,#mermaid-svg-9jhljOB8PXZixYrp .node polygon,#mermaid-svg-9jhljOB8PXZixYrp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9jhljOB8PXZixYrp .rough-node .label text,#mermaid-svg-9jhljOB8PXZixYrp .node .label text,#mermaid-svg-9jhljOB8PXZixYrp .image-shape .label,#mermaid-svg-9jhljOB8PXZixYrp .icon-shape .label{text-anchor:middle;}#mermaid-svg-9jhljOB8PXZixYrp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9jhljOB8PXZixYrp .rough-node .label,#mermaid-svg-9jhljOB8PXZixYrp .node .label,#mermaid-svg-9jhljOB8PXZixYrp .image-shape .label,#mermaid-svg-9jhljOB8PXZixYrp .icon-shape .label{text-align:center;}#mermaid-svg-9jhljOB8PXZixYrp .node.clickable{cursor:pointer;}#mermaid-svg-9jhljOB8PXZixYrp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9jhljOB8PXZixYrp .arrowheadPath{fill:#333333;}#mermaid-svg-9jhljOB8PXZixYrp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9jhljOB8PXZixYrp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9jhljOB8PXZixYrp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9jhljOB8PXZixYrp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9jhljOB8PXZixYrp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9jhljOB8PXZixYrp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9jhljOB8PXZixYrp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9jhljOB8PXZixYrp .cluster text{fill:#333;}#mermaid-svg-9jhljOB8PXZixYrp .cluster span{color:#333;}#mermaid-svg-9jhljOB8PXZixYrp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9jhljOB8PXZixYrp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9jhljOB8PXZixYrp rect.text{fill:none;stroke-width:0;}#mermaid-svg-9jhljOB8PXZixYrp .icon-shape,#mermaid-svg-9jhljOB8PXZixYrp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9jhljOB8PXZixYrp .icon-shape p,#mermaid-svg-9jhljOB8PXZixYrp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9jhljOB8PXZixYrp .icon-shape .label rect,#mermaid-svg-9jhljOB8PXZixYrp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9jhljOB8PXZixYrp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9jhljOB8PXZixYrp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9jhljOB8PXZixYrp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 约 50 ms
PWM 量级 · ADC 注入完成
ADC1: U,V 同拍
I = Offset − ADC
W = −U − V
ST Clarke
θ: 边沿 + ω·Ts
ST Park
PI Id / Iq
ST RevPark
官方同款 SVPWM
TIM1 CCR U/V/W
霍尔 RPM
PI 速度
Iq*

注意:β 取反已在 svpwm_calc 内部 完成(对齐 wUBeta = -β·...),FOC_SVPWM_NEGATE_BETA 保持 0,不要二次取反。

5.3 启动状态机(bsp_foc_boot

实现文件:User/foc/bsp_foc_boot.c,主循环约每 25 ms 调 foc_boot_poll()w 1 触发 foc_boot_request()

5.3.1 本章启动方式

对比 lesson19(接口 2) 本课默认(接口 1,对齐官方)
路径 Align → 开环 Drag → Run Charge → Offset → Run
开环拖转 有(六步升频换相) FOC_BOOT_USE_ALIGN=0,不进 Align/Drag)
切入闭环时转子 已由 Drag 转起来 常为 静止或极低速,靠霍尔扇区角 + 起步 Iq 直接闭环拉转

本课默认 不是 「开环强拖到一定转速再切闭环」;

而是官方 Hall FOC 一样:硬件准备好电流采样后,立刻用霍尔 θ 进电流环,再软衔接速度环。

代码里仍保留 FOC_BOOT_ALIGN / FOC_BOOT_DRAG 枚举与阶段函数,并不在使用;正常启动不会走进 Drag(文件头注释亦写明)。

5.3.2 默认路径(FOC_BOOT_USE_ALIGN = 0

复制代码
IDLE
  → ChargeCap   低边三管 ON,~10 ms,给高边自举电容充电
  → OffsetCal   低边仍 ON + TIM1 继续跑,ADC 采零偏(必须 cal=1)
  → Run         霍尔 θ + Id=0 / Iq* 电流环 + SVPWM;再衔接速度外环
阶段 做什么 为何需要 关键注意
ChargeCap motor_pwm_turn_on_low_sides() 半桥自举电容没电,高边驱动起不来 ~10 ms 后 stop_pwm_output() 再进 Offset
OffsetCal 低边 ON + adc_curr_recalibrate() 运放零点;闭环用 I = Offset − ADC TIM1/CC4 不能停,否则注入采样几乎停、零偏失败/超时进 FAIL
Run foc_boot_enter_run() 同步霍尔 θ、seed Iq PI、交棒给 bsp_pid_app 见下节「软衔接」

串口日志典型顺序:

text 复制代码
FOC boot: charge boot cap (low sides ON)
FOC boot: charge done -> offset cal
FOC boot: offset cal (low sides ON, wait settle+samples)
FOC boot: offset done -> hall+Iq run (no align, official path)
FOC boot handover: hall=... rpm=... Iq=... Vq=... th=... (hall+PI)

5.3.3 Run 内的「软衔接」(不是 Drag,但是启动关键)

进入 Run 时转子往往还没转起来,因此有一层 闭环内 的过渡,容易和「开环启动」混淆:

  1. 交接(handover)

    • 用当前霍尔扇区中心角复位 foc_theta_hf_*
    • 给定起步 Iq* ≈ MOTOR_STARTUP_IQ_MA(并限幅);
    • pi_seed(Iq, Vq≈2.5 V),避免 PI 从 0 积分导致力矩塌陷;
    • foc_boot_take_handover() 把 Iq 交给速度环软衔接。
  2. Grace 宽限期

    • 刚切入时缩短堵转误判窗口;并尽量保证一段 以电流环为主 的窗口(宏:FOC_BOOT_GRACE_MIN_MSFOC_BOOT_GRACE_RPM_EXITFOC_BOOT_GRACE_FWD_EDGES)。
    • 转速与正向霍尔边沿够了再完全放开后续保护/速度环节奏,减少霍尔抖动导致的失速。
  3. 之后

    • ADC ISR 里 dq_current_loop_hf() 全速跑 Id/Iq + 官方 SVPWM;
    • 主循环速度 PI 输出更新 g_fm_target_iq,跟 t xxx / K3·K4 目标转速。

所以:

没有开环 Drag 升速 ;有的是 「电流环先拉转 → 速度环再接管」 的闭环软启动。

5.3.4 可选路径(FOC_BOOT_USE_ALIGN = 1,教学/标定)

复制代码
... → Offset → Align(Vd 固定在霍尔扇区中心,~800 ms) → Run
  • Align :开环 Vd 电压矢量把转子拉到已知扇区(不是六步 Drag)。
  • Drag:状态机仍保留,接口 1 上官方路径不依赖它;强拖逻辑易与霍尔扇区「钉死」冲突,本课默认关闭。
  • 串口还有 v / a 等开环标定命令(foc_boot_openloop_vq_step / foc_boot_openloop_vd_deg),用于核对 hall↔θ,不属于正常 w 1 启动流程

5.3.5 与 lesson19 / 官方启动对照

官方 Hall FOC lesson19 本课默认
Charge / Offset 弱化/不同硬件 有,对齐官方
Align / Drag 一般无 Drag 核心教学内容 默认关;Align 可选
切入 Run 霍尔 θ + FOC 拖转够速再切 Offset 完直接 Run
启动力矩 电流环 Iq 开环 duty 升频 起步 Iq + PI seed

5.4 与官方 / lesson19 运行对照

官方 Demo lesson19 本课 lesson20
接口 1 2 六步 1 互补
调制输出 PWMC_SetPhaseVoltage |V|→单占空比 同官方算法
坐标变换 ST MCM_* 经典 ST
电流极性 Offset−ADC 早期习惯因板而异 Offset−ADC
电流环 PWM 任务 主循环慢 ADC ISR ≈15 kHz
启动 Charge→Offset→Run Align→Drag→Run Charge→Offset→Run
启停 / 调速 KEY2 启停 串口 串口 w/s/t 启停K3/K4 运行中调速(见 5.5)

5.5 按键功能(骄阳板)

main 主循环调用 deal_key_input()bsp_bldcm_control.c),扫描骄阳板 SW2~SW5(按下为高电平):

板丝印 引脚 本课默认 FOC 速度环已开(w 1 仅电流环开 双环都关(开环占空比)
K1 / SW2 KEY1 PA0 --- --- 占空比 + 步进
K2 / SW3 KEY2 PG2 ---(官方 Demo 用此键启停) --- 占空比 - 步进
K3 / SW4 KEY3 PC13 目标 RPM +50(上限 3000) Iq +200 mA* 正转
K4 / SW5 KEY4 PG3 目标 RPM −50(下限 0) Iq −200 mA* 反转

说明:

  • 本课启停走串口(与官方 KEY2 启停不同);速度环跑起来后,用 K3/K4 现场改 g_fm_target_rpm,内部会 foc_spd_recalc_now() 立刻刷新斜坡与 Iq。
  • 步进宏:FOC_SPD_KEY_STEP=50CURR_PID_KEY_STEP=200bsp_pid_app.h)。
  • SW7 为硬件复位(NRST),不可软件扫描。

六、实验步骤

6.1 先烧官方 hex 验证硬件

官方DEMO可从官网下载。

复制代码
...\PMSM_FOC_V5.44_Hall_speed_control\PMSM_control\MDK-ARM\PMSM_control\PMSM_control.hex

烧录后按 KEY2(PG2):应能顺转。

6.2 本课固件

烧录后用串口启动:

复制代码
s 0          → 等 ~2s(电流重校准)
r
t 500
w 1

电机转起来后,可不用再发串口,直接按板子按键调速:

  • K3:目标转速 +50 RPM
  • K4:目标转速 −50 RPM

串口会打印类似 Key K3: RPM +50 -> 550, Iq=...

应该出现实验现象:

  • 出现 FOC boot handover 后 RPM 爬向目标(如 500);
  • g_fm_theta_deg 连续锯齿(非卡死在扇区中心);
  • 空载相电流约数十~数百 mA,不应持续数安堵转。

停机:w 0s 0

日志示例:

text 复制代码
[12:03:25.241]发→◇r
□
[12:03:25.244]收←◆[MOT] PI/fault reset, Iq=1642 mA

[12:03:26.740]发→◇t 500
□
[12:03:26.744]收←◆[MOT] RPM target: 500, Iq=1642 mA, use w 1 to run

[12:03:27.836]发→◇w 1
□
[12:03:27.840]收←◆[MOT] FOC boot start: IF1 sine+Hall poles=4 shift=240 deg
[MOT] FOC boot: charge->offset->hall+Iq (official)
[MOT] Speed loop ON, target 500 RPM (auto boot)
[MOT] [DBG] st=charge hall=6/6 rpm=0 Iu/Iv/Iw=0/-75/75 mA
[MOT] [DBG] Vd=0.00 Vq=0.00 Id=-70/0 Iq=-45/1642 theta=150 CCR=3865/1046/4554 Vbus=23.6
[MOT] [DBG] off=1553/1553/1553 inj=1532799 raw=1535/1552/1553 cal=1 en=1 fault=0
[MOT] FOC boot: charge boot cap (low sides ON)

[12:03:27.903]收←◆[MOT] FOC boot: charge done -> offset cal
[MOT] FOC boot: offset cal (low sides ON, wait settle+samples)

[12:03:28.356]收←◆[MOT] [DBG] st=offset hall=6/6 rpm=0 Iu/Iv/Iw=0/0/0 mA
[MOT] [DBG] Vd=0.00 Vq=0.00 Id=-0/0 Iq=0/1642 theta=150 CCR=3865/1046/4554 Vbus=24.4
[MOT] [DBG] off=0/0/0 inj=1540278 raw=1580/1559/1553 cal=0 en=1 fault=0

[12:03:28.753]收←◆[MOT] ADC off U/V/W=1554/1553/1553 cal=1 inj=1546040 raw=1560/1536/1553
[MOT] FOC boot: offset done -> hall+Iq run (no align, official path)
[MOT] FOC boot handover: hall=6 rpm=0 Iq=1600 Vq=+2.50 th=150 (hall+PI)
[MOT] FOC run: Iq handover RPM=54 Iq=1600 mA (hall+PI)

[12:03:28.854]收←◆[MOT] [DBG] st=run hall=2/2 rpm=375 Iu/Iv/Iw=-20/10/10 mA
[MOT] [DBG] Vd=-3.53 Vq=5.46 Id=35/0 Iq=28/1600 theta=68 CCR=2342/4059/1488 Vbus=23.8
[MOT] [DBG] off=1554/1553/1553 inj=1547803 raw=1555/1563/1553 cal=1 en=1 fault=0
[MOT] [DBG] drag step=2 duty=4071 fwd=95 raw=95 boot_theta=150 blend=0.00

[12:03:29.357]收←◆[MOT] [DBG] st=run hall=2/2 rpm=369 Iu/Iv/Iw=-25/90/-65 mA
[MOT] [DBG] Vd=-3.41 Vq=5.54 Id=-89/0 Iq=-56/746 theta=81 CCR=1930/4015/1585 Vbus=24.0
[MOT] [DBG] off=1554/1553/1553 inj=1555308 raw=1549/1560/1553 cal=1 en=1 fault=0
[MOT] [DBG] drag step=6 duty=4083 fwd=255 raw=255 boot_theta=150 blend=0.00

[12:03:29.854]收←◆[MOT] [DBG] st=run hall=6/6 rpm=389 Iu/Iv/Iw=-312/-115/427 mA
[MOT] [DBG] Vd=-3.32 Vq=5.59 Id=-47/0 Iq=126/1411 theta=188 CCR=1449/2427/4110 Vbus=23.2
[MOT] [DBG] off=1554/1553/1553 inj=1562817 raw=1526/1539/1553 cal=1 en=1 fault=0
[MOT] [DBG] drag step=5 duty=4134 fwd=255 raw=255 boot_theta=150 blend=0.00

[12:03:30.354]收←◆[MOT] [DBG] st=run hall=4/4 rpm=372 Iu/Iv/Iw=-140/-70/210 mA
[MOT] [DBG] Vd=-3.39 Vq=5.55 Id=-54/0 Iq=113/1611 theta=201 CCR=1577/1933/4023 Vbus=23.8
[MOT] [DBG] off=1554/1553/1553 inj=1570318 raw=1535/1552/1553 cal=1 en=1 fault=0
[MOT] [DBG] drag step=5 duty=4085 fwd=255 raw=255 boot_theta=150 blend=0.00

[12:03:30.469]发→◇s 0
□
[12:03:30.473]收←◆[MOT] All loops OFF, recalibrating current (wait ~2s)

6.3 变量曲线解析

6.3.1 电角度

红色是电角度,连续锯齿,0-360-0。

6.3.2 目标转速

蓝色是目标转速,按K3/K4改转速时平衡爬升、无明显持续振荡。

6.3.3 g_fm_target_iq Q轴电流给定 I q ∗ I q ∗ I^*_qIq* Iq∗Iq∗

希望电机产生多大转矩电流。开速度环 w 1时,主要由速度 PI 算出来写进去 ;转速偏低就抬高 I q ∗ I q ∗ I^*_qIq* Iq∗Iq∗ , 偏高就压低。

空载稳态往往很小(几十mA),加速或带载会明显变大。

g_fm_iq_actual 是 Q 轴电流实际反馈 I q I q I_qIq IqIq,意思:三相电流经 Clark→Park 算出来的真实 I q I q I_qIq IqIq​(再滤波后×1000 成 mA)。

电流环 PI 跟踪: ( e = g _ f m _ t a r g e t _ i q − g _ f m _ i q _ a c t u a l ) (e = g\_fm\_target\_iq - g\_fm\_iq\_actual) (e=g_fm_target_iq−g_fm_iq_actual),再输出 ( V q ) (V_q) (Vq)。

加速过程:

6.3.4 比较寄存器CCR g_fm_ccr_*

变量 对应相 含义
g_fm_ccr_u U 相 TIM1 CH1 的 CCR,决定 U 相上下管导通时间
g_fm_ccr_v V 相 TIM1 CH2 的 CCR
g_fm_ccr_w W 相 TIM1 CH3 的 CCR

来源:电流环算出 ( V d , V q ) (V_d,V_q) (Vd,Vq) → RevPark 得 ( V α , V β ) (V_\alpha,V_\beta) (Vα,Vβ) → 官方同款 SVPWM → 得到三相 CCR,再镜像到这三个 g_fm_* 给 FreeMASTER 看。

数值怎么理解

  • 不是"伏特",是定时器计数:越大,该相高边导通时间越长(中心对齐 PWM)。
  • 正常运行时三相 互不相等、随电角度轮流高低;。
  • 大致范围在约 0 ~ ARR(中心对齐下 50% 占空附近约在 ARR/2 一带)。

和扇区的关系

g_fm_svpwm_sector(1~6)变时,哪一相最高/最低会跟着换------这就是 SVPWM 在"转矢量"。

看曲线时注意

它们按 FOC 节拍(约 15 kHz)在变;FreeMASTER 采集比较慢,单相 ccr_u 会像乱毛刺。看表里三相瞬时值和扇区即可;要波形就加快采样,并给 CCR 单独 Y 轴。


七、小结与下一章

本章把 lesson15~18 的「能算」升级为「与官方 Hall FOC 同一套约定能转」:

  1. ST 坐标变换 + Offset−ADC + 相移 240 成套使用;
  2. 官方 PWMC_SetPhaseVoltage 级 SVPWM(s16 标度 + 内部 β 取反 + CCR 公式);
  3. PWM 频率电流环 + HALL_CalcElAngle 风格霍尔 θ
  4. 启动对齐官方 Charge→Offset→Run

代码地址:

https://gitee.com/xundh/learn-motor-stm32

相关推荐
实验如有神祝女士17 小时前
不同参数规模大模型在医学翻译场景的适配差异
论文阅读·人工智能·深度学习·学习·算法·语言模型·论文笔记
若衹如初見20 小时前
一步一步学习使用LiveBindings() LiveBindings图像绑定与自定义绑定方法()
学习·命令模式
kdxiaojie20 小时前
Linux 驱动研究 —— V4L2 (15)
linux·运维·笔记·学习
fanged21 小时前
udev番外--动态驱动加载(TODO)
学习
醉城夜风~21 小时前
HTML列表标签学习博客:有序列表、无序列表、自定义列表详解
前端·学习·html
Cachel wood21 小时前
hands-on-modern-rl:动手学强化学习 贝尔曼方程
开发语言·网络·python·学习·embedding
要加油GW1 天前
[ACTF2020 新生赛]Include
学习
早睡早起身体好1231 天前
Vue 3 路由与懒加载入门:从零完成一个迷你学习中心
javascript·vue.js·学习
minglie11 天前
蚂蚁S9矿板PS 将驱动编译到内核
学习
华如锦1 天前
【AGENT开发】python学习 Python Level 5
python·学习·elasticsearch