BLDC BLOCK 换相控制技术

BLDC块换相控制技术指南

概述

无刷直流电机(BLDC)是现代电机控制领域的重要组成部分,广泛应用于工业自动化、机器人、无人机等领域。本文将基于HPMicro SDK中的bldc_block示例,详细介绍BLDC电机的块换相控制技术,包括控制原理、软件架构和实际应用。

1. BLDC电机基础理论

1.1 BLDC电机结构

BLDC电机由定子和转子组成,定子通常采用三相绕组结构,转子使用永磁体。与传统有刷直流电机相比,BLDC电机具有以下优势:

  • 高效率:无电刷摩擦损耗
  • 长寿命:无机械磨损部件
  • 低噪音:运行平稳
  • 高转矩密度:功率重量比优异

1.2 换相控制原理

块换相(Block Commutation)是BLDC电机最基本的控制方式,也称为六步换相或方波控制。其核心思想是根据转子位置信息,依次给三相绕组通电,产生旋转磁场驱动转子运转。

\text{换相周期} = \frac{360°}{6} = 60°
\text{每个周期持续时间} = \frac{60°}{\omega \cdot p}

其中:

  • \omega 为转子角速度
  • p 为电机极对数

1.3 位置检测方法

BLDC电机需要准确的转子位置信息来确定换相时机。本示例支持两种检测方式:

Hall传感器检测

  • 使用三个Hall传感器布置在定子上
  • 检测转子磁场变化
  • 提供6个状态信息(001, 010, 011, 100, 101, 110)

光电编码器检测

  • 使用QEI
  • 提供高精度位置信息
  • 支持增量式和绝对式编码器

2. 软件架构分析

2.1 系统架构概述

\text{主控制循环} \rightarrow \text{MCL库} \begin{cases}
\text{编码器处理} \rightarrow \text{位置/速度计算} \\
\text{控制算法} \rightarrow \text{PID速度环} \\
\text{驱动输出} \rightarrow \text{PWM生成} \\
\text{检测功能} \rightarrow \text{故障保护}
\end{cases}

2.2 核心数据结构

系统使用motor0_t结构体封装所有电机控制相关的数据:

typedef struct {
    mcl_encoder_t encoder;              // 编码器对象
    mcl_filter_iir_df1_t encoder_iir;   // IIR滤波器
    mcl_drivers_t drivers;              // PWM驱动器
    mcl_control_t control;              // 控制算法
    mcl_loop_t loop;                    // 主控制环
    mcl_analog_t analog;                // 模拟量采集
    mcl_detect_t detect;                // 检测模块
    struct {
        // 配置参数结构体
        mcl_cfg_t mcl;
        mcl_encoer_cfg_t encoder;
        // ... 其他配置
    } cfg;
} motor0_t;

2.3 关键参数配置

电机物理参数

motor0.cfg.mcl.physical.motor.pole_num = MOTOR_POLE_NUM;    // 极对数
motor0.cfg.mcl.physical.motor.i_max = 9;                   // 最大电流 (A)
motor0.cfg.mcl.physical.motor.vbus = 24;                   // 母线电压 (V)
motor0.cfg.mcl.physical.motor.rpm_max = 3500;              // 最大转速 (rpm)

PWM参数配置

motor0.cfg.mcl.physical.board.pwm_frequency = PWM_FREQUENCY;  // PWM频率 20kHz
motor0.cfg.mcl.physical.board.pwm_reload = PWM_RELOAD;       // PWM重载值

控制参数配置

motor0.cfg.control.speed_pid_cfg.cfg.kp = BOARD_BLDC_BLOCK_SPEED_KP;  // 比例系数
motor0.cfg.control.speed_pid_cfg.cfg.ki = BOARD_BLDC_BLOCK_SPEED_KI;  // 积分系数

3. 外设初始化详解

3.1 PWM外设初始化

PWM是BLDC控制的核心外设,系统支持PWM和PWMV2两种模块。初始化过程包括:

PWM模块初始化

void pwm_init(void)
{
    uint8_t cmp_index = BOARD_BLDCPWM_CMP_INDEX_0;
    pwm_cmp_config_t cmp_config[2] = {0};
    pwm_config_t pwm_config = {0};

    // 停止PWM计数器
    pwm_stop_counter(MOTOR0_BLDCPWM);
    reset_pwm_counter();

    // 设置PWM重载值和起始计数值
    pwm_set_reload(MOTOR0_BLDCPWM, 0, PWM_RELOAD);
    pwm_set_start_count(MOTOR0_BLDCPWM, 0, 0);

    // 配置比较器
    cmp_config[0].mode = pwm_cmp_mode_output_compare;
    cmp_config[0].cmp = PWM_RELOAD + 1;
    cmp_config[0].update_trigger = pwm_shadow_register_update_on_shlk;

    // PWM输出配置
    pwm_config.enable_output = true;
    pwm_config.dead_zone_in_half_cycle = 100;  // 死区时间
    pwm_config.invert_output = false;
}

