简介:这份资源是面向嵌入式初学者与电子设计竞赛选手的单片机实战项目资料,围绕轴承旋转灵活性检测这一典型工业场景,提供从硬件到软件的完整实现思路。包内以原理图电路图、C语言程序源码、演示视频讲解及设计文档为主,压缩包约6.72MB,文件总数暂未提供明细。硬件部分涵盖传感器、信号调理、电源与显示模块的连接关系及元器件电气特性;软件部分包含初始化、数据采集、滤波计算与通信协议等关键代码,可帮助读者理解如何读取转速、转矩等参数并完成报警或显示逻辑。配套视频演示系统搭建、程序烧录与实际测试流程,文档则说明设计背景、工作原理与使用方法,便于对照复现和二次开发。目前已有109人学习,适合希望打通单片机软硬件协同、积累完整项目经验的读者参考。
1. 轴承灵活性检测这件事,为什么非得用单片机来做
产线上干了十几年的老师傅,判断一套轴承转起来顺不顺,靠的是手感——捏住内圈拨一下,听声音、看惯性、感受有没有卡滞。这套方法在单件维修场景下够用,但放到批量检测环节就彻底失效了:不同的人手感阈值不一样,同一个人上午和下午的状态也不一样,更别提把“有点涩”这种描述量化成可追溯的数据。基于单片机的轴承旋转灵活性检测系统,解决的正是这个“把老师傅的手感翻译成数字”的问题。它的核心思路不复杂:用电机带动轴承内圈或外圈旋转,通过传感器采集转速、扭矩或振动信号,再由单片机做特征提取和判定,最终输出合格/不合格或者灵活性等级。适合谁看?如果你手头有单片机开发基础,正在找一套能落地到工装治具上的检测方案,或者需要把人工判定环节改成自动化数据采集,这套东西的参考价值比较直接。源码包里通常包含信号采集、滤波、判定逻辑和串口/屏幕输出几个模块,下面拆开讲。
2. 系统架构与信号链:从轴承转动到单片机读到什么
2.1 为什么选“转速衰减法”而不是纯扭矩检测
轴承旋转灵活性的本质是摩擦力矩的大小和均匀性。常见做法有两类:一类是直接测扭矩,用扭矩传感器或者通过电机电流间接估算;另一类是测转速衰减,给轴承一个初始转速,然后看它自由减速到停的过程有多长、衰减曲线是否平滑。前者对传感器精度要求高,小尺寸轴承的摩擦力矩往往只有几毫牛米,普通扭矩传感器分辨率不够,信噪比很难看。后者用光电对管或者霍尔传感器就能做,成本低、响应快,而且转速衰减时间本身就是一个很直观的灵活性指标——转得越久说明阻力越小。
我一般会推荐转速衰减法作为主方案,扭矩检测作为辅助验证。具体实现上,用一个小直流电机通过联轴器带动轴承内圈加速到设定转速(比如 1500 rpm),然后断开电机驱动,让轴承自由减速。单片机用定时器捕获光电传感器的脉冲间隔,算出实时转速,记录从断开驱动到转速降到某个阈值(比如 50 rpm)所用的时间。这个时间越长,灵活性越好。源码里通常会有get_decel_time()这样的函数,核心就是定时器输入捕获加一个状态机。
2.2 信号采集电路的关键参数
光电对管方案里,发射端用红外 LED,接收端用光敏三极管,轴承外圈上贴一圈黑白相间的反光标记,或者直接在旋转部件上开一个缺口让光路通断。这里有几个参数容易翻车:限流电阻选大了,LED 亮度不够,接收端波形上升沿变缓,单片机捕获到的边沿位置漂移;选小了,LED 发热严重,长时间跑温漂明显。常见做法是红外 LED 限流电阻取 220Ω 到 470Ω 之间,接收端上拉电阻取 10kΩ,配合单片机内部施密特触发器整形。
如果轴承转速范围宽(比如 100 到 3000 rpm),单圈一个脉冲的话,低速时脉冲间隔太长,定时器溢出处理麻烦;高速时脉冲太密,中断响应不过来。折中方案是贴 6 到 12 个反光标记,这样低速时也有足够的分辨率,高速时中断频率在单片机可承受范围内。以 STM32F103 为例,72MHz 主频,定时器输入捕获中断处理时间大约 2 微秒,12 个标记在 3000 rpm 下脉冲频率是 600Hz,完全没压力。
2.3 单片机选型与资源分配
这个系统对单片机的算力要求不高,但对外设资源有几点硬需求:至少一个高级定时器做输入捕获,一个串口用于输出数据,若干 GPIO 控制电机驱动和状态指示。STM32F103C8T6 是最常见的选择,价格低、资料多、社区成熟。如果要做振动信号分析,需要加 ADC 采样加速度传感器,那就要考虑 RAM 够不够放 FFT 的缓冲区。8K RAM 跑 256 点 FFT 勉强够,但加上其他变量就紧张了,建议上 STM32F103RCT6 或者国产的 GD32 同级别型号。
源码包里一般会有main.c、capture.c、filter.c、judge.c和uart.c这几个文件。capture.c负责定时器输入捕获和转速计算,filter.c做滑动平均或者一阶低通滤波,judge.c里是判定逻辑和阈值比较,uart.c把结果打到串口助手上。拿到源码先看capture.c里的定时器配置,确认预分频和自动重装载值跟你的晶振频率匹配,这是最容易出问题的地方。
3. 从源码到工装:编译、烧录与参数整定
3.1 开发环境搭建与编译选项
源码包通常提供 Keil MDK 工程或者 Makefile 工程。如果用 Keil,注意器件包要装对,STM32F1 系列装 Keil.STM32F1xx_DFP。打开工程后先看 Options for Target 里的晶振频率设置,外部晶振是 8MHz 还是 12MHz,这个值错了会导致串口波特率偏差、定时器计时不准。编译前把stm32f10x_conf.h里用不到的外设注释掉,能减小固件体积,也避免一些莫名其妙的编译错误。
如果用 Makefile 加 arm-none-eabi-gcc,检查Makefile里的C_SOURCES和C_INCLUDES路径,源码包解压后目录结构可能跟原作者不一样,路径要手动改。链接脚本.ld文件里的 FLASH 和 RAM 起始地址、大小要跟你的芯片型号一致,C8T6 是 64K FLASH、20K RAM,RCT6 是 256K FLASH、48K RAM,写错了要么烧不进去,要么跑飞。
# 以 Makefile 工程为例,编译并生成 bin 文件 make clean make -j4 arm-none-eabi-objcopy -O binary build/your_project.elf build/your_project.bin # 用 st-flash 烧录(需要 ST-Link 调试器) st-flash write build/your_project.bin 0x08000000上面这段命令里,make clean清掉旧的目标文件,避免增量编译时残留的.o文件导致链接错误。-j4是并行编译,加快速度。objcopy把 ELF 转成纯二进制,因为 st-flash 只认 bin 或者 hex。烧录地址0x08000000是 STM32 内部 FLASH 的起始地址,这个不能改。如果你用 J-Link,把最后一行换成JLinkExe的脚本或者用 J-Flash 图形界面操作。
3.2 转速捕获与衰减时间计算的代码逻辑
源码里最核心的函数是转速捕获和衰减时间计算。下面这段代码是简化后的逻辑,实际工程里会加上超时保护和异常处理。
// capture.c 中定时器输入捕获中断处理 void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { uint16_t capture_val = TIM_GetCapture1(TIM2); uint16_t period = capture_val - last_capture_val; // 两次捕获的计数值差 last_capture_val = capture_val; // 计算转速:定时器频率 1MHz,每转 12 个脉冲 // rpm = (60 * 1000000) / (period * 12) if (period > 0) { current_rpm = 5000000 / (period * 12); // 简化计算 } // 状态机:检测到电机断电后开始计时 if (motor_off_flag && current_rpm < STOP_THRESHOLD) { decel_time_ms = get_elapsed_ms() - motor_off_timestamp; judge_result = (decel_time_ms > PASS_THRESHOLD_MS) ? PASS : FAIL; } TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); } }这段代码的关键参数有三个:STOP_THRESHOLD是判定停转的转速阈值,一般取 30 到 50 rpm,取太小了等待时间太长,取太大了衰减时间测不准。PASS_THRESHOLD_MS是合格判定的时间阈值,这个值需要根据轴承型号和实际测试数据来整定,没有万能值。period是两次捕获之间的计数值差,定时器预分频设为 72-1 的话,计数频率是 1MHz,每个计数代表 1 微秒,period直接就是微秒数。
注意current_rpm的计算里用了整数运算,5000000 / (period * 12)这个公式是60 * 1000000 / (period * 12)约分后的结果。如果period很大(低速时),除法结果可能为 0,需要加一个下限保护,或者改用浮点运算。但浮点运算在中断里开销大,我一般会判断period超过某个值就直接认为转速为 0。
3.3 阈值整定与重复性验证
阈值整定是这个系统能不能用的分水岭。源码里给的默认值只能让系统跑起来,真正要判定合格与否,必须用一批已知合格和不合格的轴承做标定。具体做法:取 20 套合格轴承和 20 套有轻微卡滞的轴承,分别测衰减时间,画出分布图。合格品的衰减时间应该集中在一个区间内,不合格品要么明显偏短,要么离散度很大。
如果两组数据的重叠区域太大,说明转速衰减法在这个轴承型号上分辨力不够,需要考虑加振动检测或者提高初始转速。初始转速提高后,摩擦阻力的差异会被放大,衰减时间的区分度会变好。但转速太高会带来噪声和轴承发热,一般不超过 3000 rpm。整定好的阈值写到judge.c的宏定义里,同时把标定数据存到 FLASH 里做追溯用。
重复性验证要做三件事:同一套轴承连续测 10 次,看衰减时间的标准差;同一批次不同轴承测一遍,看批内一致性;隔一天再测一遍,看温漂和磨损的影响。标准差超过平均值的 5% 就要查机械工装的同轴度和传感器安装位置了。
4. 避坑与排查:调试台上最容易翻车的五个地方
4.1 转速读数跳动大,衰减曲线毛刺多
现象是串口打出来的转速值上下跳,衰减时间每次测都不一样,重复性极差。原因通常是光电传感器的信号质量不行。反光标记的边缘不齐、标记间距不均匀、接收端没有施密特整形,都会导致捕获到的边沿位置抖动。解决方法是先拿示波器看接收端的波形,上升沿和下降沿要陡,过冲和振铃要小。如果波形本身没问题,那就是定时器捕获的滤波参数没设对,STM32 的输入捕获通道有ICFilter配置,设成 0x0F 可以滤掉高频噪声。
4.2 电机断电后轴承还在被驱动
现象是衰减时间异常长,甚至测出来比理论自由减速时间还长。原因是电机驱动电路断电后,电机线圈还在发电,通过续流二极管形成回路,产生阻尼力矩。解决方法是断电时同时断开电机两端,用继电器或者 H 桥的刹车模式让电机线圈短路,这样阻尼更大,轴承的衰减特性才能真实反映出来。如果用的是简单的三极管驱动,加一个继电器做物理断开。
4.3 串口输出乱码或者丢数据
现象是串口助手上看到的是乱码,或者数据断断续续。先查波特率,单片机晶振频率和串口初始化里的波特率设置要匹配,8MHz 晶振配 9600 或者 115200 都没问题,但 12MHz 晶振配 115200 会有误差。如果波特率没错,看是不是在中断里调用了printf,printf是阻塞式的,放在中断里会打乱时序。正确做法是把数据存到缓冲区,在主循环里发送。
4.4 判定结果跟人工手感不一致
现象是系统判合格的轴承,老师傅说手感涩;系统判不合格的,老师傅说没问题。这种情况先别急着改阈值,先确认人工判定的一致性——找三个老师傅盲测同一批轴承,看他们之间的一致率。如果人工判定本身就不一致,那系统判定的“不一致”反而是对的。如果人工判定一致而系统不一致,检查工装夹持力是否过大,夹持力会改变轴承的预紧状态,影响摩擦力矩。
4.5 长时间运行后数据漂移
现象是系统刚开机时测的数据跟跑了两小时后的数据对不上,合格率逐渐下降。原因是红外 LED 发热导致发光强度变化,接收端的光电流跟着变,边沿位置漂移。解决方法是给 LED 加恒流驱动而不是恒压驱动,或者用调制发射加同步解调,彻底消除环境光和温漂的影响。简单点的做法是每隔半小时自动重新标定一次零点,用标准件跑一遍校准。
5. 进阶玩法:把单点检测变成趋势数据
源码包给的是一个能跑通的最小系统,但真正在产线上用起来,单次判定合格/不合格只是及格线。我后来习惯在judge.c里加一个趋势记录模块,把每次测的衰减时间、转速曲线特征值(比如减速过程中的波动次数)存到外部 FLASH 或者通过串口打到上位机。这样做的价值在于:轴承的灵活性劣化往往是一个渐变过程,单次判定可能都在合格范围内,但衰减时间在缓慢缩短,波动次数在增加。等到判定不合格的时候,其实已经劣化很久了。
具体实现上,在judge.c里加一个环形缓冲区,存最近 100 次的衰减时间。每次测量后计算滑动平均值和标准差,如果标准差连续 10 次增大,即使当前值还在合格范围内,也输出一个“预警”标志。上位机那边用 Python 或者 LabVIEW 画趋势图,横轴是测量次数,纵轴是衰减时间,合格线画一条,预警线画一条。这套东西加上去之后,产线反馈说能提前两三天发现某批轴承的异常趋势,比等到批量不合格再停线排查省事得多。
验证方法也简单:拿一套已知会逐渐劣化的轴承(比如清洗不干净或者润滑脂分布不均的),连续跑几百次,看趋势曲线是不是单调下降。如果是,说明趋势模块工作正常。如果曲线上下跳没有趋势,要么是测量重复性不够,要么是轴承劣化过程太快,单次测量间隔太长。这时候把测量间隔缩短,或者提高转速让劣化加速。
从那以后我每次拿到一套新的检测源码,第一件事不是改判定逻辑,而是先跑 50 次重复性测试,把衰减时间的标准差算出来。标准差大于平均值的 3%,后面所有阈值整定都是白费功夫。这个习惯帮我省掉了至少三次返工。希望帮到你。
本文还有配套的精品资源,点击获取