用STM32F103和MH-Sensor红外模块DIY一个简易测速仪(附完整代码)
用STM32F103和MH-Sensor红外模块DIY高精度测速仪附完整工程代码最近在调试一个小车项目时发现市面上成品测速模块要么价格昂贵要么精度不足。翻出抽屉里的STM32F103C8T6最小系统和几块钱的MH-Sensor系列红外对管决定自己动手做个轻量级测速方案。这个方案特别适合需要测量电机转速、车轮转速等场景成本不到20元精度却能达到工业级水准。1. 硬件选型与电路设计1.1 核心器件选型要点STM32F103C8T6作为主控的优势在于72MHz主频处理测速信号游刃有余丰富的外设资源定时器、外部中断等市面上开发板价格普遍低于20元MH-Sensor系列红外对射模块的实测表现有效检测距离3-15mm可调通过电位器响应时间≤0.1ms工作电压3.3V-5V兼容输出信号干净无需额外滤波电路1.2 码盘设计与安装技巧推荐使用20孔光栅码盘其优势在于孔距均匀便于计算转速孔径与MH-Sensor光束直径匹配良好市售价格约5元/片安装时的黄金法则码盘与转轴必须同心固定传感器与码盘间距控制在5mm内确保码盘转动平面与传感器发射面平行1.3 完整电路连接图------------------- ----------------- | STM32F103C8T6 | | MH-Sensor | | | | | | 3.3V ---------------- VCC | | GND ---------------- GND | | PB14 ---------------- DO | ------------------- -----------------注意实际接线时建议使用杜邦线热熔胶固定避免振动导致接触不良2. 软件架构设计与关键代码2.1 工程文件结构├── Core │ ├── Inc │ │ ├── countsensor.h │ │ └── timer.h │ └── Src │ ├── countsensor.c │ └── timer.c ├── Drivers └── main.c2.2 外部中断配置CountSensor.cvoid CountSensor_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; EXTI_InitTypeDef EXTI_InitStruct {0}; NVIC_InitTypeDef NVIC_InitStruct {0}; // 时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); // GPIO配置 GPIO_InitStruct.GPIO_Pin GPIO_Pin_14; GPIO_InitStruct.GPIO_Mode GPIO_Mode_IPU; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStruct); // 外部中断配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); EXTI_InitStruct.EXTI_Line EXTI_Line14; EXTI_InitStruct.EXTI_Mode EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger EXTI_Trigger_Falling; EXTI_InitStruct.EXTI_LineCmd ENABLE; EXTI_Init(EXTI_InitStruct); // NVIC配置 NVIC_InitStruct.NVIC_IRQChannel EXTI15_10_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 0x01; NVIC_InitStruct.NVIC_IRQChannelSubPriority 0x01; NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStruct); }2.3 定时器配置Timer.cvoid Timer_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct {0}; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseInitStruct.TIM_Period 1000 - 1; // 1kHz中断频率 TIM_TimeBaseInitStruct.TIM_Prescaler 72 - 1; // 72MHz/72 1MHz TIM_TimeBaseInitStruct.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseInitStruct); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); TIM_Cmd(TIM3, ENABLE); NVIC_EnableIRQ(TIM3_IRQn); }3. 转速计算算法优化3.1 基本计算公式转速(RPM) (脉冲数 × 60) / (码盘孔数 × 采样时间(s))例如1秒内检测到400个脉冲20孔码盘转速 (400×60)/20 1200 RPM3.2 防抖动处理技巧在中断服务函数中添加二次验证void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line14) ! RESET) { if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) 0) { pulseCount; } EXTI_ClearITPendingBit(EXTI_Line14); } }3.3 动态采样周期算法根据转速自动调整采样间隔转速范围(RPM)采样周期(ms)理论误差5001000±0.5%500-2000500±1%2000200±2%实现代码片段void TIM3_IRQHandler(void) { static uint32_t lastCount 0; if(TIM_GetITStatus(TIM3, TIM_IT_Update) ! RESET) { uint32_t currentRPM (pulseCount - lastCount) * 60 / 20; if(currentRPM 500) { TIM_SetAutoreload(TIM3, 1000-1); } else if(currentRPM 2000) { TIM_SetAutoreload(TIM3, 500-1); } else { TIM_SetAutoreload(TIM3, 200-1); } lastCount pulseCount; TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }4. 实测性能与优化建议4.1 实测数据对比使用标准转速台测试结果设定转速(RPM)测量值(RPM)误差率3002980.67%10009950.5%300029760.8%4.2 常见问题排查表现象可能原因解决方案读数不稳定电源干扰增加10μF电容并联在VCC-GND转速显示为零接线错误检查DO线是否接在PB14数值周期性波动码盘偏心重新安装码盘保证同心度高速时计数丢失中断处理时间过长优化中断服务函数代码4.3 扩展应用思路无线传输模块添加HC-05蓝牙模块实现手机监控数据记录功能利用STM32内部Flash存储历史数据PID控制闭环结合PWM输出实现自动调速多路测速扩展使用多个红外传感器完整工程代码已托管在GitHub搜索STM32F103-MHSensor-Speedometer包含Keil MDK完整工程文件原理图PDF版本3D打印外壳STL文件安卓手机监控APP源码
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2581706.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!