关键配置参数说明

  • PWM频率PWM_FREQUENCY = 20000 (20kHz)
  • 重载值PWM_RELOAD = (motor_clock_hz/PWM_FREQUENCY) - 1
  • 死区时间:防止上下桥臂直通,设置为100个时钟周期

3.2 编码器外设初始化

系统支持Hall传感器和QEI编码器两种位置检测方式:

Hall传感器初始化

hpm_mcl_stat_t encoder_init(void)
{
#ifdef HPMSOC_HAS_HPMSDK_HALL
    trgm_output_t config = {0};

    // 初始化Hall引脚
    init_hall_trgm_pins();

    // 配置TRGM输出
    config.invert = false;
    config.input = BOARD_BLDC_HALL_TRGM_HALL_U_SRC;
    trgm_output_config(BOARD_BLDC_HALL_TRGM, TRGM_TRGOCFG_HALL_U, &config);

    // 配置Hall模块
    hall_counter_reset_assert(BOARD_BLDC_HALL_BASE);
    hall_phase_config(BOARD_BLDC_HALL_BASE, 1, hall_count_delay_start_after_uvw_toggle);
    hall_load_read_trigger_event_enable(BOARD_BLDC_HALL_BASE, HALL_EVENT_PHUPT_FLAG_MASK);

    // 使能中断
    intc_m_enable_irq_with_priority(BOARD_BLDC_HALL_IRQ, 1);
    hall_counter_reset_release(BOARD_BLDC_HALL_BASE);
#endif
}

QEI编码器初始化

#ifdef HPMSOC_HAS_HPMSDK_QEIV2
    qeiv2_uvw_config_t uvw_config;

    // 初始化QEI引脚
    init_qeiv2_uvw_pins(BOARD_BLDC_QEIV2_BASE);

    // 配置QEI工作模式
    qeiv2_reset_counter(BOARD_BLDC_QEIV2_BASE);
    qeiv2_set_work_mode(BOARD_BLDC_QEIV2_BASE, qeiv2_work_mode_uvw);
    qeiv2_config_abz_uvw_signal_edge(BOARD_BLDC_QEIV2_BASE, true, true, true, true, true);

    // 配置UVW位置检测
    qeiv2_get_uvw_position_defconfig(&uvw_config);
    uvw_config.pos_opt = qeiv2_uvw_pos_opt_next;
    qeiv2_config_uvw_position(BOARD_BLDC_QEIV2_BASE, &uvw_config);

    // 配置脉冲和中断
    qeiv2_set_pulse0_num(BOARD_BLDC_QEIV2_BASE, 1);
    qeiv2_enable_irq(BOARD_BLDC_QEIV2_BASE, QEIV2_EVENT_PULSE0_FLAG_MASK);
    intc_m_enable_irq_with_priority(BOARD_BLDC_QEIV2_IRQ, 1);
#endif

3.3 定时器初始化

定时器用于周期性执行控制算法:

static void timer_init(void)
{
    gptmr_channel_config_t config;

    // 添加时钟到时钟组
    clock_add_to_group(BOARD_BLDC_TMR_CLOCK, 0);

    // 获取默认配置
    gptmr_channel_get_default_config(BOARD_BLDC_TMR_1MS, &config);

    // 配置定时器参数
    config.debug_mode = 0;
    config.reload = BLOCK_TMR_RLD + 1;          // 重载值
    config.cmp[0] = BLOCK_TMR_RLD;              // 比较值
    config.cmp[1] = config.reload;

    // 使能中断和配置通道
    gptmr_enable_irq(BOARD_BLDC_TMR_1MS, GPTMR_CH_CMP_IRQ_MASK(BOARD_BLDC_TMR_CH, BOARD_BLDC_TMR_CMP));
    gptmr_channel_config(BOARD_BLDC_TMR_1MS, BOARD_BLDC_TMR_CH, &config, true);
    intc_m_enable_irq_with_priority(BOARD_BLDC_TMR_IRQ, 1);
}

定时器参数计算

T_{timer} = \frac{BLOCK\_TMR\_RLD + 1}{f_{timer\_clock}} = \frac{BOARD\_BLDC\_TMR\_RELOAD \times 1000}{f_{timer\_clock}} = 1ms

4. 软件结构框架

4.1 分层架构设计

系统采用分层设计,从下到上分为:

\text{应用层} \rightarrow \text{MCL中间件层} \rightarrow \text{驱动层(Driver)} \rightarrow \text{硬件层(Hardware)}

各层职责

  • 硬件层:芯片寄存器和外设
  • 驱动层:封装硬件操作接口
  • MCL中间件层:电机控制算法库
  • 应用层:用户应用逻辑

4.2 回调函数架构

系统使用回调函数实现硬件抽象,便于移植:

