从示波器波形到单片机代码:一次搞定霍尔电机信号里的‘杂波’滤波与速度计算 从示波器波形到单片机代码一次搞定霍尔电机信号里的‘杂波’滤波与速度计算当你在调试一个不知名的霍尔电机时示波器上那些看似规律的方波中隐藏着令人头疼的高频杂波。这些15.3kHz的干扰信号会让你的转速计算偏离实际值数千倍。本文将带你完整经历一次从波形异常发现、问题分析到最终解决方案落地的工程实践。1. 霍尔电机信号基础与异常发现霍尔电机通过内置的霍尔传感器输出方波信号通常每个磁极会对应一个完整的方波周期。在理想情况下这些信号应该是干净整齐的方波但实际上我们常常会遇到各种干扰。使用示波器观察信号时我发现基础信号频率约85Hz对应电机转速5100r/min叠加的高频噪声15.3kHz的周期性干扰干扰幅度达到基础信号幅度的30%关键测量数据对比表测量方式测得频率换算转速(r/min)实际转速(r/min)转速表-51005100原始信号85Hz51005100干扰信号15.3kHz918,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)基本消除信号幅度5V4.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避免每次上电重新校准