从示波器波形到单片机代码:一次搞定霍尔电机信号里的‘杂波’滤波与速度计算
从示波器波形到单片机代码:一次搞定霍尔电机信号里的‘杂波’滤波与速度计算
当你在调试一个不知名的霍尔电机时,示波器上那些看似规律的方波中隐藏着令人头疼的高频杂波。这些15.3kHz的干扰信号会让你的转速计算偏离实际值数千倍。本文将带你完整经历一次从波形异常发现、问题分析到最终解决方案落地的工程实践。
1. 霍尔电机信号基础与异常发现
霍尔电机通过内置的霍尔传感器输出方波信号,通常每个磁极会对应一个完整的方波周期。在理想情况下,这些信号应该是干净整齐的方波,但实际上我们常常会遇到各种干扰。
使用示波器观察信号时,我发现:
- 基础信号频率:约85Hz(对应电机转速5100r/min)
- 叠加的高频噪声:15.3kHz的周期性干扰
- 干扰幅度:达到基础信号幅度的30%
关键测量数据对比表:
| 测量方式 | 测得频率 | 换算转速(r/min) | 实际转速(r/min) |
|---|---|---|---|
| 转速表 | - | 5100 | 5100 |
| 原始信号 | 85Hz | 5100 | 5100 |
| 干扰信号 | 15.3kHz | 918,000 | 不适用 |
注意:干扰信号的频率换算转速明显不合理,表明这是需要滤除的噪声
2. 杂波分析与滤波器设计
高频干扰的来源可能是电机驱动电路的开关噪声、电源纹波或电磁辐射。针对15.3kHz的干扰,我们需要设计一个低通滤波器,保留有用的转速信号(<1kHz),滤除高频噪声。
2.1 滤波器类型选择
考虑两种常见方案:
- RC低通滤波器:
- 优点:简单、成本低
- 缺点:对陡峭截止需求响应一般
- LC低通滤波器:
- 优点:截止特性更陡峭
- 缺点:体积大、成本高
基于本应用的需求,选择RC滤波器完全足够。
2.2 RC参数计算
截止频率公式:
f_c = 1 / (2πRC)设计目标:
- 保留信号:<1kHz
- 滤除信号:>10kHz
- 选择截止频率:2kHz(兼顾保留有用信号和滤除干扰)
常用电阻值选择360Ω,计算所需电容:
C = 1 / (2π × 360 × 2000) ≈ 220nF实际选用:
- 电阻:360Ω
- 电容:220nF(标称值最接近计算值)
3. 硬件滤波实现与验证
将设计的RC滤波器接入信号线路后,重新用示波器观察波形变化:
滤波前后波形对比:
| 特性 | 滤波前 | 滤波后 |
|---|---|---|
| 上升时间 | <100ns | ~2μs |
| 高频噪声 | 明显(15.3kHz) | 基本消除 |
| 信号幅度 | 5V | 4.8V(轻微衰减) |
| 波形完整性 | 方波有毛刺 | 较干净的正弦化边缘 |
虽然滤波后的上升沿变得稍缓,但对转速测量应用完全可接受。关键是没有了高频干扰,转速计算将更准确。
4. 单片机测速算法实现
4.1 测量原理
霍尔电机通常有多个极对,每个极对会产生两个边沿(上升沿和下降沿)。假设电机有3个极对,则:
- 每转产生6个边沿
- 测量两个边沿的时间间隔×3=每转时间
4.2 代码实现关键
使用STM32的定时器捕获功能实现:
// 定时器捕获初始化 void TIM1_Capture_Init(uint16_t prescaler, uint16_t reload) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; // 时基配置 TIM_TimeBaseStructure.TIM_Period = reload - 1; TIM_TimeBaseStructure.TIM_Prescaler = prescaler - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // 输入捕获配置 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x01; // 轻微滤波 TIM_ICInit(TIM1, &TIM_ICInitStructure); // 启用中断 TIM_ITConfig(TIM1, TIM_IT_CC2 | TIM_IT_Update, ENABLE); TIM_Cmd(TIM1, ENABLE); }4.3 转速计算
在捕获中断中计算转速:
void TIM1_CC_IRQHandler(void) { static uint32_t last_capture = 0; uint32_t current_capture; if (TIM_GetITStatus(TIM1, TIM_IT_CC2) != RESET) { current_capture = TIM_GetCapture2(TIM1); // 计算周期(考虑定时器溢出) uint32_t period = (current_capture > last_capture) ? (current_capture - last_capture) : (0xFFFF - last_capture + current_capture); // 保存当前值供下次使用 last_capture = current_capture; // 计算转速(r/min) // 假设3个极对,每个极对2个边沿,所以乘以6 float rpm = (60.0f * SystemCoreClock) / (period * prescaler * 6); // 更新全局转速变量 motor_rpm = (uint32_t)rpm; TIM_ClearITPendingBit(TIM1, TIM_IT_CC2); } }5. 转向判断实现
霍尔电机的转向可以通过多个霍尔信号的相位关系判断。典型的三相霍尔信号在正反转时会有不同的边沿顺序:
正转序列:
- 霍尔A上升沿
- 霍尔B上升沿
- 霍尔C上升沿
反转序列:
- 霍尔A上升沿
- 霍尔C上升沿
- 霍尔B上升沿
实现代码片段:
void EXTI_IRQHandler(void) { static uint8_t last_state = 0; uint8_t current_state = (HALL_A_PIN << 2) | (HALL_B_PIN << 1) | HALL_C_PIN; if (current_state != last_state) { // 判断转向逻辑 if ((last_state == 0b100 && current_state == 0b110) || (last_state == 0b110 && current_state == 0b010) || (last_state == 0b010 && current_state == 0b011) || (last_state == 0b011 && current_state == 0b001) || (last_state == 0b001 && current_state == 0b101) || (last_state == 0b101 && current_state == 0b100)) { motor_direction = FORWARD; } else if (...) { // 反向判断逻辑 motor_direction = REVERSE; } last_state = current_state; } EXTI_ClearITPendingBit(HALL_A_EXTI_LINE | HALL_B_EXTI_LINE | HALL_C_EXTI_LINE); }6. 系统优化与误差处理
在实际应用中,还需要考虑以下优化:
软件滤波:对连续几次测量结果进行中值滤波
#define MEDIAN_FILTER_SIZE 5 uint32_t speed_buffer[MEDIAN_FILTER_SIZE]; uint32_t median_filter(uint32_t new_value) { static uint8_t index = 0; uint32_t temp_buffer[MEDIAN_FILTER_SIZE]; // 更新缓冲区 speed_buffer[index++] = new_value; if (index >= MEDIAN_FILTER_SIZE) index = 0; // 复制并排序 memcpy(temp_buffer, speed_buffer, sizeof(speed_buffer)); bubble_sort(temp_buffer, MEDIAN_FILTER_SIZE); return temp_buffer[MEDIAN_FILTER_SIZE/2]; }异常处理:检测信号丢失或异常
- 设置超时机制,长时间无信号变化视为停止
- 检测信号占空比异常(如持续高/低电平)
校准功能:
- 通过已知转速校准极对数参数
- 存储校准值到Flash,避免每次上电重新校准