// 驱动回调函数注册
motor0.cfg.drivers.callback.init = pwm_init;
motor0.cfg.drivers.callback.enable_all_drivers = enable_all_pwm_output;
motor0.cfg.drivers.callback.disable_all_drivers = disable_all_pwm_output;
motor0.cfg.drivers.callback.update_duty_cycle = pwm_duty_set;
motor0.cfg.drivers.callback.disable_drivers = pwm_disable_channel;
motor0.cfg.drivers.callback.enable_drivers = pwm_enable_channel;

// 编码器回调函数注册
motor0.cfg.encoder.callback.init = encoder_init;
motor0.cfg.encoder.callback.start_sample = encoder_start_sample;
motor0.cfg.encoder.callback.get_theta = encoder_get_theta;
motor0.cfg.encoder.callback.get_absolute_theta = encoder_get_abs_theta;
motor0.cfg.encoder.callback.get_uvw_level = encoder_get_uvw_level;

// 控制回调函数注册
motor0.cfg.control.callback.init = motor0_control_init;

// 检测回调函数注册
motor0.cfg.detect.callback.disable_output = disable_all_pwm_output;

4.3 初始化流程

系统的初始化流程如下:

1. 硬件初始化:board_init()、时钟配置、引脚初始化

2. 电机参数配置:物理参数设置、控制参数设置、回调函数注册

3. MCL模块初始化

  • hpm_mcl_filter_iir_df1_init()
  • hpm_mcl_encoder_init()
  • hpm_mcl_drivers_init()
  • hpm_mcl_control_init()
  • hpm_mcl_loop_init()
  • hpm_mcl_detect_init()

4. 外设初始化:pwm_init()、timer_init()、encoder_init()

5. 启动电机控制:hpm_mcl_loop_start_block()、中断使能、hpm_mcl_loop_enable()

4.4 运行时框架

系统运行时的主要流程:

// 主循环
while (1) {
    // 用户输入处理
    // 速度设定
    user_speed.value = speed * MCL_2PI * MOTOR_POLE_NUM;
    hpm_mcl_loop_set_speed(&motor0.loop, user_speed);
}

// 定时器中断 (1ms周期)
void isr_gptmr(void)
{
    hpm_mcl_detect_loop(&motor0.detect);        // 故障检测
    hpm_mcl_encoder_process(&motor0.encoder, tick); // 编码器处理
    hpm_mcl_loop(&motor0.loop);                 // 主控制循环
}

// Hall中断 (换相触发)
void isr_hall(void)
{
    hpm_mcl_uvw_get_theta(BOARD_BLDC_HALL_BASE, NULL, MOTOR_ANGLE_DETA, &encoder_theta);
    hpm_mcl_loop_refresh_block(&motor0.loop);   // 刷新块换相
}

5. 控制算法实现

5.1 速度控制环

系统采用PI控制器实现速度闭环控制:

e(k) = \omega_{ref} - \omega_{actual}
u(k) = K_p \cdot e(k) + K_i \sum_{i=0}^{k} e(i) \cdot T_s

其中:

  • e(k) 为速度误差
  • \omega_{ref} 为参考速度
  • \omega_{actual} 为实际速度
  • K_p, K_i 为PI参数
  • T_s 为采样周期

5.2 换相逻辑

块换相控制根据位置传感器信号确定当前扇区,并输出对应的PWM控制信号:

扇区 Hall状态 导通相 角度范围
1 101 AH+BL 0° - 60°
2 100 AH+CL 60° - 120°
3 110 BH+CL 120° - 180°
4 010 BH+AL 180° - 240°
5 011 CH+AL 240° - 300°
6 001 CH+BL 300° - 360°

5.3 IIR滤波器

系统使用二阶IIR滤波器对编码器信号进行滤波处理:

H(z) = \frac{b_0 + b_1z^{-1} + b_2z^{-2}}{1 + a_1z^{-1} + a_2z^{-2}}

滤波器参数通过双线性变换从模拟域转换到数字域,实现低通滤波功能。

6. 中断服务程序

6.1 Hall中断处理

void isr_hall(void)
{
    hall_clear_status(BOARD_BLDC_HALL_BASE, hall_get_status(BOARD_BLDC_HALL_BASE));
    hpm_mcl_uvw_get_theta(BOARD_BLDC_HALL_BASE, NULL, MOTOR_ANGLE_DETA, &encoder_theta);
    hpm_mcl_loop_refresh_block(&motor0.loop);
}

每当Hall传感器状态发生变化时,系统会:

  1. 清除中断状态
  2. 计算当前转子角度
  3. 刷新控制循环

6.2 定时器中断处理

