基于STM32的智能垃圾桶设计:红外感应、超声波满溢与状态机实现
发布时间:2026/10/28 19:21:29 锦皓数字建站

简介面向单片机课程设计、毕业设计及嵌入式入门读者的《基于 STM32 的智能垃圾桶设计》完整论文文档以 STM32F103C8T6 为核心围绕超声波测距、红外感应、电机驱动、LCD1602 显示、WT588D 语音播报与继电器消毒等模块展开适合需要参考系统方案、硬件选型与控制逻辑的读者。资源包共 1 个 PDF 文件大小约 1.94MB保留封面、独创性声明、中英文摘要、关键词及正文等完整结构便于按章节查阅。目前已有 7845 人学习文中对自动翻盖、满溢语音提醒、延时关闭和按键消毒等功能的实现思路交代较清楚并配有总体方案、模块电路与软件流程的论述对超声波测距、红外感应与电机驱动之间的联动关系、延时参数设置及语音报警触发条件也有说明可作为课程设计、毕业设计选题、答辩准备及系统框图整理的参考资料。1. 从「不想用手掀盖」说起这套智能垃圾桶方案要解决的四个真问题做基于 STM32 的智能垃圾桶设计这个题目最容易翻车的地方不是焊板子而是把它做成一堆模块的堆砌红外能感应、超声波能测距、屏幕能亮但合起来不知道要干什么。我在动手前先把需求钉死成四句话手不碰桶盖就能扔垃圾桶快满了要有人喊一声垃圾倒掉后能消一遍毒断电或程序跑飞时还能当普通桶用。这四条对应四组输入输出也决定了后面所有的选型。这套方案适合正在做单片机课程设计、电子类毕设的读者硬件成本可控软件规模在一个 F103C8T6 里跑得开答辩时每一条功能都能当着老师的面复现。下面按「需求怎么变成架构、架构怎么落到电路、电路怎么被代码驱动、最后怎么验收」的顺序展开。2. 总体方案设计一颗主控、四路输入、三路输出的职责划分2.1 把五条验收要求翻译成输入输出动作需求分析这一节在很多方案里写得像散文其实它就是一张映射表。我一般会把每条功能拆成「谁触发、单片机看到什么、单片机做什么、人看到什么结果」四列拆完以后硬件框图基本就自己长出来了。红外感应这条触发源是靠近的人手或身体单片机看到的是 PA0 上一个由高变低的电平跳变动作是驱动电机正转开盖人看到的结果是盖子抬起、屏幕状态从 CLOSED 变成 OPEN。超声波满溢这条触发源是桶内垃圾面单片机看到的是一个距离数值动作是调用语音芯片播报人听到的是「垃圾桶已满请及时处理」。继续往下拆会发现两个隐藏需求不写进功能列表但必须实现。一个是关盖延时人手离开后不能立刻关否则容易夹手通常取 3 到 5 秒另一个是满溢后的重复播报抑制垃圾一直满着不能每秒钟喊一遍需要做状态锁和回差。消毒功能也要加互锁消毒期间禁止开盖因为无论是紫外还是臭氧对人都不友好这条在答辩时是加分项说明你想过安全问题。拆解完得到一份清单输入有红外电平、超声波距离、三个按键输出有电机正反转、继电器、语音、液晶。数量上刚好被 F103C8T6 的 37 个可用 IO 覆盖不用扩 io 口也不用上第二块板子。这一步做完选型就没有悬念了。提示需求表里一定要单独列一栏「异常时的表现」比如超声波测不到回波、红外一直有信号这些异常怎么处理会直接决定第 5 章的排查思路。2.2 总体架构与引脚分配一颗 F103C8T6 怎么排得下系统按星型结构组织STM32F103C8T6 做中心节点所有模块挂在它周围模块之间不直接通信。这条原则很重要一旦让红外模块直接去驱动电机逻辑就散在硬件里后面改「人走后延时 5 秒再关盖」这种需求就得动电路。全部收归单片机以后任何时序调整都只是改一行宏定义。引脚分配我按「功能分组、避开调试口」的原则排具体见下表。PA13 和 PA14 是 SWD 下载调试口任何时候都不要占用血泪经验是有人把 LCD 数据线排到这两个脚上结果程序下载不进去查了两个晚上。功能引脚模式说明红外感应输出PA0上拉输入LM393 输出检测到物体为低模式切换键PA1上拉输入自动/手动手动开盖键PA2上拉输入手动模式下点动消毒键PA3上拉输入下降沿触发LCD1602 D4~D7PA4~PA7推挽输出四位数据模式LCD1602 RS/RW/ENPA8/PA9/PA10推挽输出RW 只写时可接地超声波 TrigPB0推挽输出输出 20us 高脉冲超声波 EchoPB1浮空输入兼作 TIM3_CH4PB1 为 5V 容忍脚电机 IN1/IN2PB6/PB7推挽输出接 ULN2003A 两路输入消毒继电器PB8推挽输出低电平吸合语音 DATAPB9推挽输出WT588D 一线串口语音 BUSYPB10上拉输入播放中为低电平电机用两路 IO 而不是一路是为了能做正反转IN1 高 IN2 低是开盖反过来是关盖两路都低是停止。虽然也可以用单路加一个方向脚但 ULN2003A 是七路达林顿空着也是空着两路独立控制接线更直白。2.3 三种工作状态的划分与切换规则整个系统跑三个状态自动、手动、消毒。自动模式是默认态红外和超声波都生效人靠近开盖人离开延时关盖。手动模式下红外被屏蔽只有按键能开盖关盖做测试和演示时特别有用因为你可以让盖子停在半空观察电机。消毒态是一个临时状态按下消毒键后先强制关盖再吸合继电器计时 30 秒后自动退出回到原来的模式。状态切换的规则要写死不能靠感觉模式键只在盖子完全闭合时有效避免盖子动到一半切模式把状态机搞乱消毒键在任何模式下都能触发但触发后会锁住开盖请求直到计时结束。这条互锁在代码里就是一个标志位实现成本很低但演示时能讲出东西来。状态机建议用枚举写而不是一堆 if 嵌套。自动/手动用work_mode_t盖子位置用lid_state_t两个维度分开维护互不干扰第 4 章会给完整实现。3. 硬件电路设计传感调理、驱动与消毒三段的落地细节3.1 最小系统与供电3.3V 和 5V 两套轨的分工板子上同时存在 3.3V 和 5V 两套电源这不是设计失误是模块决定的。STM32F103C8T6 主频 72MHz内核和 IO 都是 3.3VHC-SR04、LCD1602、继电器模块按 5V 设计WT588D 和红外调理电路可以吃 3.3V。常规做法是一个 5V 适配器进来经 AMS1117-3.3 降压给单片机5V 直供外设。最小系统包含三部分主时钟用 8MHz 无源晶振两侧各挂 20pF 起振电容RTC 时钟用 32.768kHz 晶振配 6pF 电容虽然这个设计里不用 RTC但最小系统板通常会焊上复位电路用 10k 上拉加 100nF 电容加轻触按键复位按键按下时 NRST 拉低松开后电容充电延时释放保证上电复位可靠。BOOT0 串 10k 下拉到地从主闪存启动这个电阻别省。电源入口并一个 1000μF 电解电容加一个 0.1μF 瓷片电容前者对付电机启动时的浪涌后者滤高频。这个位置看起来不起眼但它是第 5 章那类「电机一转就复位」问题的第一道防线。3.2 红外感应链路RPR220 加 LM393 的阈值怎么定选 RPR220 的理由很实在反射式、体积小、几毛钱一颗内部带可见光过滤室内灯光干扰比裸光敏管小得多。它的接法是发射管串限流电阻常亮接收管集电极接上拉光敏三极管收到反射光时导通集电极电压下降。单靠 RPR220 的输出没法直接给单片机因为模拟量随距离和物体颜色连续变化需要一个判决门限。LM393 就是干这个的RPR220 的接收端接同相输入端反相输入端接一个 10k 电位器分压。有反射光时同相端电压被拉低低于反相端设定值比较器输出低电平没有反射时同相端被上拉输出高电平。所以这个电路是「检测到物体输出低」PA0 配置成上拉输入程序里判断下降沿即可。电位器要现场调调法是把桶放在实际使用位置用手在 5cm 到 30cm 之间反复靠近找到一个「远处不触发、近处稳定触发」的中间点然后锁死。我一般会在电位器旋钮上点一点热熔胶防止运输或答辩搬动时跑偏这算是踩过坑之后的习惯。RPR220 的输出还会经过一级 RC 滤波10k 加 0.1μF时间常数 1ms 左右能压掉日光灯 100Hz 的闪烁干扰。这点很关键很多方案里红外乱触发根源就是工频光调制被当成了物体信号。3.3 超声波接口HC-SR04 的电平与时序前提HC-SR04 有四个脚VCC、GND、Trig、Echo。工作过程是 Trig 收到一个至少 10μs 的高电平模块内部自动发出 8 个 40kHz 的脉冲串同时 Echo 拉高直到收到回波或超时Echo 拉低。高电平持续时间就是声波往返时间距离等于时间乘声速除以二声速取 340m/s 时换算成厘米就是高电平微秒数除以 58。这套时序有两个电气细节必须提前确认。第一Echo 是 5V 输出直接接普通 IO 会灌电流进保护二极管长期工作不可靠所以必须接 5V 容忍引脚PB1 正好是 FT 引脚这也是引脚表里把 Echo 放在这个位置的唯一原因。第二Trig 只需要 3.3V 高电平就能被识别因为 HC-SR04 的输入高电平门限是 2.0V 左右3.3V 有足够余量不需要电平转换。测量范围上模块标称 2cm 到 400cm实际在桶内这种小空间里最小可测距离受余振影响太近会读到虚假值。我的处理是把探头装在桶盖内侧中央向下照射垃圾面桶满时距离探头大约还有 8cm正好避开了盲区。3.4 电机驱动与消毒继电器感性负载的隔离桶盖用一个小型减速直流电机带动堵转电流能到几百毫安单片机 IO 直接驱动必然烧。ULN2003A 是七路达林顿阵列每路 500mA内部自带续流二极管接感性负载正合适。接法是 IN1 到 PB6、IN2 到 PB7OUT1 和 OUT2 分别接电机两端COM 脚接 5V电机断电瞬间的反电动势就通过内部二极管泄放到电源轨上。继电器模块负责消毒实物阶段它只是一个开关吸合代表消毒装置启动可以是紫外灯管也可以是臭氧发生器答辩时讲清楚这是模拟执行机构即可。继电器线圈本身也是感性负载成品模块上一般已经带了光耦隔离和续流二极管直接 IO 驱动就行。要注意的是模块的触发电平有高触发和低触发两种买回来先用万用表确认程序里的GPIO_ResetBits和GPIO_SetBits别写反否则上电就消毒演示时很尴尬。机械结构上我还加了一条开盖和关盖靠行程时间判定不装限位开关。电机转 1.2 秒基本能到机械限位之后短时间堵转ULN2003A 断电即可。这样做省了两个开关和两根线代价是这个时间常数要实测标定电压不足时行程会变短第 4 章会讲怎么在软件里补偿。3.5 显示与语音LCD1602 和 WT588D 的接线约定LCD1602 用四位数据模式只占用 4 根数据线加 3 根控制线省下来的 IO 留给其他模块。接法是 D4 到 D7 接 PA4 到 PA7RS 接 PA8 选择数据或指令RW 接 PA9EN 接 PA10 做使能脉冲。因为只写不读RW 其实可以直接接地但接一个 IO 更灵活调试时还能读忙标志。第三脚 VL 接 10k 电位器中间抽头用来调对比度这个电位器调不好会表现为整屏全黑或者全是方块很多人第一反应是程序错其实是对比度问题。WT588D 用一线串口模式只需要一根 DATA 线加一根 BUSY 线。三脚是音频输出四脚接功放或直接接喇叭P03 定义为 DATA 输入单片机按特定时序发送地址码就能触发对应语音段P15 是忙信号输出播放期间为低可以用来做「播完再播下一条」的排队控制。VDD 和 VCC 都接 3.3V喇叭串一个 8 欧 0.5W 的规格即可声音足够一个房间听见。4. 软件实现主循环加四个子程序的可复现写法4.1 工程骨架与初始化顺序开发环境用 Keil5 加标准外设库工程按功能分层bsp放 GPIO、定时器、延时driver放超声波、红外、LCD、语音、电机app放状态机和业务逻辑main.c只做初始化和主循环调度。分层的好处是答辩时你可以指着目录说清楚每个文件负责什么而不是所有代码都堆在 main 里。初始化的顺序有讲究先开时钟再配 GPIO再配定时器最后初始化外设模块。原因是 LCD 和语音芯片上电后需要一段稳定时间如果一上电就发指令容易吞掉第一条命令导致屏幕不亮。我一般的做法是延时 100ms 再初始化 LCD再延时 50ms 初始化语音。/* main.c —— 初始化与主循环调度1ms 节拍由 SysTick 提供 */ #include stm32f10x.h #include bsp.h #include lcd1602.h #include hc_sr04.h #include wt588d.h #include app.h volatile uint32_t g_ms_tick 0; void SysTick_Handler(void) /* 1ms 中断全系统唯一时基 */ { g_ms_tick; } int main(void) { SystemInit(); /* 72MHz 主频 */ BSP_Clock_Enable(); /* 各外设时钟使能 */ BSP_GPIO_Init(); /* 按键、电机、继电器统一在此配置 */ BSP_Systick_Init(72000); /* 1ms 一次中断 */ delay_ms(100); /* 等电源稳定也给 LCD 内部复位留时间 */ LCD1602_Init(); HCSR04_Init(); WT588D_Init(); App_Init(); /* 状态机变量复位默认自动模式 */ while (1) { App_Task_10ms(); /* 内部靠 g_ms_tick 分频10ms 执行一次 */ } }这段代码里最关键的设计是「只有一个时基」。所有延时、超时、计时都从g_ms_tick派生不额外开一堆定时器也不在主循环里写delay_ms(5000)这种阻塞调用。原因很直接一旦阻塞红外信号就没人采样人在桶前站五秒中间的状态变化全丢了表现出来就是「有时灵有时不灵」这种玄学问题。App_Task_10ms()内部用static uint32_t last记录上次执行时刻g_ms_tick - last 10才进入一次这是单片机里最朴素也最可靠的时间片写法。4.2 超声波测距输入捕获加中值滤波超声波测距有两种实现路径GPIO 轮询加定时器计数或者定时器输入捕获。轮询写法简单但 Echo 高电平期间 CPU 全被占住遇到无回波时会卡死。输入捕获由硬件记录边沿时刻CPU 只要等一个完成标志超时也好处理我选后者。TIM3 的通道 4 映射到 PB1预分频设成 7172MHz 除以 72 得到 1MHz 计数频率也就是一个计数对应 1 微秒正好可以直接套公式。捕获中断里第一次进是上升沿记下时刻并把极性改成下降沿第二次进是下降沿记下时刻、算出宽度、置完成标志。/* hc_sr04.c —— TIM3_CH4 输入捕获单次测距返回 cm-1 表示超时 */ #define SOUND_CM_PER_US 0.034f /* 340m/s 换算成 cm/us */ #define ECHO_TIMEOUT_US 30000 /* 30ms 无回波按超时处理约合 5m */ static volatile uint16_t s_rise, s_fall; static volatile uint8_t s_done; void TIM3_IRQHandler(void) /* 捕获中断两次边沿一次测量 */ { if (TIM_GetITStatus(TIM3, TIM_IT_CC4) ! RESET) { if (TIM_GetCapture4(TIM3) !s_done s_rise 0) { s_rise TIM_GetCapture4(TIM3); TIM_OC4PolarityConfig(TIM3, TIM_ICPolarity_Falling); } else { s_fall TIM_GetCapture4(TIM3); s_done 1; TIM_OC4PolarityConfig(TIM3, TIM_ICPolarity_Rising); } TIM_ClearITPendingBit(TIM3, TIM_IT_CC4); } } int16_t HCSR04_MeasureOnce(void) { uint16_t t0, t1, width; uint32_t guard; s_rise 0; s_fall 0; s_done 0; GPIO_SetBits(GPIOB, GPIO_Pin_0); /* Trig 拉高 */ delay_us(20); /* 要求 ≥10us给 20us 留余量 */ GPIO_ResetBits(GPIOB, GPIO_Pin_0); guard ECHO_TIMEOUT_US; while (!s_done guard--) delay_us(1); if (!s_done) return -1; /* 无回波垃圾面太软或超出量程 */ t0 s_rise; t1 s_fall; width (t1 t0) ? (t1 - t0) : (uint16_t)(0xFFFF - t0 t1); /* 处理计数器回绕 */ return (int16_t)(width * SOUND_CM_PER_US / 2.0f 0.5f); } int16_t HCSR04_GetDistance(void) /* 五次采样去极值取中值 */ { int16_t buf[5], tmp; uint8_t i, j, n 0; for (i 0; i 5; i) { tmp HCSR04_MeasureOnce(); if (tmp 0) buf[n] tmp; delay_ms(20); /* 两次测量间隔 ≥60ms 更稳 */ } if (n 0) return -1; for (i 0; i n - 1; i) /* 冒泡排序n 最大 5开销可忽略 */ for (j 0; j n - 1 - i; j) if (buf[j] buf[j 1]) { tmp buf[j]; buf[j] buf[j1]; buf[j1] tmp; } return buf[n / 2]; }几个参数需要单独说明。SOUND_CM_PER_US取 0.034 对应 20℃ 左右的声速冬天室内温度低声速会下降约 3%但桶内测距对绝对精度要求不高这个偏差可以接受。ECHO_TIMEOUT_US设 30ms对应约 5 米超过这个距离一定是没有有效回波比如垃圾是泡沫或者塑料袋声波被吸收掉了。取五次中值的做法值得多花两句单次超声波测量受温度、气流、桶壁反射影响很大直接读一次经常会出现几百厘米的野值屏幕上跳来跳去很像程序有 bug。中值滤波能把这些野值滤掉代价是五次测量要花大约 100ms对桶盖控制这种秒级响应的场景完全够用。为了避免每次都测五次拖慢主循环实际工程里会做成 100ms 触发一次测量并缓存结果业务逻辑直接读缓存。4.3 开盖关盖用时间片代替 delay 的状态机这是整个软件里最容易写歪的部分。新手写法是「检测到人 → 开盖 → delay 5 秒 → 关盖」逻辑上没错但五秒里程序什么都做不了屏幕不刷新、按键无响应、满溢也不检测。正确做法是把开盖关盖拆成四个状态每个状态只判断「条件满足没有」满足就迁移不满足立刻返回。/* app.c —— 盖子状态机10ms 调用一次全程无阻塞 */ typedef enum { LID_CLOSED, LID_OPENING, LID_OPEN, LID_CLOSING } lid_state_t; typedef enum { MODE_AUTO 0, MODE_MANUAL } work_mode_t; #define LID_TRAVEL_MS 1200 /* 电机走完全程的实测时间需按实物标定 */ #define LID_HOLD_MS 5000 /* 人离开后保持开盖的时间 */ #define LID_OVERRUN_MS 200 /* 到机械限位后多转一会确保关严 */ static lid_state_t s_lid LID_CLOSED; static work_mode_t s_mode MODE_AUTO; static uint32_t s_mark 0; void App_LidTask(void) { switch (s_lid) { case LID_CLOSED: if (App_OpenRequest()) { /* 自动模式看红外手动模式看按键 */ Motor_Open(); s_mark g_ms_tick; s_lid LID_OPENING; } break; case LID_OPENING: if (g_ms_tick - s_mark LID_TRAVEL_MS) { Motor_Stop(); /* 到位后断电机避免长时间堵转发热 */ s_mark g_ms_tick; s_lid LID_OPEN; } break; case LID_OPEN: if (s_mode MODE_AUTO App_ObjectNear()) { s_mark g_ms_tick; /* 人还在计时清零防止夹手 */ } else if (g_ms_tick - s_mark LID_HOLD_MS) { Motor_Close(); s_mark g_ms_tick; s_lid LID_CLOSING; } break; case LID_CLOSING: if (g_ms_tick - s_mark LID_TRAVEL_MS LID_OVERRUN_MS) { Motor_Stop(); s_lid LID_CLOSED; } break; } }LID_OPEN状态里那行「人还在就把时间戳刷新」是这套逻辑的核心。如果只在进入开盖状态时记一次时间人站在桶前慢慢扔垃圾五秒一到盖子就压下来了体验极差还容易夹到手。改成持续检测、有人就续期人走后才开始倒计时这才是符合直觉的行为。LID_TRAVEL_MS这个 1200ms 必须实测。做法是手动模式下按一次开盖用秒表或者干脆录一段视频数帧量出从通电到盖子停稳的时间然后写进宏定义。电池供电或者 5V 适配器功率不足时电机转速会下降行程时间变长这时要么换电源要么把这个值调大一点。LID_OVERRUN_MS是给关盖留的余量防止盖子差一点点没合严红外在缝隙里反复触发。4.4 满溢判定与语音播报的防抖满溢判定看着简单——距离小于阈值就报——实际有两个坑。第一个是临界抖动垃圾面刚好在阈值附近测量值在 7.9 和 8.1 之间来回跳语音就会被反复触发。解决办法是加回差小于 8cm 判定为满大于 11cm 才判定为不满中间 3cm 是死区进来就不动。第二个是重复播报垃圾一直满着不能每轮检测都喊一遍所以要加状态锁从「不满」跳到「满」的那个瞬间才播报一次。/* app.c —— 满溢检测带回差和单次播报锁 */ #define FULL_ENTER_CM 8 /* 小于此值判定满 */ #define FULL_EXIT_CM 11 /* 大于此值才解除形成 3cm 回差 */ static uint8_t s_full_flag 0; void App_FullTask(void) { int16_t d HCSR04_GetDistance(); if (d 0) return; /* 超时值不参与判定 */ if (!s_full_flag d FULL_ENTER_CM) { s_full_flag 1; WT588D_Play(WT_ADDR_FULL); /* 只在跳变沿播报 */ LCD1602_ShowStatus(FULL, d); } else if (s_full_flag d FULL_EXIT_CM) { s_full_flag 0; /* 垃圾被清空解除锁定 */ LCD1602_ShowStatus(OK , d); } }WT588D_Play内部要先读 BUSY 脚上一次播报没结束就等或者丢弃本次请求。一线串口的时序是拉低 DATA 若干毫秒表示起始然后逐位送出地址每一位用不同的高低电平宽度区分 0 和 1具体时序按芯片手册来不同批次的模块对脉宽容差不一样写完先用示波器或者逻辑分析仪看一眼波形比反复改代码快得多。4.5 显示与按键刷屏节奏和消抖LCD1602 刷新不能太频繁整屏重写一次大约几毫秒10ms 刷一次会占掉可观的时间片而且屏幕会闪。我的做法是内容变化才刷用一个静态缓存记录当前显示的两行字符新的字符串和缓存不一致才调写屏函数一致就直接跳过。这样正常运行时的刷新频率很低只有状态真正变化时才动屏幕。按键消抖用软件做10ms 扫描一次连续三次读到同一电平才认账按下沿触发一次动作松开之前不再响应。三个按键的优先级也要定清楚消毒键最高模式键次之手动开盖键最低。消毒键按下时如果盖子开着先发关盖指令等LID_CLOSED状态确认后再吸合继电器这个等待过程用一个中间状态实现不能在按键处理函数里原地等。显示内容建议两行分工明确第一行显示模式和盖子状态比如AUTO LID:OPEN第二行显示距离和满溢标志比如DIST:12cm OK。答辩演示时老师一眼就能看到系统当前在干什么比一堆调试信息有用得多。5. 避坑与常见问题排查调试台上最容易翻车的五件事5.1 超声波读数乱跳或者恒为 0现象屏幕上的距离值在 2cm 和 300cm 之间反复横跳或者一直显示 0、一直返回超时。原因三种可能。一是 Trig 脉冲宽度不够或者两次测量间隔太短模块内部还没准备好就收到下一次触发回波和前一次串在一起二是 Echo 接到了非 5V 容忍引脚电平被钳位捕获到的边沿位置失真三是供电纹波大电机或继电器动作时模块瞬间复位。解决Trig 脉宽给到 20μs两次测量间隔拉到 60ms 以上最好做成 100ms 定时触发Echo 必须接 FT 引脚模块 VCC 与 GND 之间就近并一个 0.1μF 加 10μF 电容。软件上再加一层中值滤波兜底。判断模块是否工作的土办法是对着墙面测读数稳定在墙距附近就说明硬件没问题剩下的是安装位置问题。5.2 红外在深色物体和强光下失灵现象白色纸巾靠近能开盖黑色垃圾袋靠近没反应或者白天正常晚上开日光灯就自己乱开盖。原因RPR220 是反射式红外深色物体反射率低接收管导通程度不够比较器翻转不了日光灯和部分 LED 灯含有 100Hz 调制成分被接收管当成信号输出跟着抖。解决硬件上把比较器阈值电位器往灵敏度高的方向调接收端并 0.1μF 电容做低通软件上做连续判定连续三次 10ms 采样都检测到物体才认账单次跳变直接丢弃。深色物体这个物理限制没法彻底消除可以在结构上把探头稍微下倾让探测区覆盖人的手而不是垃圾本身因为开盖的触发源本来就是人。5.3 电机一转单片机就复位现象盖子开始动作的瞬间屏幕黑掉或者花屏程序从头跑继电器也乱吸合。原因典型的电源跌落。电机启动电流是额定的好几倍和单片机共用一条 5V 轨走线又细启动瞬间把电压拉到 3V 以下单片机的掉电复位电路动作。地线布局也有关系电机电流从信号地回流抬高了单片机的地电位。解决电机和继电器单独走一路电源或者至少从电源入口单独拉一对粗线入口加大电容储能1000μF 起步地线做单点汇聚功率地和信号地只在电源入口处连一次软件上先关继电器再动电机避免两个大电流负载同时动作。改完以后用示波器看 3.3V 轨动作瞬间跌落不超过 0.2V 就算过关。5.4 语音模块不响或者只响一次现象第一次满溢能播报第二次就不出声了或者干脆一直没声音。原因一线串口没有等 BUSY 释放就发下一帧模块还在播上一条新指令被丢弃或者喇叭阻抗不匹配模块带不动再或者是供电不足WT588D 播放瞬间电流能到几百毫安从单片机 3.3V 稳压器取电会被拉垮。解决播报前先查 BUSY 脚为低就表示在忙此时要么等要么直接返回喇叭按 8Ω 0.5W 配语音模块单独从 5V 取电或者给 3.3V 稳压器加散热。还有个容易忽略的点语音地址烧录时要确认是从 0 开始还是从 1 开始编号地址差一位就是「放错音」听起来像芯片坏了。5.5 LCD1602 显示乱码或者全黑现象上电后屏幕全黑、全是一行方块或者显示几个乱码字符。原因八成是对比度没调好VL 脚的电位器拧到了极端其次是初始化时序不对LCD 内部复位需要 40ms 以上程序上电就发指令会被吞掉再次是四位模式的初始化序列必须严格按手册来先按八位发三次再切四位顺序错了后续全是乱码。解决先拧电位器看到字符轮廓再调清晰初始化前加 100ms 延时四位模式初始化序列照抄手册不要自己简化。RW 如果直接接地就别在代码里读忙标志改成固定延时等待否则会一直读不到应答卡死在那里。6. 验收与答辩一张测试用例表把功能讲清楚答辩现场最容易失分的地方不是功能没做完而是说不清「做完了什么、做到什么程度」。我的建议是提前做一张测试用例表每一行对应一条需求写清楚测试条件、操作步骤、预期结果和实测结果。老师翻到这一页基本就能判断你是真调过还是只焊了个板子。编号测试项操作预期结果判定依据T1自动开盖手在 20cm 内停留 1s1.5s 内开盖秒表计时重复 10 次T2延时关盖手离开桶口5s 后自动关闭秒表计时误差 ±0.5sT3防夹手开盖后手持续在探测区盖子不关闭持续 30s 观察T4满溢播报用纸板挡住探头至 8cm 内播报一次屏幕显示 FULL连续保持 30s 不重复播报T5解除满溢移开纸板至 11cm 外屏幕恢复 OK再次遮挡可再次播报T6消毒互锁开盖状态下按消毒键先关盖再吸合继电器观察继电器指示灯T7手动模式切到手动后靠近不开盖按键才开两种模式各测 5 次T8断电恢复运行中拔电再上电盖子闭合进入自动模式上电自检正常这张表的价值在于把「能用」变成「可测量」。比如 T2 的延时不能写「几秒后关闭」要写 5s ± 0.5s这样你才需要去测测了才发现原来的 5000ms 宏在 10ms 时间片下实际是 5.01 到 5.02 秒误差可以接受。T8 这条是很多人忽略的上电时如果盖子停在半开位置程序必须先执行一次关盖复位否则第一次使用就是错的。演示环节有三点经验。第一顺序上先演自动开盖和满溢播报这两个视觉听觉都明显的功能把评委的注意力抓住再讲硬件框图和状态机第二随身带一个备用舵机或者备用电机机械结构在搬运途中出问题是最常见的翻车方式第三主动说出方案的局限比如超声波在泡沫类垃圾上测距不准、深色物体红外灵敏度下降讲清楚你怎么规避的比被问出来强得多。从那以后我每次做带电机和继电器的板子都会在电源入口先并一个大电容、再单独拉一路功率地上电前用万用表量一遍地和电源有没有短路最后才敢插电。这套动作看起来笨但省下来的返工时间足够把状态机再打磨两轮。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。