目录
一、核心原理:无传感器 BLDC 与反电动势检测
1. BLDC 无传感器控制的核心逻辑
2. 反电动势获取方式
3. 关键滤波需求
二、反电动势常用滤波方法(硬件 + 软件)
1. 硬件滤波(前置处理)
2. 软件滤波(核心算法)
三、完整控制流程(无传感器 BLDC + 反电动势滤波)
关键步骤说明:
四、代码实现(基于 STM32F103,轻量化方案)
1. 核心宏定义与变量
2. 一阶低通滤波函数
3. 反电动势采集与滤波(ADC 中断回调)
4. 过零点检测与换相控制
5. 电机启动与主循环
五、关键注意事项
总结
要实现基于反电动势(Back EMF)滤波的无传感器无刷直流电机(BLDC)控制,核心是通过处理反电动势信号(替代位置传感器),结合滤波算法消除噪声干扰,精准识别转子位置,进而实现电机的换相和调速控制。以下从原理、滤波方法、控制流程到代码实现,完整讲解这一方案。
一、核心原理:无传感器 BLDC 与反电动势检测
1. BLDC 无传感器控制的核心逻辑
BLDC 电机的转子位置是换相的关键,无传感器方案中,反电动势是最常用的位置反馈依据:
- BLDC 定子绕组导通两相时,第三相悬空(未通电),转子旋转会在该相绕组中感应出反电动势;
- 反电动势的过零点(相对于电机中性点电压)与转子磁极位置严格对应,过零点后延迟 30° 电角度就是换相时机;
- 反电动势信号包含大量噪声(功率管开关噪声、母线纹波、电磁干扰等),必须通过滤波处理才能准确检测过零点。
2. 反电动势获取方式
- 虚拟中性点法:无需硬件中性点,通过三相母线电压分压(如电阻分压)生成虚拟中性点电压,将悬空相的反电动势与虚拟中性点对比;
- 端电压检测法:直接采集电机绕组端电压,扣除母线电压和导通压降后计算反电动势。
3. 关键滤波需求
滤波需平衡两个目标:
- 噪声抑制:消除高频开关噪声和电磁干扰;
- 响应速度:不能过度滤波导致过零点检测延迟,影响换相精度。
二、反电动势常用滤波方法(硬件 + 软件)
1. 硬件滤波(前置处理)
先通过硬件滤除大部分高频噪声,降低软件处理压力:
- RC 低通滤波:在反电动势采集引脚串联电阻(1k~10kΩ)+ 并联电容(0.1μF~1μF),截止频率设为 10kHz~50kHz(避开 PWM 开关频率,且高于电机电气频率);
- TVS 管 / 钳位电路:抑制尖峰电压,保护 MCU 的 ADC 引脚。
2. 软件滤波(核心算法)
硬件滤波后仍有残留噪声,需软件进一步处理,以下是适合 BLDC 反电动势的轻量化算法(适配 MCU 资源):
| 滤波算法 | 原理 | 优势 | 适用场景 |
|---|---|---|---|
| 滑动平均滤波 | 取最近 N 个采样值的平均值作为当前值 | 简单、轻量化、抗随机噪声 | 低速 / 中速 BLDC 控制 |
| 一阶低通数字滤波 | Y(n) = α*X(n) + (1-α)*Y(n-1)(α 为滤波系数,0<α<1) | 响应快、参数可调 | 全转速范围 |
| 中值滤波 | 取最近 N 个采样值的中值,剔除异常尖峰 | 抗脉冲干扰 | 电磁干扰严重的场景 |
重点推荐:一阶低通数字滤波(兼顾性能和效率),α 取值建议:
- 低速(<1000rpm):α=0.2~0.4(更强滤波);
- 高速(>3000rpm):α=0.5~0.8(更快响应)。
三、完整控制流程(无传感器 BLDC + 反电动势滤波)
graph TD A[电机启动:开环V/F控制] --> B[达到阈值转速,切换到反电动势检测] B --> C[ADC采集悬空相反电动势+虚拟中性点电压] C --> D[软件滤波处理反电动势信号] D --> E[检测反电动势过零点] E --> F[延迟30°电角度,触发换相] F --> G[PWM驱动功率管换相] G --> H[调速闭环(PI调节PWM占空比)] H --> C[循环采集与换相]关键步骤说明:
- 开环启动:无传感器 BLDC 无法直接从静止检测反电动势,需先通过开环 V/F 控制(逐步提升频率和电压)让电机达到约 10% 额定转速;
- 过零点检测:滤波后的反电动势与虚拟中性点电压对比,当信号从负变正(或正变负)时,判定为过零点;
- 换相延迟:过零点后需延迟 30° 电角度再换相(通过定时器计数实现),确保转矩最大化;
- 闭环调速:通过霍尔传感器(若有)或反电动势频率计算转速,结合 PI 算法调节 PWM 占空比,稳定转速。
四、代码实现(基于 STM32F103,轻量化方案)
以下是核心代码片段,包含反电动势采集、滤波、过零点检测和换相控制,适配 3 相 6 步 BLDC 控制。
1. 核心宏定义与变量
#include "stm32f10x.h" // 反电动势滤波参数 #define ALPHA 0.6f // 一阶低通滤波系数 #define SAMPLE_NUM 8 // 滑动平均滤波采样数 #define NEUTRAL_VOLT 1.65f // 虚拟中性点电压(3.3V电源分压后) // 电机换相表(6步换相,对应U/V/W三相的上下桥臂) const uint8_t commutation_table[6][6] = { {1,0,0,0,1,0}, // 换相步0:U+ V- {1,0,0,0,0,1}, // 换相步1:U+ W- {0,1,0,0,0,1}, // 换相步2:V+ W- {0,1,0,1,0,0}, // 换相步3:V+ U- {0,0,1,1,0,0}, // 换相步4:W+ U- {0,0,1,0,1,0} // 换相步5:W+ V- }; // 全局变量 float b_emf_u = 0.0f, b_emf_v = 0.0f, b_emf_w = 0.0f; // 滤波后反电动势 float raw_b_emf_u = 0.0f, raw_b_emf_v = 0.0f, raw_b_emf_w = 0.0f; // 原始采样值 uint8_t comm_step = 0; // 当前换相步数 uint8_t zero_cross_flag = 0; // 过零点标志2. 一阶低通滤波函数
/** * @brief 一阶低通数字滤波 * @param raw_val: 原始采样值 * @param filtered_val: 上一次滤波后的值 * @retval 当前滤波后的值 */ float first_order_lowpass_filter(float raw_val, float filtered_val) { return ALPHA * raw_val + (1 - ALPHA) * filtered_val; }3. 反电动势采集与滤波(ADC 中断回调)
/** * @brief ADC采样完成回调函数(每100μs采样一次) */ void ADC_ConvCpltCallback(void) { // 读取三相反电动势原始采样值(ADC值转换为电压,3.3V参考,12位ADC) raw_b_emf_u = (float)ADC_GetConversionValue(ADC1) * 3.3f / 4096.0f; raw_b_emf_v = (float)ADC_GetConversionValue(ADC2) * 3.3f / 4096.0f; raw_b_emf_w = (float)ADC_GetConversionValue(ADC3) * 3.3f / 4096.0f; // 对悬空相的反电动势进行滤波(仅滤波当前未导通的相) switch(comm_step) { case 0: // U+ V-,W相悬空 b_emf_w = first_order_lowpass_filter(raw_b_emf_w, b_emf_w); break; case 1: // U+ W-,V相悬空 b_emf_v = first_order_lowpass_filter(raw_b_emf_v, b_emf_v); break; case 2: // V+ W-,U相悬空 b_emf_u = first_order_lowpass_filter(raw_b_emf_u, b_emf_u); break; case 3: // V+ U-,W相悬空 b_emf_w = first_order_lowpass_filter(raw_b_emf_w, b_emf_w); break; case 4: // W+ U-,V相悬空 b_emf_v = first_order_lowpass_filter(raw_b_emf_v, b_emf_v); break; case 5: // W+ V-,U相悬空 b_emf_u = first_order_lowpass_filter(raw_b_emf_u, b_emf_u); break; default: break; } }4. 过零点检测与换相控制
/** * @brief 反电动势过零点检测 */ void b_emf_zero_cross_detect(void) { float悬空相_bemf = 0.0f; // 获取当前悬空相的滤波后反电动势 switch(comm_step) { case 0: 悬空相_bemf = b_emf_w; break; case 1: 悬空相_bemf = b_emf_v; break; case 2: 悬空相_bemf = b_emf_u; break; case 3: 悬空相_bemf = b_emf_w; break; case 4: 悬空相_bemf = b_emf_v; break; case 5: 悬空相_bemf = b_emf_u; break; } // 检测过零点:反电动势从低于中性点变为高于中性点(上升沿过零) static uint8_t last_state = 0; // 0: 低于中性点,1: 高于中性点 uint8_t curr_state = (悬空相_bemf > NEUTRAL_VOLT) ? 1 : 0; if((last_state == 0) && (curr_state == 1)) { zero_cross_flag = 1; // 检测到过零点 last_state = curr_state; } else { last_state = curr_state; } } /** * @brief 电机换相控制(定时器中断,处理过零点延迟) */ void TIM_Commutation_IRQHandler(void) { if(zero_cross_flag == 1) { // 延迟30°电角度后换相(通过定时器计数实现,需根据转速计算延迟时间) comm_step = (comm_step + 1) % 6; // 执行换相:根据换相表控制功率管的通断 set_power_switch(commutation_table[comm_step]); zero_cross_flag = 0; // 清除过零点标志 } }5. 电机启动与主循环
int main(void) { // 初始化:GPIO(PWM/功率管)、ADC(反电动势采集)、定时器(换相/调速) System_Init(); // 开环启动:逐步提升PWM频率和占空比,让电机达到检测转速 open_loop_start(); // 主循环 while(1) { // 检测反电动势过零点 b_emf_zero_cross_detect(); // 转速闭环调节(PI算法调节PWM占空比) speed_pi_control(); } }五、关键注意事项
- 滤波系数调试:α 值需根据电机转速和噪声情况调整,低速时增大滤波强度(减小 α),高速时降低滤波强度(增大 α);
- 虚拟中性点校准:实际硬件中,分压电阻的误差会导致虚拟中性点电压偏离理论值,需通过校准确保过零点检测准确;
- 死区时间设置:功率管换相时需设置死区时间(1~5μs),避免上下桥臂直通烧毁器件;
- 启动优化:开环启动的加速斜率需匹配电机特性,斜率过大会导致启动失败,过小会增加启动时间。
总结
基于反电动势滤波的无传感器 BLDC 控制核心要点:
- 反电动势过零点是转子位置的核心依据,滤波是确保过零点检测准确的关键;
- 一阶低通数字滤波是兼顾性能和资源的最优选择,滤波系数需按转速动态调整;
- 控制流程需分阶段:开环启动→反电动势检测 + 滤波→过零点判断→换相 + 闭环调速,缺一不可。
该方案无需位置传感器,降低了硬件成本和布线复杂度,适用于风扇、水泵、无人机等对成本敏感且无高精度位置要求的 BLDC 应用场景。