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传感器状态发生变化时,系统会:
- 清除中断状态
- 计算当前转子角度
- 刷新控制循环
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周期)执行:
- 故障检测
- 编码器数据处理
- 主控制循环
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_channel
和pwm_disable_channel
回调函数。通过使能或禁用特定相的PWM输出,实现六步换相逻辑,确保电机持续旋转。 -
占空比调节:
速度环的PI控制器计算出当前需要的输出力矩,并将其转换为PWM占空比。随后,控制循环调用pwm_duty_set
函数,将此占空比应用到当前导通的PWM通道上。通过调整占空比,可以有效控制施加在电机绕组上的平均电压,从而精确调节电机的转速和力矩。
8. 使用指南
8.1 硬件准备
- MCU开发板:支持HPMicro芯片的开发板
- BLDC电机:三相无刷直流电机
- 位置传感器:Hall传感器或光电编码器
- 功率驱动:三相逆变器模块
- 电源: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 操作方法
- 启动电机:系统默认以20 r/s速度运行
- 调速控制:通过串口输入目标速度值
- 速度限制:
- 最大速度:±40 r/s
- 停止电机:输入速度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; // 四比较器模式
// ... 其他配置保持不变 ...
}
常见适配场景:
-
死区时间调整(仅PWM模块):
// 根据功率器件和驱动IC的要求调整死区时间 pwm_config.dead_zone_in_half_cycle = YOUR_DEAD_TIME; // 例如:50, 100, 200等
-
PWM输出反相:
// 如果功率电路需要反相信号 pwm_config.invert_output = true; // PWM模块 // 或 pwm_cfg.invert_output = true; // PWMV2模块
-
故障保护使能(仅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. 安全注意事项
-
电气安全
- 确保接地良好
- 避免带电操作
-
机械安全
- 安装安全防护装置
- 避免超速运行
-
软件安全
- 实现故障检测机制
- 设置合理的保护限值
12. 总结
BLDC块换相控制是电机控制的基础技术,具有实现简单、成本低廉的优点。通过HPMicro MCL库的支持,开发者可以快速搭建可靠的BLDC控制系统。
本文介绍的示例代码提供了完整的控制框架,包括:
- 多种位置检测方式支持
- 灵活的PWM驱动配置
- 易于扩展的软件架构
在实际应用中,开发者可以根据具体需求对参数进行调整和优化,以获得最佳的控制性能。通过本文提供的移植指南,可以将示例快速适配到不同的硬件平台和电机系统。