void isr_gptmr(void)
{
    if (gptmr_check_status(BOARD_BLDC_TMR_1MS, GPTMR_CH_CMP_IRQ_MASK(BOARD_BLDC_TMR_CH, BOARD_BLDC_TMR_CMP))) {
        gptmr_clear_status(BOARD_BLDC_TMR_1MS, GPTMR_CH_CMP_IRQ_MASK(BOARD_BLDC_TMR_CH, BOARD_BLDC_TMR_CMP));
        hpm_mcl_detect_loop(&motor0.detect);
        hpm_mcl_encoder_process(&motor0.encoder, motor0.cfg.mcl.physical.time.mcu_clock_tick / MCL_USEC_TO_HZ(TIMER_TS));
        hpm_mcl_loop(&motor0.loop);
    }
}

定时器中断(1ms周期)执行:

  1. 故障检测
  2. 编码器数据处理
  3. 主控制循环

7. PWM驱动实现

7.1 PWM配置

系统支持两种PWM模块:

  • PWM模块:传统PWM控制器
  • PWMV2模块:增强型PWM控制器

PWM频率计算:

f_{PWM} = \frac{f_{clock}}{PWM\_RELOAD + 1}

7.2 死区时间

为防止上下桥臂直通,系统配置了死区时间:

pwm_config.dead_zone_in_half_cycle = 100;  // 死区时间设置

7.3 强制输出模式

当需要关闭所有PWM输出时,系统使用强制输出模式:

pwm_set_force_output(MOTOR0_BLDCPWM,
                    PWM_FORCE_OUTPUT(BOARD_BLDC_UH_PWM_OUTPIN, pwm_output_0)
                    | PWM_FORCE_OUTPUT(BOARD_BLDC_UL_PWM_OUTPIN, pwm_output_0)
                    | PWM_FORCE_OUTPUT(BOARD_BLDC_VH_PWM_OUTPIN, pwm_output_0)
                    | PWM_FORCE_OUTPUT(BOARD_BLDC_VL_PWM_OUTPIN, pwm_output_0)
                    | PWM_FORCE_OUTPUT(BOARD_BLDC_WH_PWM_OUTPIN, pwm_output_0)
                    | PWM_FORCE_OUTPUT(BOARD_BLDC_WL_PWM_OUTPIN, pwm_output_0));

7.4 换相与占空比控制

系统通过MCL库中的回调函数,将高层的控制逻辑与底层的PWM驱动无缝结合,实现精确的换相和调速。

  • 换相控制
    MCL库中的控制循环 hpm_mcl_loop 会根据Hall传感器反馈的转子位置,周期性地调用 pwm_enable_channelpwm_disable_channel 回调函数。通过使能或禁用特定相的PWM输出,实现六步换相逻辑,确保电机持续旋转。

  • 占空比调节
    速度环的PI控制器计算出当前需要的输出力矩,并将其转换为PWM占空比。随后,控制循环调用 pwm_duty_set 函数,将此占空比应用到当前导通的PWM通道上。通过调整占空比,可以有效控制施加在电机绕组上的平均电压,从而精确调节电机的转速和力矩。

8. 使用指南

8.1 硬件准备

  1. MCU开发板:支持HPMicro芯片的开发板
  2. BLDC电机:三相无刷直流电机
  3. 位置传感器:Hall传感器或光电编码器
  4. 功率驱动:三相逆变器模块
  5. 电源:24V直流电源

8.2 软件配置

步骤1:参数配置
根据实际电机参数修改以下定义:

#define MOTOR_POLE_NUM              (2)      // 电机极对数
#define PWM_FREQUENCY               (20000)  // PWM频率
#define BOARD_BLDC_BLOCK_SPEED_KP   (0.0005f) // 速度环比例系数
#define BOARD_BLDC_BLOCK_SPEED_KI   (0.000009f) // 速度环积分系数

步骤2:编译下载
使用支持的IDE编译工程并下载到目标板。

步骤3:运行测试
系统启动后会输出:

motor test example
Speed mode, motor run, speed is: 20.000000.
Input speed:

8.3 操作方法

  1. 启动电机:系统默认以20 r/s速度运行
  2. 调速控制:通过串口输入目标速度值
  3. 速度限制
    • 最大速度:±40 r/s
  4. 停止电机:输入速度0或断开电源

9. 调试与优化

9.1 常见问题

问题1:电机不转或抖动

  • 检查Hall传感器接线
  • 确认电机相序正确
  • 验证PWM输出波形

问题2:速度响应慢

  • 调整PI参数
  • 检查控制周期设置
  • 优化滤波器参数

问题3:过流保护触发

  • 检查负载是否过大
  • 确认电流检测电路
  • 调整电流限制参数

9.2 性能优化

参数调优

K_p = \frac{J \cdot \omega_c}{K_t}
K_i = \frac{K_p}{\tau_i}

其中:

  • J 为转动惯量
  • \omega_c 为期望带宽
  • K_t 为转矩常数
  • \tau_i 为积分时间常数

9.3 滤波器设计

IIR滤波器的设计考虑:

  • 通频带:保证速度信号不失真
  • 阻带:抑制高频噪声
  • 相位延迟:最小化控制延迟

