
说真的我还有点怀念当初那个手动掀盖的垃圾桶。但居家办公那阵子手边垃圾实在堆得太快每次扔垃圾都要腾出一只手按盖子久了真觉得烦。于是我就顺手用Arduino做了一个自动开盖的智能垃圾桶核心逻辑特别简单超声波传感器检测到人手靠近舵机把盖子顶开人走几秒后盖子自动合上。做完之后来我家的朋友几乎没有不好奇的。这篇文章我就把这套“基于Arduino的智能垃圾桶”完整的方案、硬件清单、接线方式、控制逻辑和调试过程全部写出来给想入坑的朋友一条可以直接照抄的路。这个项目非常适合刚接触Arduino的人它需要的零件少、逻辑不复杂、成本也很低一套材料下来基本几十块钱。做完之后你既能摸清传感器、舵机、串口调试这些基本功又能得到一个真正能放在家里用的东西不是那种“通电能闪灯就扔角落里吃灰”的板子。1. 方案设计动手之前先把这三个问题想清楚1.1 功能边界怎么定很多人一听到“智能垃圾桶”就想着把所有功能都塞进去自动开盖、湿度检测、满溢报警、语音提示、联网上报……我建议第一次做千万别这么干。功能越多出问题的可能性就越大而且很多功能对实际体验并没有质变。我给自己定的核心需求就两条手靠近开盖人离开后自动合盖。这个逻辑覆盖了90%的使用场景能把项目完成度做到非常高的水平。后续如果你想扩展再在稳定版本上慢慢加东西这才是效率最高的做法。1.2 为什么用超声波而不是红外垃圾桶的自动感应方案主要有三类红外反射、人体红外PIR、超声波测距。红外反射模块便宜且响应快但它有个明显的缺陷对光线敏感在强光下容易误触发而且黑色物体吸光厉害灵敏度会掉得很明显。PIR人体感应模块适合检测大范围的人体移动但它是“有人就持续触发”不太适合“伸手丢垃圾”这种精准场景误判率会偏高。超声波模块就没有这些问题。它自己发射声波并接收回波不受环境光影响不管手是深色还是浅色都能测到而且可以精确返回距离数值。我把HC-SR04测距触发阈值设在20厘米左右只有手伸到感应范围内才会开盖效果很稳定。1.3 整体结构传感器加主控加执行器这个项目的硬件链路非常简单清晰传感器HC-SR04超声波模块负责测出障碍物的距离主控Arduino Uno负责读取距离、做判断、发送控制信号执行器SG90舵机带动桶盖完成开合动作。整套系统不需要任何网络连接也不需要操作系统就是最简单的“感知—决策—执行”闭环。这也是Arduino项目最底层的思维方式你把这个链路吃透了后面再复杂的项目也是在这个基础上加模块而已。2. 硬件选型与材料清单2.1 主控板Arduino Uno够不够用Arduino Uno是绝大多数人的入门板主控芯片是ATmega328P工作频率16MHz数字IO口有14个其中6个支持PWM输出还带了6个模拟输入口。对智能垃圾桶这个项目来说Uno的IO口用掉一半都不到性能完全是溢出的。如果你手头有Arduino Nano或者Leonardo也可以直接替代接线逻辑完全一样。除非你想把垃圾桶变成联网设备、通过Wi-Fi上报状态那才需要考虑升级到ESP32或者ESP8266这两个板子自带无线功能适合后续做物联网扩展。这里多说一句在开始之前请务必确认一下IDE环境。Arduino IDE可以从官网下载版本稳定没必要追求最新版。如果你习惯用VS Code也可以安装Arduino扩展或者PlatformIO插件来替代默认编辑器代码编辑体验会好很多但对这个项目来说不是必需的。2.2 超声波模块HC-SR04的几个关键参数HC-SR04可以说是Arduino生态里最常见、也最便宜的测距模块核心参数如下工作电压5V静态电流小于2mA测距范围大概2厘米到400厘米测量精度能到0.3厘米左右模块上有四个引脚VCC、Trig、Echo、GND芯片里已经集成好超声波发射和接收电路我们只需要发一个触发信号再量一下回波的脉宽就行了。它的工作原理说起来不算复杂主控给Trig引脚一个至少10微秒的高电平脉冲模块内部就会发射一串40kHz的超声波同时把Echo引脚拉高超声波碰到障碍物返回模块收到回波后把Echo引脚拉低。所以Echo引脚高电平持续的时间就正好是声波往返的总时长我们拿这个时间就能算出距离。2.3 舵机怎么选扭矩和体积怎么平衡普通家用垃圾桶的桶盖重量都很轻用SG90这种9克级别的微型舵机就够了。SG90工作电压4.8V到6V扭矩大概是1.8公斤厘米左右对塑料或者轻质桶盖来说绰绰有余。如果你的桶盖比较重或者加了配重、保温层之类的结构那就建议换成MG995或MG996R这种金属齿轮大扭矩舵机不过它们工作电流会明显变大对供电的要求也更高可能就需要单独给舵机拉一路电源不能直接指望Arduino板载稳压器输出那么大电流。选舵机这里有个实用的经验宁可“分钟”一点预留给余量。舵机在堵转或带动重物的时候电流会飙升如果扭矩刚好卡在临界值那用起来就会时不时卡一下体验很糟糕。稍微选大一号反而省心。2.4 电源、外壳和其他配件材料清单我列一下基本都是平时做项目常用的Arduino Uno开板和USB数据线HC-SR04超声波模块SG90舵机一个5V 2A电源适配器建议用别指望USB供电带舵机面包板或者洞洞板杜邦线若干小螺丝、扎带、热熔胶枪外壳可以用快递纸箱、亚克力板或者3D打印外壳方面如果你的桶盖本身就是平面的直接用热熔胶把舵机固定在桶壁外侧就行简单粗暴。我个人建议不要把舵机直接粘死在桶身上最好做一个可以拆卸的小支架方便后续检修和换电池。关于这一点后面在组装环节还会详细展开。3. 组装与接线全过程3.1 超声波模块的安装位置超声波模块的位置非常关键它直接决定了感应的灵敏度和稳定性。我踩过的最大的坑就是把模块贴在垃圾桶正面偏下的位置结果每次弯腰靠近整个身体都进了感应区还没伸手盖子就开了然后人一直站在那里它就开开关关反复“抽风”。后来我把模块调整到桶盖前方偏上的位置设置成向下倾斜大约30度让它只感应到“手伸过来”这个动作误触发一下就少了很多。如果你用的是那种带盖的敞口垃圾桶模块可以放在桶盖前侧边缘探头方向朝斜上方如果是按压式或者翻盖式的桶就需要根据实际结构调整方向。核心原则是感应区域应该刚好覆盖手的落点而不是覆盖整个人体。这里提醒一下超声波模块的发射和接收探头必须保持清洁也不要被标签、胶带贴住那会严重衰减声波信号。3.2 舵机与桶盖的机械连接舵机的输出轴是旋转运动而桶盖需要的是开合运动这两者之间需要一个传动结构。最简单的办法是舵机摇臂上装一根连杆或硬铁丝另一端固定在桶盖上舵机旋转时连杆就会把盖子顶起来或拉回去。我用的是一个废弃的亚克力小圆片做连接件中间打孔套在舵机输出轴上另一头穿了一根铁丝钩在桶盖边缘。推荐动手能力强的朋友直接用3D打印做一个带安装孔的塑料拉杆看起来更整洁也没有铁丝钩松脱的烦恼。要注意的是舵机的初始角度一定要先标定。一般SG90在90度位置是水平臂你需要先让摇臂归中再连接桶盖机构否则开合角度会偏移很厉害。3.3 电气接线与供电方案接线这部分非常简单我就按Arduino Uno来写HC-SR04的VCC接Arduino的5VHC-SR04的GND接Arduino的GNDHC-SR04的Trig接数字口D9HC-SR04的Echo接数字口D10SG90舵机的信号线接数字口D6SG90舵机的电源线通常是红色接5V供电SG90舵机的地线通常是棕色接GND。注意这里最值得说的是供电问题。SG90标称工作电流在空载时只有几十毫安但一旦负载上去、特别是刚启动的瞬间电流峰值能到数百毫安甚至更高。如果你直接把舵机接在Arduino板子的5V引脚上而这个引脚供电来自USB口USB的500mA限制很容易被突破结果就是Arduino突然重启舵机像抽筋一样抖动。我的建议是不要用USB口供电直接用一个5V 2A的电源适配器给Arduino的DC口供电或者更稳的方案是给舵机单独用一块5V升压模块供电Arduino和传感器用一路舵机单独用一路共地就行。共地这件事千万别忘两个电源如果不共地舵机根本不会工作。4. 核心程序与控制逻辑这一步是整个项目的灵魂。硬件装好了如果程序逻辑写得稀烂那垃圾桶还是不会听话。我会先把原理讲清楚再给出完整代码。4.1 HC-SR04测距原理与距离换算在代码层面测距分三步第一步让Trig引脚输出一个至少10微秒的高电平脉冲超声波模块被触发后会自动发出8个40kHz的声波脉冲。第二步用pulseIn函数测量Echo引脚高电平持续的时间这个时间就是声波从发射到返回的总耗时单位是微秒。第三步用公式换算距离。声波在空气中的传播速度约为340米每秒也就是0.034厘米每微秒。因为声波走了两趟去和回所以实际距离等于总耗时乘以0.034再除以2。如果直接用公式代码是distance duration * 0.034 / 2。还有一个更常用的近似算法是distance duration / 58.2这个数字是通过精确声速推导出来的经验常数用起来更简洁也够准确。有个细节容易被忽略Echo输出电平是5V但有些老版本的模块上Echo返回的是5V信号接在部分3.3V单片机上需要分压。Arduino Uno的IO口兼容5V这个问题不用操心但如果你换到ESP32或者其他3.3V板子上一定要加一个分压电阻或者电平转换电路否则有烧引脚的风险。4.2 开盖与关盖的状态机逻辑整个控制逻辑可以看成是一个简单的状态机包含三个状态待机、开盖、延时关盖。待机状态下系统不断测量当前距离。如果测得距离小于阈值比如20厘米说明有人伸手过来了就进入开盖状态在开盖状态下先让舵机转到打开角度然后进入一个持续延时比如4秒延时结束后再让舵机转回关闭角度回到待机状态。这里有一个很容易做错的细节在延时阶段超声波还在不断测量。如果人一直把手放在那里距离一直小于阈值你会希望盖子一直保持打开而不是强行关上。所以代码里要处理成“有障碍物就重置延时计时”延迟时间从最后一次检测到人的那一刻开始算这样体验才是最自然的。4.3 防误触、防抖动的细节处理实际使用中HC-SR04的读数偶尔会跳变。比如突然蹦出一个30厘米的数据然后又跳回正常。如果程序对每一次读数都马上去做判断那就有极小概率会出现盖子莫名其妙开一下又关的“灵异事件”。解决办法是做一个简单的滤波连续多次测量只有当连续几次都低于阈值时才真正触发开盖动作同理连续几次都高于阈值时才执行关盖。这个做法类似按键消抖逻辑不复杂但能挡掉绝大多数干扰。另外传感器第一次上电时前几次测量数据可能不准因为声波在探头附近还有余波。我习惯在setup阶段先执行几次测距并丢弃等数据稳定了再进入主循环。延时关盖的时间也值得调一下。我个人试下来4秒比较舒服扔完垃圾转身走开盖子刚好在你后脚离开时合上不会夹到你也不会开太久。4.4 完整代码可直接抄作业下面是我这个项目使用的完整代码已经加好注释你直接复制到Arduino IDE里编译上传就能跑#include Servo.h // 引脚定义 const int trigPin 9; const int echoPin 10; const int servoPin 6; // 阈值参数单位厘米 const int triggerDistance 20; const unsigned long closeDelayMs 4000; // 舵机角度参数 const int servoClosedAngle 90; // 合盖时的角度 const int servoOpenAngle 10; // 开盖时的角度 Servo myServo; unsigned long lastActiveTime 0; bool isOpen false; // 连续测量滤波参数 const int filterCount 3; const long filterMinTime 20; // 当连续filterCount次低于阈值才触发 long readDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration pulseIn(echoPin, HIGH); long distance duration * 0.034 / 2; return distance; } void setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); myServo.attach(servoPin); myServo.write(servoClosedAngle); // 上电预热丢弃前几次不稳定的测量值 for (int i 0; i 5; i) { readDistance(); delay(50); } Serial.println(Smart Trash Can Ready!); } void loop() { long distance readDistance(); Serial.print(Distance: ); Serial.print(distance); Serial.println( cm); bool personDetected (distance triggerDistance); // 简单的连续滤波连续三次检测到人才认为真的有人 static int detectCounter 0; if (personDetected) { detectCounter; if (detectCounter filterCount) { detectCounter filterCount; } } else { detectCounter 0; } if (detectCounter filterCount) { // 检测到人开盖如果还没开 lastActiveTime millis(); if (!isOpen) { myServo.write(servoOpenAngle); isOpen true; Serial.println(Open!); } } else { // 没检测到人且盖子已经打开 if (isOpen) { // 只有超过设定的延迟时间才关盖 if (millis() - lastActiveTime closeDelayMs) { myServo.write(servoClosedAngle); isOpen false; Serial.println(Close!); } } } delay(100); }这段代码的逻辑很直白主要就是维护一个isOpen状态防止每次循环都重复输出舵机指令。注意我把延时关盖的判断放在“没检测到人”的分支里所以人一直站在旁边的话lastActiveTime会一直被刷新盖子就不会强行关闭。4.5 使用模拟器和替代开发环境这个项目在实体硬件上跑起来之前强烈建议先用仿真平台验证一遍代码逻辑。Wokwi是目前体验最好的在线Arduino仿真工具它支持Arduino Uno、ESP32、屏幕等各种外设直接在浏览器里就能搭出“超声波模块加舵机加Uno”的电路图烧录代码后能实时看到舵机转动和串口输出对学习阶段来说非常方便。如果你实在不想用官方IDE也可以用VS Code加Arduino扩展或者PlatformIO框架项目管理能力强不少但对这个项目来说有点杀鸡用牛刀。我用仿真平台验证逻辑后才把程序烧到实体板上结果几乎没有一次失败。建议你也养成这个习惯硬件在外、逻辑在里的时候先用仿真调好能省下大量重复插拔线材的时间。5. 调试实录与常见问题排查5.1 现象一串口监视器里距离乱跳这是最典型的HC-SR04问题。如果你发现距离读数不稳定、忽大忽小大概率是以下几个原因模块供电不稳。如果用的是USB口供电加上舵机已经开始动了电压波动会直接影响超声波模块的测量稳定性。解决方法是换供电方式或者单独给模块用电容滤波。接近障碍物角度太倾斜。超声波在斜入射的时候回波信号衰减非常严重读数就会跳动。所以探头正前方尽量留出平整的反射面。环境中有其他超声波噪声干扰。这个在室内不常见但如果你旁边也有人在调试同类模块可能互相干扰。排查方法很简单先用Serial.println把测距输出打出来观察一下数据跳动的规律再对照上述原因逐项排除。我在实测中发现只要供电稳住读数基本上能稳定在正负1厘米以内。5.2 现象二舵机不转或者抖动舵机不转先检查三根线的顺序。SG90的三根线颜色分别是红色VCC棕色GND橙色或黄色信号线接错基本会烧毁舵机所以接线前一定多看一眼。舵机抖动九成情况是供电不够。前面已经强调过舵机启动瞬间电流比你想象的大很多。我一开始用USB供电舵机一转Arduino就重启串口监视器疯狂打印“Distance: xxx”。后来换成5V 2A适配器一切正常。还有一个容易忽略的点舵机长时间堵转会导致内部齿轮磨损甚至烧坏驱动芯片。如果你的桶盖卡住导致舵机无法转到目标角度输入电流会一直居高不下几分钟就可能报废一个舵机。所以机械结构尽量顺畅不要让舵机硬顶着干活。5.3 现象三桶盖合不上或者开盖太慢这种情况多数不是舵机的问题而是机械连接的问题。铁丝绑得太松舵机都转到位了连杆还有一大截空程盖子当然纹丝不动太紧的话舵机转起来又费劲速度也就慢了。解决方案是调整连杆长度让它在开盖和合盖两个极限位置都能刚好拉紧。建议加一个弹簧缓冲弹簧的一端连接桶盖另一端连接舵机摇臂这样即使机械机构有一点误差弹簧也能把运动补偿掉开合会顺滑很多。5.4 实测效果与参数微调我的完整测试流程是这样的距离阈值先设30厘米站在桶前测试感应范围如果发现人还没伸手就开了就慢慢把阈值往下调最后确定为20厘米。关盖延迟也测试过2秒、4秒、6秒三档2秒太急促扔完垃圾转身还没离开盖子就压上来了6秒有点磨叽总感觉在等待什么4秒最自然。感应范围方面我通过调整模块的角度实现了“手伸到桶口上方才能触发”的效果。具体操作是先让模块仰角大一点站在垃圾桶正面稍远处观察串口距离值然后用手模拟扔垃圾动作确认手到哪个位置才会进入到阈值之内。调整角度后感应区域就非常合适了。如果你做的垃圾桶是放在桌面上的感应距离可以再调小一点避免人从旁边经过时误触发如果放在客厅角落阈值可以适当调大让感应更灵敏。总之阈值这东西没有绝对的正确值只有适合你场景的值。5.5 从原型到稳定版的小技巧原型阶段用面包板是非常方便的但面包板最大的问题是接触不良。如果你发现数据偶尔不稳定先怀疑是不是杜邦线松了。长期使用的话我建议你把电路焊到洞洞板上或者直接定制一块PCB把模块和舵机接口都做成插拔式维护起来也方便。外壳方面热熔胶虽然方便但夏季高温环境容易软化如果你放在厨房附近时间长了胶体可能会松脱。我后来用扎带加小螺丝固定舵机牢固程度就完全不一样了。当然如果你有3D打印机直接打印一个集成了模块安装槽和舵机支架的外壳那是终极解决方案。这个项目做到最后我终于理解了为什么很多老手反复强调“完成比完美重要”。一开始我只想做一个自动开的盖子做完之后又想着加满溢检测、加语音提醒、加联网状态上报后来冷静下来发现当前这套“超声波检测加舵机开合”的核心体验已经非常实用了。后续的扩展打算也很明确先在桶盖内侧装一个限位开关检测盖子有没有盖到位再加一个压力传感器判断桶内剩余空间如果还有余力再考虑把状态上报到手机。一步一步来比一开始就追求高大上要靠谱得多。