电机驱动开发学习22. 霍尔电角度标定(自动/手动标定与Flash固化)

电机驱动开发学习22. 霍尔电角度标定(自动/手动标定与Flash固化)

    • [一、 本章在系列中的位置](#一、 本章在系列中的位置)
      • [1.1 与前面章节的衔接](#1.1 与前面章节的衔接)
      • [1.2 本章目标](#1.2 本章目标)
    • [二、 为什么要标定霍尔电角度](#二、 为什么要标定霍尔电角度)
      • [2.1 θ \theta θ 误差的物理本质( I d / I q I_d / I_q Id/Iq 交叉耦合)](#2.1 θ \theta θ 误差的物理本质( I d / I q I_d / I_q Id/Iq 交叉耦合))
      • [2.2 PHASE_SHIFT 的几何含义](#2.2 PHASE_SHIFT 的几何含义)
      • [2.3 标定原理( V d V_d Vd 轴磁场锁相法)](#2.3 标定原理( V d V_d Vd 轴磁场锁相法))
    • [三、 工程改动与关键代码](#三、 工程改动与关键代码)
      • [3.1 角度计算接口解耦 (`bsp_foc.c / bsp_foc.h`)](#3.1 角度计算接口解耦 (bsp_foc.c / bsp_foc.h))
      • [3.2 标定核心反算算法 (`bsp_hall_cal.c`)](#3.2 标定核心反算算法 (bsp_hall_cal.c))
      • [3.3 状态机与多数表决去抖 (`bsp_hall_cal.c`)](#3.3 状态机与多数表决去抖 (bsp_hall_cal.c))
      • [3.4 Flash 掉电固化模块](#3.4 Flash 掉电固化模块)
    • [四、 完整串口命令集](#四、 完整串口命令集)
    • [五、 实战演练与验证步骤](#五、 实战演练与验证步骤)
      • [Step 1: 准备工作与电流零偏校准](#Step 1: 准备工作与电流零偏校准)
      • [Step 2: 执行一键标定 (`hc`)](#Step 2: 执行一键标定 (hc))
      • [Step 2.1 实机日志与分析(骄阳接口 1 + 配套电机)](#Step 2.1 实机日志与分析(骄阳接口 1 + 配套电机))
      • [Step 3: 锁相验证( I d / I q I_d / I_q Id/Iq 电流分离测试)](#Step 3: 锁相验证( I d / I q I_d / I_q Id/Iq 电流分离测试))
      • [Step 4: 闭环速度运行](#Step 4: 闭环速度运行)
    • [六、 常见问题排查与踩坑指南 (FAQ)](#六、 常见问题排查与踩坑指南 (FAQ))
      • [Q1: 执行 `hc` 标定时,电机剧烈抖动、抖发噪音,怎么办?](#Q1: 执行 hc 标定时,电机剧烈抖动、抖发噪音,怎么办?)
      • [Q2: 为什么每次执行 `hc 90 1200`,测出的 PHASE_SHIFT 都不一样(比如一会儿 240°,一会儿 180°)?](#Q2: 为什么每次执行 hc 90 1200,测出的 PHASE_SHIFT 都不一样(比如一会儿 240°,一会儿 180°)?)
      • [Q3: PHASE_SHIFT 与 电流 Offset 到底有什么本质区别?](#Q3: PHASE_SHIFT 与 电流 Offset 到底有什么本质区别?)
      • [Q4: `hc` 得到 240°,和上一章跑起来一样,是不是白做了?](#Q4: hc 得到 240°,和上一章跑起来一样,是不是白做了?)
      • [Q5: 只看到 DBG,没看到 `Hall cal OK`,算不算成功?](#Q5: 只看到 DBG,没看到 Hall cal OK,算不算成功?)
    • [七、 总结](#七、 总结)

前言 :L20/L21 一直使用套件默认 PHASE_SHIFT = 240° 。这个数字到底是角度、偏置,还是「扫出来的最优值」?

本章先把 240° 的含义讲清楚 (见 §2.2),再实现 Vd 锁相自动反算(hc)+ 运行时修改(ps)+ Flash 固化(hs

配套电机上 hc 常仍得到 240°------说明默认本来就对;换电机或改霍尔线序后,同一套流程才能测出「你的相移」。


一、 本章在系列中的位置

1.1 与前面章节的衔接

章节 已掌握的技术基石 本章如何调用与递进
20 霍尔有感 SVPWM FOC 官方约定、HALL_PHASE_SHIFT=240°、双闭环运行 240° 是出厂公称值 ,机械安装误差、接线差异会导致真值在 ± 15 ∘ \pm 15^\circ ±15∘ 甚至更大范围内偏差。
21 R3_2 扇区电流采样 高调制率下 Phase A/B/C 电流精准重建 电流采样准确后,控制性能的瓶颈转移到 θ \theta θ 的绝对精度 上。
15~17 Park / 矢量闭环 θ \theta θ 参与所有的 Park / Anti-Park 坐标变换 相移错几度 → \rightarrow → I d / I q I_d/I_q Id/Iq 交叉耦合、产生额外励磁损耗、转速发抖、发热剧烈。

💡 核心逻辑转换

  • Lesson 20/21:凭运气用默认 240° "能跑起来";
  • Lesson 22 :凭技术测出具体的物理相移(如 238.5°),写入 RAM 并固化至 Flash,实现电机极致效率。

1.2 本章目标

通过对电机施加 开环 V d V_d Vd 矢量 将转子"强行拉定"在已知角度,读取此时的霍尔状态,反算并纠正固定偏差。

复制代码
[串口命令/状态机] 
       │
       ▼
 1. 施加 Vd 开环电压 ──► 转子锁定到已知电角度 θ_cmd (例: 90°)
       │
       ▼
 2. 采样 16 次霍尔状态 ──► 多数表决筛选出稳定 hall 值 ──► 映射为扇区 sec
       │
       ▼
 3. 执行物理反算 ──► PHASE_SHIFT = wrap360( θ_cmd − (sec + 0.5) × 60° )
       │
       ▼
 4. 动态更新 FOC 指针 ──► 实时生效 ──► (可选) 写入 Flash 掉电保存
# 目标 工程落点 (代码/接口)
1 相移解耦 将宏定义改为运行时变量,提供 foc_hall_phase_shift_deg() 动态接口。
2 自动标定 实现 hc 串口指令: V d V_d Vd 锁相 → \rightarrow → 霍尔状态采样 → \rightarrow → 相移自动反算。
3 手动交互 支持 ps / ps <deg> 交互;a/v 用于细调与矢量检验。
4 掉电固化 支持 hs (Flash Write) / hl (Flash Read):基于 Sector 11 的持久化存储。
5 底层兼容 完全复用 L21 的三电阻采样与闭环结构 (Charge → \rightarrow → Offset → \rightarrow → Run)。

二、 为什么要标定霍尔电角度

2.1 θ \theta θ 误差的物理本质( I d / I q I_d / I_q Id/Iq 交叉耦合)

在 FOC 中,Park 变换与反 Park 变换依赖电角度 θ \theta θ 将三相静止坐标系转化为旋转 d − q d-q d−q 轴坐标系。

假设转子真实位置为 θ r e a l \theta_{real} θreal,但软件通过霍尔推算出的角度为 θ e s t = θ r e a l + δ \theta_{est} = \theta_{real} + \delta θest=θreal+δ(其中 δ \delta δ 为相位偏差):

I d e s t I q e s t \] = \[ cos ⁡ δ sin ⁡ δ − sin ⁡ δ cos ⁡ δ \] \[ I d r e a l I q r e a l \] \\begin{bmatrix} I_d\^{est} \\\\ I_q\^{est} \\end{bmatrix} = \\begin{bmatrix} \\cos\\delta \& \\sin\\delta \\\\ -\\sin\\delta \& \\cos\\delta \\end{bmatrix} \\begin{bmatrix} I_d\^{real} \\\\ I_q\^{real} \\end{bmatrix} \[IdestIqest\]=\[cosδ−sinδsinδcosδ\]\[IdrealIqreal

后果分析

  1. 转矩衰减 :期望输出纯转矩电流 I q I_q Iq,但实际上真实的 I q r e a l = I q cos ⁡ δ I_q^{real} = I_q \cos\delta Iqreal=Iqcosδ。若 δ = 30 ∘ \delta = 30^\circ δ=30∘,输出力矩直接打 86 折!
  2. 非法直轴电流 :漏出的 I d r e a l = I q sin ⁡ δ I_d^{real} = I_q \sin\delta Idreal=Iqsinδ 会产生无用的直轴磁场。如果 δ > 0 \delta > 0 δ>0,相当于强行弱磁 ;如果 δ < 0 \delta < 0 δ<0,相当于直轴增磁,导致电机发热剧烈,甚至发热烧毁 MOS 管。
  3. 高转速失步:在高速运行时,相位偏差会引发电流环系统正反馈振荡,产生巨大发声与抖动。

2.2 PHASE_SHIFT 的几何含义

开关型霍尔传感器在电机内部按照 120 ∘ 120^\circ 120∘ 电角度间隔放置。电机旋转时,3 个霍尔管脚输出 6 个组合状态(1~6)。软件将这 6 个状态映射为 6 个扇区(sec = 0..5)。

  • 扇区中心角 : θ c e n t e r = ( sec + 0.5 ) × 60 ∘ + PHASE_SHIFT \theta_{center} = (\text{sec} + 0.5) \times 60^\circ + \text{PHASE\_SHIFT} θcenter=(sec+0.5)×60∘+PHASE_SHIFT
  • 扇区起始角 : θ e d g e = sec × 60 ∘ + PHASE_SHIFT \theta_{edge} = \text{sec} \times 60^\circ + \text{PHASE\_SHIFT} θedge=sec×60∘+PHASE_SHIFT

📌 核心推论PHASE_SHIFT 的物理本质,就是霍尔硬件信号的扇区起点,距离电机 A A A 相反电动势过零点(或 ST 约定的 d d d 轴零点)的电角度偏移量

以公称值 240° 为例,霍尔状态与角度映射表如下:

霍尔原始值 (hall) 映射扇区 (sec) 扇区角度范围 (PHASE_SHIFT=240°) 扇区中心角 ( θ c e n t e r \theta_{center} θcenter)
5 0 240 ∘ ∼ 300 ∘ 240^\circ \sim 300^\circ 240∘∼300∘ 270 ∘ 270^\circ 270∘
1 1 300 ∘ ∼ 360 ∘ 300^\circ \sim 360^\circ 300∘∼360∘ 330 ∘ 330^\circ 330∘
3 2 0 ∘ ∼ 60 ∘ 0^\circ \sim 60^\circ 0∘∼60∘ 30 ∘ 30^\circ 30∘
2 3 60 ∘ ∼ 120 ∘ 60^\circ \sim 120^\circ 60∘∼120∘ 90 ∘ 90^\circ 90∘
6 4 120 ∘ ∼ 180 ∘ 120^\circ \sim 180^\circ 120∘∼180∘ 150 ∘ 150^\circ 150∘
4 5 180 ∘ ∼ 240 ∘ 180^\circ \sim 240^\circ 180∘∼240∘ 210 ∘ 210^\circ 210∘

2.3 标定原理( V d V_d Vd 轴磁场锁相法)

如何测出真实的 PHASE_SHIFT?最稳妥的办法就是"把转子定在已知电角度"。

下面用到的符号说明:

写法 读作 含义
θ_cmd theta command 命令电角度 :软件强制反 Park / SVPWM 使用的角度(hc 默认 90°)
V_align V align 定位用的 d 轴电压 :开环拉住转子的电压大小(由占空比 duty=1200 等折算),不是单独的芯片寄存器名

根据 FOC:施加 Vd = V_align、Vq = 0 ,并把变换角度固定为 θ_cmd 时,定子磁场停在 θ_cmd 方向。转子永磁体 N 极被吸过去,最后停在 θ_cmd 对应位置(锁相 / 定位)。

本课对应代码:foc_boot_openloop_vd_deg(θ_cmd, duty)duty 决定 V_align 有多大。

复制代码
          d轴合成磁场 (Vd > 0)
              ▲
              │   转子N极被强行拉至与d轴重合
              │  /
              │ / 
              │/  (物理位置 θ_real = θ_cmd)
──────────────┴──────────────► q轴
  1. 选定设定角 θ_cmd = 90°(在 PHASE_SHIFT=240 时正好是 hall=2 扇区中心,距两侧霍尔跳变沿各约 30°,容错最好)。

  2. 开启 Vd 供电,等待转子稳定(约 1.5 s)。

  3. 读取 hall,用 foc_hall_to_sector(hall) 得到 sec

  4. 对齐后应满足:

    θ_cmd ≡ (sec + 0.5) × 60° + PHASE_SHIFT (模 360°)

  5. 反算:

    PHASE_SHIFT = wrap360( θ_cmd − (sec + 0.5) × 60° )

⚠️ 注意:前提是 SVPWM 的 α-β 方向与硬件接线匹配(含反 Park 对 β 取反等 ST 约定)。


三、 工程改动与关键代码

软件架构在 Lesson 21 基础上拓展,增加了标定模块 bsp_hall_cal.c/.h,并将硬编码的宏更改为运行时可修改的全局角度解耦函数。

3.1 角度计算接口解耦 (bsp_foc.c / bsp_foc.h)

将静态的 FOC_HALL_ANGLE_OFFSET 宏重定向到运行时变量:

c 复制代码
/* bsp_foc.h */
float foc_hall_phase_shift_deg(void);
float foc_hall_phase_shift_rad(void);
void  foc_set_hall_phase_shift_deg(float deg);

/* 关键重定向:原算法中的宏直接替换为函数调用 */
#define FOC_HALL_ANGLE_OFFSET  (foc_hall_phase_shift_rad())

bsp_foc.c 中实现该变量的管理:

c 复制代码
/* bsp_foc.c */
static float g_hall_phase_shift_deg = MOTOR_HALL_PHASE_SHIFT_DEG; // 默认 240.0f

float foc_hall_phase_shift_deg(void) {
    return g_hall_phase_shift_deg;
}

float foc_hall_phase_shift_rad(void) {
    return g_hall_phase_shift_deg * (3.14159265f / 180.0f);
}

void foc_set_hall_phase_shift_deg(float deg) {
    /* 规范化到 0 ~ 360° */
    while (deg < 0.0f)   deg += 360.0f;
    while (deg >= 360.0f) deg -= 360.0f;
    g_hall_phase_shift_deg = deg;
}

3.2 标定核心反算算法 (bsp_hall_cal.c)

c 复制代码
#include "bsp_hall_cal.h"
#include "bsp_foc.h"

/**
  * @brief  角度 wrap 函数:限制在 [0, 360) 范围内
  */
static float wrap360(float deg) {
    while (deg < 0.0f)   deg += 360.0f;
    while (deg >= 360.0f) deg -= 360.0f;
    return deg;
}

/**
  * @brief  根据锁相角度和读取的霍尔值,计算相移 PHASE_SHIFT
  * @param  theta_cmd_deg: 开环锁相的目标电角度 (如 90.0f)
  * @param  hall: 稳定读取到的霍尔值 (1~6)
  * @retval 反算出的 PHASE_SHIFT (0~360°)
  */
float hall_cal_compute_shift_deg(float theta_cmd_deg, uint8_t hall)
{
    uint8_t sec = foc_hall_to_sector(hall);
    
    /* 扇区未包含 PHASE_SHIFT 时的基准中心角 */
    float center_wo_shift = ((float)sec + 0.5f) * 60.0f;
    
    /* 反算相移 */
    return wrap360(theta_cmd_deg - center_wo_shift);
}

3.3 状态机与多数表决去抖 (bsp_hall_cal.c)

为了防止机械微幅震荡或霍尔临界抖动导致误采,标定过程采用 16 次连续采样 + 多数表决(Majority Voting) 筛选真实霍尔值。

c 复制代码
typedef struct {
    uint8_t  is_running;
    uint32_t start_ms;
    float    theta_cmd;
    uint16_t duty;
    uint8_t  hall_samples[16];
    uint8_t  sample_idx;
} hall_cal_t;

static hall_cal_t g_cal;

/* 启动标定流程 */
void hall_cal_start(float theta_cmd_deg, uint16_t duty) {
    g_cal.theta_cmd = theta_cmd_deg;
    g_cal.duty      = duty;
    g_cal.start_ms  = HAL_GetTick();
    g_cal.sample_idx = 0;
    g_cal.is_running = 1;
    
    /* 开启开环 Vd 锁相输出 */
    foc_boot_openloop_vd_deg(g_cal.theta_cmd, g_cal.duty);
}

/* 需在主循环或 1ms 定时器中频繁调用的 Poll 函数 */
void hall_cal_poll(void) {
    if (!g_cal.is_running) return;

    /* 1. 等待电机旋转稳定 (默认 1500ms) */
    if (HAL_GetTick() - g_cal.start_ms < 1500) {
        return;
    }

    /* 2. 采样 16 次霍尔值 (每 5ms 采一次) */
    static uint32_t last_sample_ms = 0;
    if (HAL_GetTick() - last_sample_ms >= 5 && g_cal.sample_idx < 16) {
        last_sample_ms = HAL_GetTick();
        g_cal.hall_samples[g_cal.sample_idx++] = hall_read_raw(); // 读取硬件霍尔 GPIO
        return;
    }

    /* 3. 采样完成,进行多数表决 */
    if (g_cal.sample_idx >= 16) {
        uint8_t counts[8] = {0};
        for (int i = 0; i < 16; i++) {
            if (g_cal.hall_samples[i] <= 6) {
                counts[g_cal.hall_samples[i]]++;
            }
        }
        
        uint8_t best_hall = 0;
        uint8_t max_cnt  = 0;
        for (int h = 1; h <= 6; h++) {
            if (counts[h] > max_cnt) {
                max_cnt = counts[h];
                best_hall = h;
            }
        }

        /* 4. 停止 PWM,计算并更新相移 */
        foc_stop_pwm();
        g_cal.is_running = 0;

        if (best_hall != 0) {
            float shift = hall_cal_compute_shift_deg(g_cal.theta_cmd, best_hall);
            foc_set_hall_phase_shift_deg(shift);
            printf(">> Hall Cal OK: hall=%d sec=%d -> PHASE_SHIFT=%.1f deg\r\n", 
                    best_hall, foc_hall_to_sector(best_hall), shift);
        } else {
            printf(">> Hall Cal ERROR: Invalid Hall Read!\r\n");
        }
    }
}

3.4 Flash 掉电固化模块

选用 STM32F407 的 Sector 11 (地址 0x080E0000)作为参数保存区:

c 复制代码
#define FLASH_PARAM_ADDR   0x080E0000     // Sector 11 起始地址
#define PARAM_MAGIC        0x48434C31     // 魔数 "HCL1"

typedef struct {
    uint32_t magic;
    float    phase_shift_deg;
    uint32_t checksum;
} flash_param_t;

void hall_cal_save_flash(void) {
    flash_param_t param;
    param.magic = PARAM_MAGIC;
    param.phase_shift_deg = foc_hall_phase_shift_deg();
    param.checksum = param.magic + (uint32_t)param.phase_shift_deg;

    HAL_FLASH_Unlock();
    
    /* 1. 擦除 Sector 11 */
    FLASH_EraseInitTypeDef erase;
    erase.TypeErase    = FLASH_TYPEERASE_SECTORS;
    erase.Sector       = FLASH_SECTOR_11;
    erase.NbSectors    = 1;
    erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
    uint32_t sector_err = 0;
    HAL_FLASHEx_Erase(&erase, &sector_err);

    /* 2. 写入数据 */
    uint32_t *pData = (uint32_t *)&param;
    for (int i = 0; i < sizeof(param)/4; i++) {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_PARAM_ADDR + (i*4), pData[i]);
    }

    HAL_FLASH_Lock();
    printf(">> Saved to Flash Sector11: PHASE_SHIFT = %.1f\r\n", param.phase_shift_deg);
}

四、 完整串口命令集

下表整理了本工程支持的所有调测命令:

命令分类 指令格式 功能说明 示例及响应
查询/手动修改 ps 打印当前 RAM 中的 PHASE_SHIFT >> Current PHASE_SHIFT = 240.0 deg
ps <deg> 手动设定运行时相移(仅 RAM,实时生效) ps 238.5 → \rightarrow → 动态切为 238.5°
自动标定 hc 默认参数(锁角 90 ∘ 90^\circ 90∘,占空比 1200)执行自动标定 >> Hall cal OK: hall=2 sec=3 -> PHASE_SHIFT=240.0 deg
hc <duty> 修改对齐占空比执行标定 hc 1500 (强磁电机加大占空比)
hc <deg> <duty> 指定角度与占空比标定 hc 30 1200
持久化存储 hs 将当前 RAM 中的 PHASE_SHIFT 写入 Flash >> Saved to Flash Sector11
hl 从 Flash 重新加载参数 >> Loaded from Flash: 238.5 deg
hd 恢复出厂硬编码默认值(240.0°) >> Reset to default: 240.0 deg
开环验证 a <deg> <duty> 手动强制 V d V_d Vd 锁相到指定电角度 a 90 1200
v <duty> 当前扇区中心 施加 V d V_d Vd 验证锁相角度 v 1200(若相移准确, I q I_q Iq 应接近 0)

五、 实战演练与验证步骤

Step 1: 准备工作与电流零偏校准

  1. 安全确认:电机脱开负载(空载),转轴无缠绕;驱动板接好母线电源(如 24V)。
  2. 电流零偏校准 :上电后,先关闭速度/电流环,执行 cal 命令。
bash 复制代码
s 0        # 关速度环
w 0        # 关电流环
cal        # 执行 ADC 采样 Offset 校准

等待 2 秒,输入 pid 确认 cal=1


Step 2: 执行一键标定 (hc)

串口输入:

bash 复制代码
hc
  • 观察现象:电机会发出轻微响声,并迅速旋转固定在某一个物理位置,静止 1.5 秒。
  • 串口输出
text 复制代码
>> Start Hall Calibration: deg=90.0, duty=1200...
>> Hall cal OK: hall=2 sec=3 -> PHASE_SHIFT=240.0 deg

如果测出的角度在 230° ~ 250° 之间,说明硬件安装与官方标准一致,微小的偏差是由机械制造公差导致的;如果测出角度为 180°300°,说明霍尔线序 U / V / W U/V/W U/V/W 接入顺序反了或者相位插错

执行固化:

bash 复制代码
hs         # 写入 Flash,防止掉电丢失

Step 2.1 实机日志与分析(骄阳接口 1 + 配套电机)

下面是一次完整实机过程(串口时间戳已保留)。最后结论:

Hall cal OK → PHASE_SHIFT=240.0°,与编译默认相同。

对本套硬件,闭环体感与 lesson21 无区别;本课价值是「现场确认 + 可改可存」,功能可在生产中换其它电机时使用。

(1)零偏与标定前状态
text 复制代码
发→ cal
收← Current zero recalibrating, wait ~2s then check pid (cal=1)

发→ pid
收← RPM SP=500  ACT=0  speed_loop=0
     Iq SP=1500 mA  Iq=-5  Id=2  U/V/W=-25/50/-25
     Vd=0.00 V  Vq=0.00 V  theta=330.0 deg  SVPWM sec=0
     CCR U/V/W=0/0/0  Vbus=24.5
     curr_loop=0  en=0  fault=0  protect=1  cal=1
     boot_stage=idle(0)  ...
     hall=1  off=1554/1554/1554  ...
     PHASE_SHIFT=240.0 deg (default=240)  hall_cal=0  last_hall=0
字段 说明
cal=1 OK 电流零偏完成,可以发 hc
en=0 / Vd=0 OK 双环关闭,未误出力
PHASE_SHIFT=240 hall_cal=0 OK 尚未跑过自动标定,仍用默认
hall=1 theta=330 一致 240° 公式下 hall1 中心角就是 330°
(2)执行 hc(锁 90° / duty=1200)
text 复制代码
发→ hc
收← Hall cal: Vd lock theta=90 deg duty=1200, wait 1500 ms...

[DBG] st=idle hall=3/3 rpm=76 Iu/Iv/Iw=815/-730/-85 mA
      Vd=2.98 Vq=0.00 Id=43/0 Iq=68/1500 theta=0 ... en=1

[DBG] st=idle hall=2/2 rpm=0 Iu/Iv/Iw=2351/-1208/-1143 mA
      Vd=2.76 Vq=0.00 Id=2005/0 Iq=1190/1500 theta=60 ... en=1

[DBG] st=idle hall=2/2 rpm=0 ... Id=2042 Iq=1192 theta=60 ... en=1

收← Hall cal OK: hall=2 sec=3 → PHASE_SHIFT=240.0 deg
       (theta_cmd=90, center_wo_shift=210)
       Apply runtime done. Optional: hs (Flash) ...
       Verify: v 1200 then check Id>>Iq;  w 1 closed-loop

(串口可能 显示成 鈫? 之类乱码,忽略即可,数值仍以 PHASE_SHIFT=240.0 为准。)

过程是否合理:

阶段 日志现象 是否正常
启动 Vd lock theta=90 duty=1200 正常
前约 0.5 s hall=3rpm=76 转子被拉向锁角,正常
稳定 hall=2rpm=0Vd≈2.8 已锁住,正常
锁住时 Id≈2000Iq≈1190 两者都大 hc 过程中也正常(见下)
结束 Hall cal OK ... 240.0 成功

验算:

PHASE_SHIFT = w r a p 360 ( 90 − ( 3 + 0.5 ) × 60 ) = w r a p 360 ( 90 − 210 ) = 240 ∘ \] \[\\text{PHASE\\_SHIFT}=\\mathrm{wrap}_{360}(90-(3+0.5)\\times 60)=\\mathrm{wrap}_{360}(90-210)=240\^\\circ\] \[PHASE_SHIFT=wrap360(90−(3+0.5)×60)=wrap360(90−210)=240∘

与打印一致;hall=2 → sec=3 正是「θ_cmd=90°、相移=240°」时该落到的扇区。

为什么 hc 过程中 Id、Iq 都很大,不能用来判好坏?

  • hc绝对电角度 90° 施加 (V_d);
  • DBG 里的 Id/Iq 仍用霍尔推算的 θ 做 Park(稳定后约 theta=60,扇区起点角);
  • 电压角与反馈角差约 30° → Id/Iq 交叉耦合,两者都会偏大。

因此:不要用 hc 等待期间的 Id/Iq 判断相移 ;以最后一行 PHASE_SHIFT 为准,再用后面的 v 1200 验证。

结束后 en=0、相电流回到几十 mA 量级,属于关驱动后的正常空闲;若仍看到一帧带旧 Id 的 DBG,是日志节拍滞后,可再等 0.5 s 或发 pid 看一眼。

(3)和上一章(lesson21)的关系
说明
测得相移 240° = 编译默认
闭环效果 与 lesson21 基本无差别(角度链路没变)
本章收获 用实机证明「默认 240° 对本套件是准的」;并留下 ps/hc/hs 入口,换电机或改接线后不必改宏重编

只有当 hc 测出明显不是 240°(例如差一整格 60°,或稳定偏 10° 以上)时,闭环噪音/Iq 波动才会相对前一章有可感知差异。


Step 3: 锁相验证( I d / I q I_d / I_q Id/Iq 电流分离测试)

使用 v 命令在当前相移下施加 V d V_d Vd 开环电压:

bash 复制代码
v 1200
pid
  • 判定标准
  • 相移准确时 :转子被强行对齐,此时 I d I_d Id 有明显数值(如 1000~2000mA),I q I_q Iq 几乎为 0 ( ± 50 mA \pm 50\text{mA} ±50mA 抖动)
  • 相移错误时 : I q I_q Iq 数值极大,且电机伴有明显的蜂鸣声甚至缓慢微动。

Step 4: 闭环速度运行

bash 复制代码
t 400      # 设定目标转速 400 RPM
w 1        # 使能速度闭环

对本套件实机(见 Step 2.1):测得仍是 240° ,空载 t 400 / w 1 应与 lesson21 同级------这是预期结果,不是标定失败。

若换电机后 hc 得到例如 238.5° 或偏差更大,再用 FreeMASTER 对比标定前后的 Iq / RPM 波动才有意义:

复制代码
       相移明显不准时                         相移校正后(示例)
  ┌─────────────────────────────┐         ┌─────────────────────────────┐
  │ Iq 波动大、易交叉到 Id       │         │ Iq 更贴近转矩需求            │
  │ 转速锯齿、噪音偏大           │         │ 转速更稳、声音更干净         │
  └─────────────────────────────┘         └─────────────────────────────┘

六、 常见问题排查与踩坑指南 (FAQ)

Q1: 执行 hc 标定时,电机剧烈抖动、抖发噪音,怎么办?

原因 :标定占空比 duty 过大,导致开环电流过大,触发了驱动板的过流保护或产生强震。

解决办法 :降低占空比重新标定,例如发送 hc 90 600hc 90 800

Q2: 为什么每次执行 hc 90 1200,测出的 PHASE_SHIFT 都不一样(比如一会儿 240°,一会儿 180°)?

原因

  1. 电机摩擦力过大,开环拉不动转子,未完全停靠在 90 ∘ 90^\circ 90∘ 位置。
  2. 锁相角度(如 90 ∘ 90^\circ 90∘)正好选在了霍尔状态的跳变边沿上 ,受磁体公差影响在两个霍尔状态间切换。
    解决办法:尝试改变标定锚定角,用不同角度多测几次:
bash 复制代码
hc 30 1200
hc 90 1200
hc 150 1200

正确的相移计算逻辑在不同 theta_cmd 下反算的 PHASE_SHIFT 应该是一致的(模 360 ∘ 360^\circ 360∘ 后相等)。

Q3: PHASE_SHIFT 与 电流 Offset 到底有什么本质区别?

维度 电流 Offset (ADC Offset) 霍尔 PHASE_SHIFT
物理对象 运放与 ADC 采样通道的零点电压 霍尔传感器与电机磁极的安装空间角度
对控制的影响 影响电流采样的准确度,偏大导致零点漂移 影响 Park 变换,偏大导致 I d / I q I_d/I_q Id/Iq 耦合
校准条件 电机静止、PWM 完全关闭 必须发波,将电机强行锁相
校准指令 cal hc

Q4: hc 得到 240°,和上一章跑起来一样,是不是白做了?

不是。 说明野火配套霍尔安装与官方 HALL_PHASE_SHIFT=240 一致,L20/L21「能转」有物理依据。

本章交付的是:确认方法 + 运行时改相移 + 可选 Flash 。换电机、改霍尔线序后,同一套 hc/ps/hs 才能立刻体现差异。

Q5: 只看到 DBG,没看到 Hall cal OK,算不算成功?

不算。 DBG 是周期慢日志;标定成败以

Hall cal OK: ... PHASE_SHIFT=...

或随后 ps 打印为准。hc 结束后 st=idleen=0hall=2theta=60 只说明回到空闲,且与 240° 公式自洽,仍建议再发 ps 核对。


七、 总结

本章将电机控制从"用默认参数能转"推进到"能量产式确认/改写相移":

  1. 接口解耦FOC_HALL_ANGLE_OFFSET 绑定运行时相移,支持 ps / FreeMASTER;
  2. 标定算法 :(V_d) 锁相 + 多数表决 + 几何反算,hc 约 1.5 s 出结果;
  3. 参数固化 :Flash Sector11(hs/hl),掉电可保留;
  4. 实机结论(配套电机) :测得 240° = 默认,闭环与 lesson21 同级------标定成功的标志是「测得可信」,不一定是「数字变了」。
相关推荐
m4Rk_2 小时前
【论文阅读】Agent 记忆机制(26):Infini Memory——将长期记忆维护成可读写的主题文档
论文阅读·人工智能·学习·开源·github
正经人_x3 小时前
学习日记46:LISA: Reasoning Segmentation via Large Language Model
人工智能·学习·语言模型
神龙天舞20014 小时前
CMake构建学习笔记-通用的CMake构建脚本
笔记·学习
似的83512 小时前
一步一步学习使用FireMonkey动画() 使用TAnimator类创建动画
linux·学习·nginx
fanged12 小时前
总线学习3--SPI番外(TODO)
学习
ThsPool14 小时前
【遥感学习整理 02】ENVI遥感图像处理基础:从数据读取到遥感信息产品
图像处理·人工智能·学习
05664615 小时前
Python康复训练——常用标准库
开发语言·python·学习
05664616 小时前
Python康复训练——控制流与函数
开发语言·python·学习
早睡早起身体好12317 小时前
为什么 Network 中会出现两个同名请求?——CORS 预检请求学习笔记
网络·笔记·学习·网络安全