10. 移植指南

10.1 硬件移植步骤

当需要将示例移植到不同的电路板时,需要修改以下内容:

步骤1:板级定义文件修改

board.h中定义新的硬件资源:

// PWM相关定义
#define MOTOR0_BLDCPWM              HPM_PWM0    // PWM模块选择
#define BOARD_BLDCPWM_CMP_INDEX_0   (0U)        // 比较器索引
#define BOARD_BLDCPWM_CMP_INDEX_1   (1U)

// PWM输出引脚定义
#define BOARD_BLDC_UH_PWM_OUTPIN    (0U)        // U相上桥臂
#define BOARD_BLDC_UL_PWM_OUTPIN    (1U)        // U相下桥臂
#define BOARD_BLDC_VH_PWM_OUTPIN    (2U)        // V相上桥臂
#define BOARD_BLDC_VL_PWM_OUTPIN    (3U)        // V相下桥臂
#define BOARD_BLDC_WH_PWM_OUTPIN    (4U)        // W相上桥臂
#define BOARD_BLDC_WL_PWM_OUTPIN    (5U)        // W相下桥臂

// Hall传感器相关定义
#define BOARD_BLDC_HALL_BASE        HPM_HALL0   // Hall模块
#define BOARD_BLDC_HALL_IRQ         IRQn_HALL0  // Hall中断号

// QEI编码器相关定义
#define BOARD_BLDC_QEIV2_BASE       HPM_QEI0    // QEI模块
#define BOARD_BLDC_QEIV2_IRQ        IRQn_QEI0   // QEI中断号

// 定时器相关定义
#define BOARD_BLDC_TMR_1MS          HPM_GPTMR0  // 定时器模块
#define BOARD_BLDC_TMR_CH           (0U)        // 定时器通道
#define BOARD_BLDC_TMR_CMP          (0U)        // 比较器
#define BOARD_BLDC_TMR_IRQ          IRQn_GPTMR0 // 定时器中断号
#define BOARD_BLDC_TMR_RELOAD       (1000U)     // 重载值

// 时钟源定义
#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot0  // 电机时钟源
#define BOARD_BLDC_TMR_CLOCK        clock_gptmr0 // 定时器时钟源

步骤2:引脚配置函数

实现对应的引脚初始化函数:

// 在board.c中实现
void init_pwm_pins(PWM_Type *ptr)
{
    // 配置PWM输出引脚
    // 设置引脚复用功能为PWM
    // 配置引脚驱动强度等
}

void init_hall_trgm_pins(void)
{
    // 配置Hall传感器输入引脚
    // 设置引脚复用功能
    // 配置上拉/下拉电阻
}

void init_qeiv2_uvw_pins(QEI_Type *ptr)
{
    // 配置QEI编码器引脚
    // 设置A、B、Z相输入引脚
    // 配置UVW输入引脚
}

10.2 电机参数适配

步骤1:电机物理参数

根据实际电机规格修改以下参数:

void motor_init(void)
{
    // 板级参数配置
    motor0.cfg.mcl.physical.board.num_current_sample_res = 2;        // 电流采样电阻数量
    motor0.cfg.mcl.physical.board.pwm_dead_time_tick = 0;           // PWM死区时间(时钟周期)
    motor0.cfg.mcl.physical.board.pwm_frequency = PWM_FREQUENCY;     // PWM频率
    motor0.cfg.mcl.physical.board.pwm_reload = PWM_RELOAD;          // PWM重载值

    // 电机基本参数
    motor0.cfg.mcl.physical.motor.pole_num = MOTOR_POLE_NUM;        // 极对数
    motor0.cfg.mcl.physical.motor.i_max = 9;                       // 最大电流(A)
    motor0.cfg.mcl.physical.motor.vbus = 24;                       // 母线电压(V)
    motor0.cfg.mcl.physical.motor.rpm_max = 3500;                  // 最大转速(rpm)
    motor0.cfg.mcl.physical.motor.power = 50;                      // 额定功率(W)

    // 电机电气参数
    motor0.cfg.mcl.physical.motor.res = 0.0011;                    // 相电阻(Ω)
    motor0.cfg.mcl.physical.motor.ls = 0.00263;                    // 相电感(H)
    motor0.cfg.mcl.physical.motor.inertia = 0.075;                 // 转动惯量(kg·m²)

    // Hall传感器配置
    motor0.cfg.mcl.physical.motor.hall = phase_120;                // Hall传感器类型(120°或60°)

    // 时间参数配置
    motor0.cfg.mcl.physical.time.encoder_process_ts = MCL_USEC_TO_SEC(TIMER_TS);
    motor0.cfg.mcl.physical.time.speed_loop_ts = MCL_USEC_TO_SEC(TIMER_TS) * 2;
    motor0.cfg.mcl.physical.time.mcu_clock_tick = clock_get_frequency(clock_cpu0);
    motor0.cfg.mcl.physical.time.pwm_clock_tick = clock_get_frequency(BOARD_BLDC_QEI_CLOCK_SOURCE);

    // 编码器参数配置
    motor0.cfg.encoder.communication_interval_us = 0;              // 通信间隔
    motor0.cfg.encoder.disable_start_sample_interrupt = true;      // 禁用采样中断
    motor0.cfg.encoder.period_call_time_s = MCL_USEC_TO_SEC(TIMER_TS);
    motor0.cfg.encoder.precision = 6;                              // 精度
    motor0.cfg.encoder.speed_abs_switch_m_t = 5;                   // 速度切换阈值
    motor0.cfg.encoder.speed_cal_method = encoder_method_m;        // 速度计算方法
    motor0.cfg.encoder.timeout_s = 0.5;                           // 超时时间
}

