教室里的粉笔灰问题,大家都不陌生:每次擦完黑板,前排同学下意识捂鼻子,讲台边沿永远积着一层白灰,黑板下沿的粉笔槽更是重灾区。这个基于STM32单片机的黑板粉尘清除装置,就是冲着这个场景去的——用传感器检测积灰,用电机带动清扫机构把粉尘收进集尘盒,整个过程自动完成,不需要人弯腰去擦、去倒。我做这套装置的动机很朴素:与其在答辩PPT里堆概念,不如做一个看得见、摸得着、能现场演示的完整系统。它从传感器选型、电机驱动、PWM调速到机械结构配合,覆盖了一条完整的嵌入式开发链路,非常适合作为单片机方向毕业设计的主项目,也适合刚学完STM32想找个综合项目练手的开发者参考。
1. 需求拆解与整体方案设计
1.1 粉笔灰到底从哪里来,要清到哪里去
做设计之前,先得把“粉尘清除”这件事拆清楚。粉笔灰的产生有两个节点:一是书写时粉笔与黑板摩擦,少量粉尘直接飘落;二是擦黑板时,板擦把大面积粉尘扫落,其中一部分飘散到空气中,一部分沿黑板表面滑落,最终堆在黑板下沿的粉笔槽里。飘散到空气中的粉笔灰颗粒直径通常在10微米左右,会长时间悬浮,这是对呼吸系统影响最大的部分,但靠一个固定在黑板下方的装置很难处理悬浮颗粒,需要教室通风配合。真正能有效清理的,是沉降在粉笔槽和黑板下沿的积灰——这部分粉尘量大、集中、可预测。
所以这套装置的边界就很清晰了:检测黑板下沿粉笔槽里的积灰量,积灰达到一定厚度或环境粉尘浓度超标时启动清扫机构,把粉尘从槽内刮入集尘盒,同时用小型风机在吸尘口形成负压,防止清扫过程中粉尘二次飞扬。至于空气中已经飘散的颗粒,不在本装置的能力范围内,这一点在论文里需要写清楚,否则评委老师会追问。
1.2 清扫方案对比:为什么选“刮擦+负压”组合
确定目标之后,清扫方式的选择直接决定机械结构和代码复杂度。我对比过三种常见方案:
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 纯刮擦式 | 电机带动刮板沿粉笔槽往复运动,把灰尘推到一端 | 结构简单,成本低 | 刮板推灰时容易扬尘,边缘残留多 |
| 纯吸尘式 | 风机+吸尘口持续吸走槽内灰尘 | 无机械运动,寿命长 | 粉笔灰堆积较厚时吸不干净,需要人工预处理 |
| 刮擦+负压组合式 | 刮板或毛刷先把积灰松动,吸尘口紧随其后把粉尘吸走 | 清扫彻底,二次扬尘少 | 结构和控制逻辑略微复杂 |
我最终选了第三种。原因很直接:粉笔槽里的灰往往是压实状态,单纯靠吸力很难把板结的灰块吸起来,必须先用机械结构把它破坏、松动,吸尘口才能发挥作用。这个组合在工业吸尘器上已经很成熟——先刷后吸——只是把它小型化、自动化而已。机械上,我用一根同步带带动一个小滑台,滑台上固定毛刷和扁形吸尘嘴,沿黑板下沿导轨往复运动,吸尘嘴通过软管连接到小车内部的集尘盒和风机。整个行程在样机上做了1米,完整版可以按3米设计,原理完全一样。
1.3 主控选型:STM32F103C8T6为什么够用
主控的选择没什么悬念,STM32F103C8T6是目前毕业设计里最“稳”的芯片。72MHz主频、64KB Flash、20KB RAM,跑这种级别的控制逻辑绰绰有余。它有两个高级定时器可以输出多路PWM,足够同时驱动风机和清扫电机;有2个ADC,能接模拟量粉尘传感器;有足够多的GPIO接按键、指示灯、OLED显示屏和红外传感器。更重要的是,它的资料和开源例程极其丰富,任何一个功能模块都能找到现成代码参考,这对时间紧张的毕设来说是非常实际的加分项。
为什么不选更便宜的C6T6?它只有32KB Flash,如果把OLED字库、状态机逻辑、PWM控制全部写进去,Flash空间会比较紧张,后续扩展几乎没有余地。为什么不选F407系列?性能过剩,而且LQFP100封装焊接难度大,打板成本也高。C8T6是目前这个场景下的性价比甜点,我身边好几个做类似项目的同学最后都回到这个芯片上。
2. 硬件选型与电路设计要点
2.1 系统框架与供电设计
整套硬件可以按功能分成四层:感知层(红外积灰检测、粉尘浓度检测)、控制层(STM32最小系统)、执行层(风机、步进电机或直流减速电机)、人机交互层(OLED屏、按键、指示灯)。供电方面,我的方案是外部12V/2A直流适配器供电,经过降压后分成两路:12V直接给风机和电机驱动模块供电,5V给STM32系统板供电,再通过AMS1117-3.3给OLED和传感器供电。
这里有一个容易踩的坑:不要把风机和单片机共用一个5V供电。风机启动瞬间电流冲击很大,实测能拉低电源电压0.5V以上,会导致单片机复位。我测试时用同一个5V电源给风机和STM32供电,结果风机一启动,OLED屏幕就闪一下,程序偶尔重启。后来改成12V直接给风机,5V单独从适配器降压出来,问题就消失了。如果条件允许,最好在电机电源输入端并联一个大容量的电解电容,比如470uF/25V,可以吸收启动浪涌。
2.2 积灰检测传感器的两种实现思路
积灰检测是整个装置触发逻辑的关键。我做样机时试了两种方案,各有适用场景:
第一种是红外反射检测。在粉笔槽一侧安装一对红外发射管和接收管,没有积灰时,接收管收到的反射信号较弱;积灰变厚后,灰尘表面更接近传感器窗口,反射信号增强。接收管输出的模拟电压经ADC采样后,和阈值比较就能判断“需要清扫”。这个方案优点是成本极低,一个红外对管几毛钱;缺点是检测区域很小,只能覆盖粉笔槽的一个截面,如果粉笔灰只在另一侧堆积,会测不到。
第二种是粉尘浓度传感器,型号是GP2Y1010AU0F。它的原理是内部红外LED发出一束光,空气中的粉尘颗粒产生散射光,光电二极管把散射光强度转换为电压,粉尘浓度越高输出电压越大。这种传感器能感知空气中悬浮的粉笔灰浓度变化,擦黑板时浓度飙升,可以作为清扫启动的辅助条件。但它的响应更多反映“正在产生的粉尘”,而不是“已经堆积的粉尘”,单独用容易误触发——比如有人路过带起一阵风,传感器读数也会波动。
我的最终做法是两者结合:红外对管负责检测积灰厚度,粉尘传感器负责检测擦黑板动作,逻辑上“积灰超阈值 OR 粉尘浓度超阈值”即触发清扫。这个设计在答辩时也是加分项,因为它体现了“冗余检测、逻辑融合”的工程思维,而不是单一传感器一拍脑袋。
2.3 电机驱动模块与PWM通道规划
清扫机构我选的是42步进电机配合DRV8825驱动模块,之所以不用普通直流减速电机,是因为步进电机可以精确控制往复运动的行程——每次清扫从起点出发,走到终点再返回,行程固定,不容易出现直流电机因惯性导致的越位问题。风机用的是12V涡轮风机,功率大约12W,通过N沟道MOS管或L298N模块做PWM调速。
引脚分配上,我尽量避开默认的JTAG/SWD复用引脚,避免下载器冲突:
| 功能 | 引脚 | 备注 |
|---|---|---|
| 步进电机脉冲 | PA8 | TIM1_CH1,PWM输出 |
| 步进电机方向 | PB10 | GPIO输出 |
| 风机PWM | PA1 | TIM2_CH2,PWM输出 |
| 红外传感器ADC | PA4 | ADC1_IN4 |
| 粉尘传感器ADC | PA5 | ADC1_IN5 |
| OLED I2C | PB6/PB7 | 软件I2C |
| 按键1(手动启动) | PB0 | 下降沿触发 |
| 按键2(模式切换) | PB1 | 自动/手动 |
| 运行指示灯 | PC13 | 板上LED |
这里提一个细节:DRV8825的步进脉冲频率决定电机转速,我是用定时器PWM输出脉冲的,而不是在中断里翻转引脚。定时器PWM的好处是脉冲频率恒定且不占用CPU,在扫灰过程中单片机还能同时处理传感器和OLED刷新,系统响应不会被拖慢。
2.4 集尘结构设计:滤网和密封比风机更重要
集尘盒这个部件看起来不起眼,反而是整个装置“体验感”的关键。如果滤网选不好,风机吹出的风会裹着细灰直接喷到人脸上,效果比不清理还糟。我用的是HEPA级别的滤棉,拦截效率在99%以上,配合一个用3D打印的集尘盒上盖密封圈,基本能做到出风口无可见粉尘。
另外一个细节很多人会忽略:风机应该放在滤网的后方,也就是“吸”而不是“吹”。管路连接是吸尘嘴 -> 软管 -> 集尘盒 -> 滤网 -> 风机 -> 出风口。这样气流先经过滤网再经过风机,风机叶片不会被粉尘污染,寿命长很多。如果接反了,粉尘直接打在风机叶片上,用不了几次叶片上就会结一层灰,动平衡被破坏,噪音越来越大。
3. 控制逻辑与核心代码实现
3.1 系统状态机设计
整个控制程序本质上是一个五状态的状态机:待机 -> 检测 -> 清扫 -> 返回 -> 待机,中间穿插一个报警状态。用状态机的好处是逻辑清晰,每个状态下程序只干一件事,不容易写成一锅粥。我用枚举定义状态,主循环里用switch分发:
typedef enum { STATE_IDLE, STATE_DETECT, STATE_CLEANING, STATE_RETURNING, STATE_ALERT } SystemState; SystemState currentState = STATE_IDLE;待机状态下,系统只做两件事:低频轮询传感器、刷新OLED显示。检测状态其实是待机状态的一个分支判断,我单独拉出来是为了方便调试——单独按一个测试按键可以直接跳到检测逻辑,快速验证传感器阈值是否合理。清扫状态下,步进电机以设定速度正向运动,风机以70%占空比运行,同时持续监控是否到达末端限位。返回状态则反向运动并关闭风机,回到初始限位后切换回待机。
3.2 PWM频率与占空比计算
PWM参数是运行时最有“技术含量”的部分。我的晶振是8MHz,经PLL倍频到72MHz系统时钟。以TIM2产生风机PWM为例,目标PWM频率取15kHz左右,这个频率高于人耳可听范围,不会产生尖锐的啸叫。计算公式:
PWM频率 = 72MHz / ((PSC + 1) * (ARR + 1))
我设置PSC = 3,ARR = 1199,代入得到 72MHz / (4 * 1200) = 15kHz。占空比调节通过CCR寄存器实现,风机全速对应1200,70%占空比则设置CCR = 840。实际测试下来,70%占空比时风机风量已经足够在吸尘口形成明显负压,噪音也比100%时低不少。如果占空比低于30%,风机会因为扭矩不足出现启停抖动,需要尽量避免。
步进电机用TIM1产生脉冲,频率直接决定转速。我设的脉冲频率是2kHz,对应步进电机在8细分下约37.5转/分钟,配合同步带传动,清扫速度大约每秒15厘米,1米行程大约7秒走完,效果比较协调。太快的速度会导致毛刷来不及把灰“扫”起来就被吸尘嘴压过去了,反而清理不干净,这个速度是实测后确定的。
3.3 传感器采样与阈值判断逻辑
红外传感器的ADC采样不是读一次就能用的。粉笔灰是缓慢积累的过程,单次采样容易受到环境光、传感器窗口灰尘等干扰。我做了简易的滑动滤波:连续采样8次,去掉最大值和最小值后取平均,每200ms更新一次。积灰判定阈值的确定方法是:先在干净状态下测一个基准值,然后人为在传感器前铺一层粉笔灰,测出满量程值,取两者中点的70%作为触发阈值。这个标定过程需要写进文档,因为不同批次的传感器基准值会有差异,阈值写死是不靠谱的。
粉尘传感器的数据处理稍微特殊一点。GP2Y1010AU0F输出的是模拟电压,但它的脉冲式工作方式要求软件配合:每次采样前先给LED一个0.32ms的高电平脉冲,然后在脉冲开始后0.28ms时刻读取电压。我用一个定时器中断辅助实现这个时序,读取到的电压经过换算得到浓度值(每立方米微克数)。换算公式在数据手册里有曲线,我直接拿Excel拟合了一段线性关系,在代码里用乘加运算实现。
3.4 主循环与OLED显示
主循环采用定时调度:使用SysTick作为1ms时基,每5ms处理一次按键扫描,每200ms处理一次传感器数据,每500ms刷新一次OLED。这样传感器、电机、显示互不阻塞,按键响应也不会因为执行清扫任务而卡顿。
OLED我用的是0.96寸I2C接口屏幕,通过软件模拟I2C驱动。为什么不放硬件I2C的坑?STM32F103的硬件I2C在库函数版本上偶尔会出现总线锁死的问题,排查起来比较费时间,软件I2C虽然占CPU,但胜在稳定可控,对120ms刷新一次这种低频操作来说完全够用。屏幕上显示三行信息:当前状态(待机/清扫/报警)、粉尘浓度值、积灰阈值百分比。用百分比而不是原始ADC值更直观,答辩演示时也更友好。
void System_Run(void) { switch (currentState) { case STATE_IDLE: CheckSensors(); if (dustSensorValue > DUST_THRESHOLD || grayDepthValue > GRAY_THRESHOLD) { currentState = STATE_CLEANING; OLED_ShowString(0, 0, "Cleaning..."); } break; case STATE_CLEANING: STEP_MOTOR_FORWARD(); FAN_SetDuty(840); // 70% duty if (LIMIT_SWITCH_END_READ()) { currentState = STATE_RETURNING; } break; case STATE_RETURNING: STEP_MOTOR_BACKWARD(); FAN_SetDuty(0); if (LIMIT_SWITCH_START_READ()) { currentState = STATE_IDLE; OLED_ShowString(0, 0, "Standby..."); } break; } }3.5 手动模式与异常保护
除了自动模式,我保留了一个手动模式。手动模式下,系统不自动触发清扫,而是通过一个按键控制:按一下执行一次完整清扫流程。这是为了应对一些特殊情况——比如讲台上有人站着不方便清扫,或者粉笔灰还没积到阈值但肉眼看着已经不舒服了,可以人工干预。
异常保护方面,我做了三个层面的处理:一是限位开关,步进电机到达行程两端时通过状态判断自动停止,避免堵转烧毁;二是超时保护,如果清扫开始后30秒内没有触发末端限位,说明机构可能卡死,程序自动停机并进入报警状态,OLED显示Error;三是风机堵转检测,风机电流经过采样电阻转换成电压后送入ADC,如果电流异常升高,程序会降低PWM占空比并蜂鸣报警。报警状态需要人工按键解除,这个设计避免设备带着故障反复运行。
4. 机械结构设计、组装与调试记录
4.1 结构件选材与加工方式
机械部分是这类项目里最容易被低估的工作量。我的样机结构包括:两根黑色铝型材作为导轨支架,一根GT2同步带负责传动,一个3D打印的滑台座固定毛刷和吸尘嘴,两端各有一个3D打印的端盖用来安装同步轮和限位开关。选铝型材而不是3D打印整个框架,是因为铝型材刚性足够且安装方便,直接用M3螺丝和角码组装;3D打印适合做滑台这类形状复杂的小零件,精度也能满足要求。
毛刷的选择有讲究。普通硬毛刷容易划伤黑板漆面,一般教室的黑板表面是磨砂材质,被硬毛刷反复刮擦后会留下划痕。我试过几种材料后,最终选了柔软的尼龙毛刷,长度约5厘米,既能进入粉笔槽的凹槽部分,又不会伤板面。吸尘嘴做成扁平的鸭嘴形状,开口宽度略大于粉笔槽宽度,与槽底保持约3毫米间隙,离太近会被灰尘堵塞,离太远负压效果衰减明显。
4.2 装配顺序与限位开关安装
装配顺序建议先搭机架,再装传动系统,最后装电气部分。第一步把铝型材按黑板下沿长度裁好,用角码固定在黑板框架底部;第二步装同步轮和同步带,注意同步带要张紧,否则滑台走到中间位置时皮带会晃动导致丢步;第三步把滑台挂上,手动推一下确认全程没有卡顿;第四步安装步进电机和限位开关,末端的限位开关装在行程终点前2厘米处,给滑台留出减速缓冲空间。
限位开关我用的是机械式滚轮限位开关,而不是光电开关。原因很实际:粉笔灰环境里光电开关的发射接收窗口会迅速积灰,灵敏度衰减很严重;机械开关虽然寿命有限(几十万次),但胜在抗灰尘能力强。这个选择在调试时验证了它的价值——一台装了光电限位的同学样机,运行一周后偶尔出现限位失灵,拆开一看是窗口被灰糊住了,机械开关没有这个问题。
4.3 整体联调时的时序观察
电气和机械装配完成后,联调阶段我习惯分三步走。第一步,单独测试步进电机:只调电机驱动,验证正反转、限位触发、行程覆盖,不涉及风机和传感器。第二步,加入风机和传感器:手动触发一次清扫流程,观察风机的启动时机和吸尘效果。第三步,切换自动模式:模拟积灰场景,在粉笔槽里倒一层粉笔灰,观察整套系统从检测到清扫再到复位的完整时序。
联调时一定要录视频。我自己的经验是,每次修改代码或结构后录一段运行视频,对比前后的行为差异,很多问题通过视频回放才能看出来。比如有一次清扫过程中吸尘嘴在某一段位置出现轻微抖动,从代码层面完全看不出来,回放视频才注意到是同步带在那个位置有一点松,张紧之后问题消失。
4.4 整机功耗与续航评估
因为装置固定安装在墙面上,供电走市电适配器,不需要考虑电池续航,但功耗还是值得测一下。我用一个USB功率计实测:待机状态整机电流约0.2A(12V),也就是2.4W,主要损耗在STM32板子和传感器上;清扫状态电流约1.6A(12V),约19.2W,峰值的2.2A出现在步进电机启动和风机加速的瞬间。这个数据写进论文里的意义是证明设计的合理性——整个装置最大功耗在20W级别,一个普通12V/2A适配器即可覆盖,不需要特殊供电设计。
5. 常见问题与排查技巧实录
5.1 问题速查表
做这类涉及机械+电气+代码的项目,问题大概率出在交叉环节。我记录下调试过程中最常遇到的几个问题整理成表:
| 现象 | 可能原因 | 排查方法 | 解决办法 |
|---|---|---|---|
| 步进电机抖动但不转 | 驱动板细分拨码设置错误、脉冲频率过高 | 先降到1kHz测试 | 检查细分开关,降低脉冲频率 |
| 风机转动但吸尘无力 | 滤网堵塞、管路漏气 | 拆开集尘盒检查滤网 | 更换滤网,检查软管接头密封 |
| 红外传感器误触发 | 环境光直射、窗口积灰 | 用手遮挡传感器检查ADC值变化 | 加遮光罩,定期清洁窗口 |
| 清扫到一半停住 | 同步带跳齿、限位开关接触不良 | 手动推滑台看是否卡顿 | 张紧同步带,调整限位位置 |
| OLED显示花屏 | 软件I2C时序被中断干扰 | 增大OLED刷新间隔 | 在I2C读写时关闭中断 |
| 按下按键无反应 | GPIO配置错误、按键抖动 | 串口打印按键状态 | 使能内部上拉,加软件消抖 |
5.2 电源干扰导致的“幽灵bug”
最让我头疼的一个问题:清扫过程中,OLED偶尔会出现一条闪烁的横线,但程序逻辑完全正常。起初怀疑是OLED本身的问题,换了屏幕依旧。后来用示波器观察3.3V电源轨,发现每次风机PWM占空比变化时,3.3V上会出现一个约200mV的毛刺,幅度不大但刚好超过OLED的电源噪声容限。原因是风机PWM通过接地回路影响了AMS1117的参考地。
解决思路有两个方向:一是把风机的地线从主控板的地线分离,采用单点接地——所有大功率负载的回路直接回到电源适配器负极,不经过单片机板子;二是在AMS1117的输入输出各加一个10uF陶瓷电容和一个100nF高频去耦电容,增强电源抗扰能力。我两个都做了,实测毛刺降到80mV以内,OLED不再闪烁。这种“软故障”最难排查,建议在硬件设计阶段就做好电源隔离。
5.3 粉笔灰环境下的长期可靠性
最后一个值得分享的观察是粉笔灰对设备的长期影响。设备运行一个月后,我拆开检查发现:步进电机轴端有微量粉灰侵入,传感器窗口积了薄薄一层灰,毛刷根部缠了一些粉笔屑。这些都不致命,但提醒我一个关键点——所有裸露的转动部件和传感器窗口,都应该设计可拆卸的防尘罩。我的做法是在步进电机轴上加了一个硅胶防尘圈,在传感器窗口前面贴了一层透明PET薄膜(每两周更换一次),在毛刷根部加了一片小挡板。这些低成本改动把设备的维护周期从一周延长到一个月,对实际部署来说意义很大。
另外,CMOS传感器窗口不能用干布擦拭,会留下细微划痕影响检测精度,正确做法是用气吹先吹掉浮灰,再用无尘布蘸少量酒精轻擦。这个细节看起来很小,但在答辩现场演示时如果传感器数据异常,会直接影响评委对系统稳定性的印象。
5.4 成本清单参考
不少同学关心整套装置的成本,我实际采购的清单供参考:STM32F103C8T6开发板约12元,42步进电机加DRV8825驱动约35元,12V涡轮风机约25元,铝型材和同步带约40元,3D打印结构件约30元,GP2Y1010AU0F粉尘传感器约28元,红外对管和限位开关加起来不到10元,OLED屏15元,适配器和其他辅材约20元。总成本在215元左右。
这个成本处于毕业设计项目的合理区间,比纯仿真类项目多了一些硬件投入,但换来的是一个能反复演示、能出实物照片和视频、能拆开讲解每个模块的完整系统。我个人认为,预算允许的前提下,这类机电结合的项目在毕业设计答辩中的说服力远高于纯软件仿真。
做完这套装置,我最大的体会是:真正的工程量不在代码里,而在代码和现实世界的交界处。传感器会受环境光干扰,风机会产生电源毛刺,同步带会松弛,粉笔灰会堵住一切能堵的缝隙——这些不确定性才是硬件项目区别于纯软件项目的核心挑战。方案本身并不神秘,STM32、步进电机、传感器,都是课本上讲过的东西,但把它们组合成一个能在真实教室里稳定运行的装置,每一步都在和物理世界较劲。如果你正在做类似的选题,我建议把时间分配向机械结构和联调倾斜,代码部分反而可以往后放。
最后分享一个实用技巧:调试时把粉尘传感器的阈值临时调低一些,让它频繁触发清扫,然后坐在旁边观察整个流程,连续跑十几遍。这样做能快速暴露机械卡顿、限位失灵、电源不稳等隐藏问题,比你自己“感觉差不多”要可靠得多。等所有问题都暴露并修掉之后,再把阈值恢复正常,你拿到手的就是一个真正能稳定工作的系统——而不是一个只能在答辩现场勉强演示的样机。