参数获取方法

  • 极对数:通过电机铭牌或手动转动电机观察Hall信号变化
  • 电阻/电感:使用万用表和LCR表测量
  • 转动惯量:查阅电机规格书或理论计算
  • 额定功率:电机铭牌标注
  • Hall类型:检查Hall传感器安装角度(phase_120或phase_60)

步骤2:宏定义参数调整

// 根据实际电机调整宏定义
#define MOTOR_POLE_NUM              (2)      // 电机极对数
#define PWM_FREQUENCY               (20000)  // PWM频率(根据开关器件选择)
#define BOARD_BLDC_BLOCK_SPEED_KP   (0.0005f) // 速度环比例系数
#define BOARD_BLDC_BLOCK_SPEED_KI   (0.000009f) // 速度环积分系数

// PWM重载值计算
#define PWM_RELOAD                  ((motor_clock_hz/PWM_FREQUENCY) - 1)

// Hall传感器角度偏移(根据安装方向调整)
#if defined(BOARD_BLDC_HALL_DIR_INV) && BOARD_BLDC_HALL_DIR_INV
#define MOTOR_ANGLE_DETA    -MCL_PI_DIV3 / MOTOR_POLE_NUM  // 反向安装
#else
#define MOTOR_ANGLE_DETA    MCL_PI_DIV3 / MOTOR_POLE_NUM   // 正向安装
#endif

10.3 位置传感器适配

Hall传感器适配

// 根据Hall传感器安装位置调整角度偏移
#if defined(BOARD_BLDC_HALL_DIR_INV) && BOARD_BLDC_HALL_DIR_INV
#define MOTOR_ANGLE_DETA    -MCL_PI_DIV3 / MOTOR_POLE_NUM  // 反向安装
#else
#define MOTOR_ANGLE_DETA    MCL_PI_DIV3 / MOTOR_POLE_NUM   // 正向安装
#endif

// Hall传感器状态映射表(如果需要调整)
hpm_mcl_stat_t encoder_get_uvw_level(mcl_encoder_uvw_level_t *level)
{
    uint8_t hall_stat;
    hall_stat = hall_get_current_uvw_stat(BOARD_BLDC_HALL_BASE);

    // 根据实际接线调整状态映射
    level->w = ((hall_stat >> 0) & 0x01);  // W相Hall
    level->v = ((hall_stat >> 1) & 0x01);  // V相Hall  
    level->u = ((hall_stat >> 2) & 0x01);  // U相Hall

    return mcl_success;
}

QEI编码器适配

// 编码器分辨率配置
#define ENCODER_LINES_PER_REV       (1000)      // 编码器线数
#define QEIV2_ANGLE_PRE            (ENCODER_LINES_PER_REV * 4)  // 4倍频

// 位置到UVW状态的映射
hpm_mcl_stat_t encoder_get_uvw_level(mcl_encoder_uvw_level_t *level)
{
    uint32_t pos;
    const uint8_t level_tbl[6] = {5, 4, 6, 2, 3, 1};  // 可能需要调整

    pos = qeiv2_get_postion(BOARD_QEI_BASE);
    pos /= QEIV2_ANGLE_PRE;
    pos = (pos) / 2;

    level->w = ((level_tbl[pos] >> 0) & 0x01);
    level->v = ((level_tbl[pos] >> 1) & 0x01);
    level->u = ((level_tbl[pos] >> 2) & 0x01);

    return mcl_success;
}

10.4 控制参数调优

PID参数初始设置

// 基于电机参数的初始PID设置
float motor_inertia = motor0.cfg.mcl.physical.motor.inertia;
float motor_kt = 0.1f;  // 转矩常数,需要根据实际电机确定

// 带宽设置(一般为10-100 Hz)
float desired_bandwidth = 20.0f * 2 * MCL_PI;  // 20Hz

// 初始PID参数计算
float initial_kp = motor_inertia * desired_bandwidth / motor_kt;
float initial_ki = initial_kp / 0.1f;  // 积分时间常数设为100ms

// 应用到配置
motor0.cfg.control.speed_pid_cfg.cfg.kp = initial_kp;
motor0.cfg.control.speed_pid_cfg.cfg.ki = initial_ki;

滤波器参数调整

// 根据控制频率调整滤波器参数
// 通带频率一般设为控制带宽的2-5倍
// 阻带频率设为PWM频率的1/10左右

float pass_freq = desired_bandwidth * 3 / (2 * MCL_PI);    // 通带频率
float stop_freq = PWM_FREQUENCY / 10;                      // 阻带频率

// 重新设计滤波器系数(需要使用滤波器设计工具)
// 这里仅显示如何修改现有系数
motor0.cfg.encoder_iir_mat[0].a1 = new_a1_coeff;
motor0.cfg.encoder_iir_mat[0].a2 = new_a2_coeff;
motor0.cfg.encoder_iir_mat[0].b0 = new_b0_coeff;
// ... 其他系数

10.5 功率电路适配

PWM输出配置调整

根据功率驱动电路的要求,可能需要调整以下PWM配置参数:

对于PWM模块

void pwm_init(void)
{
    // ... 其他配置保持不变 ...

    // 可调整的参数
    pwm_config.enable_output = true;              // 使能PWM输出
    pwm_config.dead_zone_in_half_cycle = 100;     // 死区时间(根据驱动IC要求调整)
    pwm_config.invert_output = false;             // 输出反相(根据电路需要)

    // ... 其他配置保持不变 ...
}

对于PWMV2模块

void pwm_init(void)
{
    // ... 其他配置保持不变 ...

    // 可调整的参数
    pwm_cfg.enable_output = true;                 // 使能PWM输出
    pwm_cfg.enable_async_fault = false;           // 异步故障检测
    pwm_cfg.enable_sync_fault = false;            // 同步故障检测
    pwm_cfg.invert_output = false;                // 输出反相(根据电路需要)
    pwm_cfg.enable_four_cmp = false;              // 四比较器模式

    // ... 其他配置保持不变 ...
}

常见适配场景

  1. 死区时间调整(仅PWM模块):

    // 根据功率器件和驱动IC的要求调整死区时间
    pwm_config.dead_zone_in_half_cycle = YOUR_DEAD_TIME;  // 例如:50, 100, 200等
  2. PWM输出反相

    // 如果功率电路需要反相信号
    pwm_config.invert_output = true;   // PWM模块
    // 或
    pwm_cfg.invert_output = true;      // PWMV2模块
  3. 故障保护使能(仅PWMV2模块):

    // 如果硬件支持故障检测信号
    pwm_cfg.enable_async_fault = true;   // 使能异步故障保护
    pwm_cfg.enable_sync_fault = true;    // 使能同步故障保护

注意事项

  • 大部分PWM配置参数在MCL库中是固定的,不建议随意修改
  • 主要可调整的参数是死区时间和输出反相
  • 如果需要修改PWM频率,应该通过修改PWM_FREQUENCY宏定义实现
  • 故障保护功能需要硬件电路支持相应的故障检测信号

10.6 移植验证步骤

步骤1:硬件连接验证

// 验证PWM输出功能
void test_pwm_output(void)
{
    // 测试单个通道PWM输出(50%占空比)
    pwm_duty_set(mcl_drivers_chn_ah, 0.5f);
    printf("Testing PWM output with 50%% duty cycle\n");
    // 使用示波器检查对应引脚的PWM波形
}

// 验证位置传感器功能
void test_position_sensor(void)
{
    mcl_encoder_uvw_level_t level;
    encoder_get_uvw_level(&level);
    printf("Hall状态: U=%d, V=%d, W=%d\n", level.u, level.v, level.w);

    // 手动转动电机,观察Hall状态变化
    // 正常情况下应该看到6个不同的状态值
}

// 验证系统时钟配置
void test_system_clock(void)
{
    uint32_t cpu_freq = clock_get_frequency(clock_cpu0);
    uint32_t motor_freq = clock_get_frequency(BOARD_BLDC_QEI_CLOCK_SOURCE);

    printf("CPU频率: %d Hz\n", cpu_freq);
    printf("电机时钟频率: %d Hz\n", motor_freq);
    printf("期望PWM频率: %d Hz\n", PWM_FREQUENCY);
    printf("实际PWM重载值: %d\n", PWM_RELOAD);
}

步骤2:MCL库初始化验证

// 验证MCL库各模块初始化
void test_mcl_init(void)
{
    // 测试各个模块的初始化状态
    printf("开始MCL库初始化测试...\n");

    // 初始化各个模块(按实际初始化顺序)
    hpm_mcl_filter_iir_df1_init(&motor0.encoder_iir, &motor0.cfg.encoder_iir, &motor0.encoder_iir_mem[0]);
    printf("IIR滤波器初始化完成\n");

    hpm_mcl_encoder_init(&motor0.encoder, &motor0.cfg.mcl, &motor0.cfg.encoder, &motor0.encoder_iir);
    printf("编码器模块初始化完成\n");

    hpm_mcl_drivers_init(&motor0.drivers, &motor0.cfg.drivers);
    printf("驱动模块初始化完成\n");

    hpm_mcl_control_init(&motor0.control, &motor0.cfg.control);
    printf("控制模块初始化完成\n");

    hpm_mcl_loop_init(&motor0.loop, &motor0.cfg.loop, &motor0.cfg.mcl,
                    &motor0.encoder, &motor0.analog, &motor0.control, &motor0.drivers, NULL);
    printf("控制环初始化完成\n");

    hpm_mcl_detect_init(&motor0.detect, &motor0.cfg.detect, &motor0.loop, &motor0.encoder, &motor0.analog, &motor0.drivers);
    printf("检测模块初始化完成\n");
}

步骤3:开环测试

// 开环PWM输出测试
void test_open_loop(void)
{
    printf("开始开环测试...\n");

    // 禁用速度环控制
    motor0.cfg.loop.enable_speed_loop = false;

    // 重新初始化控制环
    hpm_mcl_loop_init(&motor0.loop, &motor0.cfg.loop, &motor0.cfg.mcl,
                    &motor0.encoder, &motor0.analog, &motor0.control, &motor0.drivers, NULL);

    // 启动块换相模式
    hpm_mcl_loop_start_block(&motor0.loop);
    hpm_mcl_loop_enable(&motor0.loop);

    printf("请手动转动电机观察是否能正常换相\n");
    printf("按任意键继续到闭环测试...\n");
    getchar();
}

步骤4:闭环调试

// 闭环控制测试
void test_closed_loop(void)
{
    printf("开始闭环测试...\n");

    // 启用速度环控制
    motor0.cfg.loop.enable_speed_loop = true;

    // 重新初始化控制环
    hpm_mcl_loop_init(&motor0.loop, &motor0.cfg.loop, &motor0.cfg.mcl,
                    &motor0.encoder, &motor0.analog, &motor0.control, &motor0.drivers, NULL);

    // 启动控制
    hpm_mcl_loop_start_block(&motor0.loop);
    hpm_mcl_loop_enable(&motor0.loop);

    // 从低速开始测试
    float test_speeds[] = {5.0f, 10.0f, 15.0f, 20.0f};
    mcl_user_value_t user_speed;
    user_speed.enable = true;

    for(int i = 0; i < 4; i++) {
        user_speed.value = test_speeds[i] * MCL_2PI * MOTOR_POLE_NUM;
        hpm_mcl_loop_set_speed(&motor0.loop, user_speed);

        printf("设置速度: %.1f r/s\n", test_speeds[i]);
        printf("等待5秒观察电机响应...\n");

        // 延时5秒观察响应
        for(int j = 0; j < 5000; j++) {
            board_delay_ms(1);
        }

        printf("当前测试完成,按任意键继续下一个速度测试...\n");
        getchar();
    }

    // 停止电机
    user_speed.value = 0;
    hpm_mcl_loop_set_speed(&motor0.loop, user_speed);
    printf("测试完成,电机已停止\n");
}

步骤5:完整系统验证

// 在main函数中添加验证流程
int main(void)
{
    board_init();
    motor_clock_hz = clock_get_frequency(BOARD_BLDC_QEI_CLOCK_SOURCE);
    init_pwm_pins(MOTOR0_BLDCPWM);

    printf("=== BLDC控制系统验证开始 ===\n");

    // 步骤1:硬件验证
    test_system_clock();
    test_position_sensor();
    test_pwm_output();

    // 步骤2:软件初始化验证
    motor_init();
    pwm_init();
    timer_init();
    test_mcl_init();

    // 步骤3:开环测试
    test_open_loop();

    // 步骤4:闭环测试
    test_closed_loop();

    printf("=== 验证完成,进入正常运行模式 ===\n");

    // 正常运行代码...
    return 0;
}

11. 安全注意事项

  1. 电气安全

    • 确保接地良好
    • 避免带电操作
  2. 机械安全

    • 安装安全防护装置
    • 避免超速运行
  3. 软件安全

    • 实现故障检测机制
    • 设置合理的保护限值

12. 总结

BLDC块换相控制是电机控制的基础技术,具有实现简单、成本低廉的优点。通过HPMicro MCL库的支持,开发者可以快速搭建可靠的BLDC控制系统。

本文介绍的示例代码提供了完整的控制框架,包括:

  • 多种位置检测方式支持
  • 灵活的PWM驱动配置
  • 易于扩展的软件架构

在实际应用中,开发者可以根据具体需求对参数进行调整和优化,以获得最佳的控制性能。通过本文提供的移植指南,可以将示例快速适配到不同的硬件平台和电机系统。

0
0

订阅

发表回复 0

Your email address will not be published. Required fields are marked *