1. 项目概述与核心价值如果你对Arduino、传感器和简单的机械结构感兴趣并且一直想动手做一个既有趣又有成就感的项目那么这个基于Arduino的糖果自动售卖机绝对是一个绝佳的选择。它不仅仅是一个“玩具”而是一个融合了电子电路、基础编程、简单机械设计和问题解决能力的综合性STEM实践项目。想象一下当你的朋友伸手到机器前机器就能“感知”到并自动吐出一颗糖果这种将虚拟代码转化为实体互动的过程充满了创造的乐趣。这个项目的核心逻辑非常清晰利用一个超声波传感器来模拟“投币”或“按钮”动作——当检测到前方特定距离内有物体比如手出现时Arduino主控板就会向伺服电机发送指令。伺服电机转动带动一个简单的齿轮或挡板机构将储存的糖果释放一颗通过滑道送到取物口。整个过程涵盖了输入传感器感知、处理Arduino判断逻辑、输出电机执行动作这三个自动化系统的基本环节是学习嵌入式控制和物联网入门的绝佳实体模型。无论是高中生用于科技节展示大学生用于单片机课程实践还是电子爱好者周末消遣这个项目都能提供从零到一的完整构建体验。它所需的材料常见且成本低廉代码逻辑直观机械部分鼓励你利用手边的材料如纸板、塑料盒进行创造和迭代。接下来我将带你深入每一个环节不仅告诉你“怎么做”更会详细解释“为什么这么做”并分享我在多次制作和教学中积累的那些容易踩坑的细节和技巧。2. 核心设计思路与物料选型解析2.1 系统架构与工作流程拆解在动手切割第一块纸板或焊接第一条导线之前我们必须先把整个系统的逻辑想清楚。一个可靠的自动控制系统其设计思路决定了后续制作的顺畅度和最终成品的稳定性。这个糖果机的核心工作流程是一个典型的“事件驱动”循环休眠待机系统上电后超声波传感器持续工作但Arduino程序处于监控状态伺服电机保持初始位置挡住糖果下落通道。事件触发当超声波传感器检测到前方一定距离内例如10厘米出现物体并持续短暂时间如0.5秒用于防误触发它认为这是一个有效的“取糖请求”。信号处理Arduino读取到传感器测得的距离值通过简单的if判断语句确认触发条件满足。动作执行Arduino向伺服电机发出指令令其旋转一个特定角度如90度。这个旋转动作会带动连接在电机轴上的齿轮或挡板打开一个缺口允许一颗糖果因重力作用落下。复位与等待电机在短暂延迟例如1秒确保糖果完全落下后反向旋转回初始位置重新挡住通道。系统返回步骤1等待下一次触发。这个流程的关键在于去抖判断和机械可靠性。传感器可能会因环境噪音产生瞬时误信号因此代码中必须加入延时确认。机械结构则需要确保每次动作只释放一颗糖果且不会卡住。2.2 关键物料清单与选型依据原教程提到了一个材料清单但有些地方比较模糊。这里我结合经验给出一个更详细、更具可操作性的清单并解释每样东西为什么需要以及有没有替代方案。电子部分Arduino主控板1个推荐Arduino Uno R3。它是学习入门的事实标准引脚布局清晰资料丰富USB编程方便驱动能力强。 Nano虽然更小巧便宜但需要额外的USB转串口线对新手稍不友好。微型伺服电机1个推荐SG90或MG90S。这类9克舵机扭矩足够推动小糖果价格低廉控制简单仅需一根信号线。务必注意必须选择180度标准舵机而不是连续旋转舵机。超声波传感器1个推荐HC-SR04。这是最普及的模块性价比极高。它需要两个IO口Trig触发Echo回响来工作。有更集成的型号但HC-SR04的教程最多。面包板与跳线若干用于搭建测试电路。建议使用400孔以上的面包板和公-公杜邦线。在最终组装时可以考虑焊接或用接线端子固定以提高可靠性。电源在测试和最终使用时切勿仅依赖电脑USB供电特别是当舵机动作时电流可能骤增。建议准备一个5V/2A的直流电源适配器搭配一个5.5*2.1mm的DC插座插到Arduino的电源接口上。这是系统稳定运行的关键。结构部分机体材料原教程用纸板这很好成本为零易于加工。但如果你想做得更精致耐用可以考虑3mm椴木板/亚克力板可以用激光切割机做出非常精准漂亮的零件强度远胜纸板。PVC板/泡沫板手工切割比木板容易强度也不错。废弃的塑料收纳盒现成的外壳只需开孔非常方便。储糖容器与滑道原教程用了鱼缸和漏斗这是一个巧思。关键在于接口要平滑防止糖果卡在衔接处。滑道原教程的C型通道的内壁一定要光滑。可以用硬质塑料片、亚克力条甚至将吸管剖开粘贴而成。滑道的倾斜角度需要测试通常在30-45度之间比较合适角度太小糖果滑不下角度太大会导致糖果速度过快飞溅。传动机构这是项目的灵魂。最简单的方式是直接在舵机摇臂上安装一个3D打印或激光切割的齿轮齿轮充当一个带缺口的转盘。糖果堆在转盘上方缺口转到下方时一颗糖果落下。你也可以用冰棍棒做一个简单的“闸门”机构。核心原则是运动部件摩擦力小动作行程精准。连接与固定材料热熔胶枪用于快速固定非承重部件、AB胶或UHU用于固定关键受力点如舵机底座、双面胶、螺丝螺母M3规格套装用于可拆卸的牢固固定。注意在物料选择上我的个人心得是“测试先行”。尤其是糖果不同糖果的大小、形状球形、片状、长条、表面光滑度有无糖粉对机械结构的要求天差地别。建议先确定你要用什么糖再根据它来设计滑道宽度和出糖口的大小。3. 机械结构设计与组装要点3.1 机体框架与储糖仓构建机体的主要作用是容纳所有部件、提供支撑并引导糖果。我们从一个简单的六面体纸箱开始设计。首先裁切出六块纸板构成一个长方体。关键尺寸不是固定的但需要遵循一个比例原则高度要能容纳你的储糖容器鱼缸/漏斗加上下方机械结构的空间宽度和深度要能稳妥放下Arduino和面包板并为滑道留出空间。我建议初始尺寸可以定为高25cm宽15cm深15cm。前面板是操作面需要预留传感器孔和出糖口顶部面板需要开一个足够大的圆孔用于安装漏斗。安装漏斗和储糖容器时密封和对准是重中之重。用热熔胶将漏斗颈部牢固地粘在顶板圆孔上确保周围无缝隙防止小糖果漏出。然后将鱼缸或其它容器倒扣在漏斗大口上。这里不要直接粘死我建议用几条宽胶带或可拆卸的卡扣固定方便日后补充糖果或清洁。你需要反复测试确保糖果能顺畅地从容器全部流入漏斗漏斗内部不应有能卡住糖果的凸起或狭窄处。3.2 出糖机构舵机与齿轮/挡板的设计这是整个机器最核心的机械部分其可靠性直接决定了用户体验是“惊喜”还是“故障”。方案一齿轮转盘式推荐这是最经典可靠的方式。你需要一个带有缺口的圆盘齿轮。这个缺口的大小略大于一颗糖果的尺寸。圆盘紧密安装在舵机输出轴上水平放置位于漏斗出口的正下方。在初始位置圆盘的实体部分挡住漏斗口。当舵机收到信号旋转90度时缺口旋转到漏斗口下方允许一颗糖果落下随后舵机回转90度实体部分又将出口封住。设计要点齿轮/转盘厚度最好有3-5mm太薄容易变形太厚可能增加阻力。缺口形状对于球形糖一个半圆形缺口即可对于方糖或长条糖可能需要设计一个方形的“仓位”。安装高度转盘上表面与漏斗出口的间隙应小于一颗糖果的直径防止一次掉多颗。这个间隙需要精细调整。固定方式舵机必须被极其牢固地固定。原教程用纸板做支架的思路可行但更好的方法是使用专用的舵机支架金属或塑料或用螺丝将舵机锁在一块坚实的基板上如小块木板再将这块基板粘在机体底板上。舵机在启动和停止的瞬间扭矩很大不牢固的固定会导致整个机构晃动甚至失效。方案二闸门式在漏斗出口处设计一个像门一样的挡板舵机通过摇臂带动挡板横向抽拉或上下起落从而打开或关闭出口。这种方式对糖果形状适应性更强。设计要点滑轨必须顺滑挡板与出口的配合要紧密且平整否则容易卡住。可以使用雪糕棒做导轨用塑料片做挡板。无论哪种方案组装后都必须进行空载测试和负载测试。先不通电手动拨动机构检查运动是否顺畅无阻碍。然后上电用程序控制反复动作几十次观察其一致性和噪音。最后放入糖果进行实际出糖测试。3.3 糖果滑道与收集槽制作滑道的作用是引导落下的糖果平稳地滑到取物口并降低其速度避免“喷射”出来。滑道宜采用光滑材料。将硬质塑料片弯折成“U”型或“C”型槽。其倾斜角度需要实验确定在机体框架内临时放置滑道从出糖机构处释放糖果调整角度直到糖果能自然滑下且终点位置合适。角度确定后在滑道下方用三角支撑纸板折成三角形进行多点固定防止因糖果冲击而变形。取物口处的收集槽可以简单地用一个裁剪后的酸奶杯或纸盒制作用热熔胶粘在机体前面板内侧开口与面板上的出糖孔对齐。确保收集槽有一定深度防止糖果跳出。4. 电路搭建与Arduino编程详解4.1 电路连接原理与实操电路部分非常简单但连接错误会导致传感器失灵或舵机乱转。我们使用面包板进行原型搭建。接线图文字描述电源总线在面包板两侧的垂直电源轨上一侧标为“5V”接Arduino的5V引脚另一侧标为“GND”接Arduino的任意GND引脚。HC-SR04超声波模块Vcc引脚 - 面包板“5V”总线。Gnd引脚 - 面包板“GND”总线。Trig引脚 - Arduino数字引脚D9。Echo引脚 - Arduino数字引脚D10。SG90伺服电机棕色线或黑色- 面包板“GND”总线。红色线- 面包板“5V”总线。橙色线或黄色/白色信号线- Arduino数字引脚D6。重要提示务必确保电源功率充足。将外部5V/2A电源适配器插入Arduino的DC插座。不要同时通过USB和DC插座供电。舵机的电源最好直接从面包板的5V总线取电而不是从Arduino板载的5V引脚取电以避免大电流冲击损坏Arduino主板。4.2 Arduino代码逐行解析与编写下面是一个稳定、带防抖功能的完整示例代码我将在注释中详细解释每一部分的作用和原理。// 引入舵机控制库这是Arduino IDE自带的无需额外安装 #include Servo.h // 定义引脚常量提高代码可读性和可维护性 const int trigPin 9; // 超声波触发引脚 const int echoPin 10; // 超声波回响引脚 const int servoPin 6; // 舵机信号引脚 // 定义运行参数这些是你可以根据实际情况调整的“旋钮” const int detectionDistance 10; // 触发距离单位厘米。手放到机器前10cm内触发。 const int debounceTime 500; // 防抖时间单位毫秒。手需要持续停留500ms才有效。 const int servoOpenAngle 90; // 舵机打开角度初始位置为0度 const int servoOpenDelay 1000; // 打开后等待糖果掉落的时间单位毫秒 // 创建舵机对象用于控制舵机 Servo myServo; // 变量声明 long duration; // 存储超声波传播时间 int distance; // 存储计算出的距离 bool handDetected false; // 标志位记录是否检测到手 unsigned long lastDetectionTime 0; // 记录上次检测到手的时间 void setup() { // 初始化串口通信用于调试可以在电脑的“串口监视器”查看数据 Serial.begin(9600); // 设置超声波模块引脚模式 pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); // 将舵机对象关联到控制引脚 myServo.attach(servoPin); // 初始化舵机位置到0度关闭状态 myServo.write(0); delay(500); // 给舵机一点时间归位 Serial.println(糖果售卖机初始化完成); } void loop() { // 步骤1: 触发超声波测距 digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); // 发出一个10微秒的高脉冲触发信号 digitalWrite(trigPin, LOW); // 步骤2: 读取回响脉冲的持续时间 duration pulseIn(echoPin, HIGH); // 步骤3: 计算距离声速约340米/秒除以2因为是往返距离 distance duration * 0.034 / 2; // 步骤4: 打印距离到串口监视器用于调试和校准 Serial.print(距离: ); Serial.print(distance); Serial.println( cm); // 步骤5: 判断逻辑带防抖 if (distance 0 distance detectionDistance) { // 如果检测到物体在设定距离内 if (!handDetected) { // 如果是刚检测到记录开始时间 lastDetectionTime millis(); handDetected true; Serial.println(检测到物体开始计时...); } else { // 如果已经处于检测状态检查持续时间是否超过防抖时间 if (millis() - lastDetectionTime debounceTime) { Serial.println(触发条件满足开始出糖); dispenseCandy(); // 调用出糖函数 handDetected false; // 重置标志位 } } } else { // 如果物体离开或不在范围内重置检测状态 handDetected false; } delay(100); // 主循环延迟降低CPU占用100ms的刷新率足够 } // 独立的出糖函数使主循环逻辑更清晰 void dispenseCandy() { Serial.println(舵机打开...); myServo.write(servoOpenAngle); // 舵机转到打开位置 delay(servoOpenDelay); // 等待糖果落下 Serial.println(舵机关闭...); myServo.write(0); // 舵机转回关闭位置 delay(500); // 等待舵机动作完成 Serial.println(一次出糖流程结束。); // 可以在这里添加其他效果如蜂鸣器响一声 }代码关键点解析防抖逻辑这是避免误触发的关键。代码不是一检测到距离小于10cm就立刻动作而是启动一个“计时器”lastDetectionTime。只有当物体持续停留在检测区内超过debounceTime500毫秒才判定为有效触发。这能过滤掉偶然经过的飞虫或短暂的挥手。pulseIn函数它用于测量echoPin引脚保持高电平的时间即超声波从发出到返回的时间。这个时间是计算距离的基础。millis()函数获取Arduino开机以来的毫秒数用于非阻塞式计时。相比delay()它不会让程序完全停止更适合需要持续监控的场景。模块化函数将dispenseCandy()独立出来使得主循环loop()非常简洁。如果你想修改出糖动作比如增加一段音乐或灯光只需要修改这个函数而不会影响主检测逻辑。4.3 系统集成与内部布局电路测试无误后就可以将电子部分移植到机器内部了。固定Arduino与面包板在机体底板或侧板规划好位置。可以使用尼龙扎带、螺丝配合铜柱或强力双面胶来固定。确保所有连接线不会被运动部件如舵机摇臂缠绕。传感器安装在机体前面板预先开好的孔中固定超声波传感器。可以用热熔胶从内部固定其四个角。确保传感器表面与前面板平齐且前方没有障碍物如玻璃否则会影响测距。走线管理用扎带或胶带将导线捆扎整齐避免杂乱。过长的导线可以盘绕起来固定。良好的走线不仅是美观更能防止日后因导线拉扯导致脱焊或接触不良。电源接入将外部电源适配器的线从机体后方或底部预留的孔穿入连接到Arduino的DC插座。确保电源线固定稳妥不会被轻易扯掉。5. 调试、优化与问题排查实录即使严格按照步骤制作第一次运行时也难免遇到问题。下面是我总结的常见故障及其解决方法相当于一份“维修手册”。5.1 机械部分常见问题问题糖果卡在出糖机构里下不来。排查首先断电手动转动舵机齿轮观察卡点。解决间隙调整检查转盘与漏斗出口的间隙。间隙太小会摩擦太大会一次掉多颗。用垫片或胶水微调高度。缺口尺寸缺口是否略大于糖果对于异形糖缺口形状可能需要优化。糖果本身糖纸是否粘连糖粉是否结块更换更光滑、独立的糖果如MM豆、小包装糖果是立竿见影的办法。问题一次掉出多颗糖果。排查观察糖果在储糖仓的状态。是否是“桥接”现象糖果互相卡住形成拱桥然后突然崩塌解决增加阻尼在漏斗颈部内部贴一小块柔软的海绵或毛毡增加糖果下落阻力。改进机构将简单的转盘改为“星型轮”结构每个凹槽只容纳一颗糖。控制存量不要一次性装满储糖仓保持半仓以下。问题舵机动作无力或发热严重。排查机械阻力是否过大齿轮或挡板是否刮擦到其他部件解决确保所有运动部件顺滑。可以在轴孔处涂抹一点润滑脂如凡士林。检查电源电压是否稳定在5V电流是否足够使用外接电源。5.2 电子与程序部分常见问题问题超声波传感器读数不稳定忽大忽小或一直为0。排查检查接线特别是Trig和Echo是否接反。观察传感器表面是否清洁。解决代码滤波在程序中加入软件滤波。例如连续读取5次距离去掉最大最小值后取平均作为最终结果。这能有效消除偶发干扰。int getAverageDistance() { int sum 0; int readings[5]; for (int i 0; i 5; i) { // ...这里插入上述测距代码将结果存入readings[i] delay(30); // 每次测量间隔一小会儿 } // 简单的排序去极值这里省略排序代码 // 假设去掉一个最高一个最低后取中间三个值的平均 sum readings[1] readings[2] readings[3]; return sum / 3; }硬件检查确保传感器供电电压为5V。如果导线过长尝试缩短或使用屏蔽线。问题手放过去没反应或离开后还在不停出糖。排查打开串口监视器查看实时距离读数。检查detectionDistance和debounceTime这两个参数设置是否合理。解决校准距离根据串口数据调整detectionDistance。如果取糖口较深可能需要设置为5-7cm。调整防抖时间如果环境有轻微干扰如风吹动适当增加debounceTime到800ms。如果觉得反应迟钝则减少到300ms。检查逻辑标志确保handDetected标志在出糖动作完成后被正确重置。问题舵机转到错误的角度或抖动。排查检查myServo.attach(pin)中的引脚号是否正确。检查电源。舵机信号线是否受到干扰如与电机电源线平行紧贴。解决为舵机单独供电仍共地。在Arduino的5V输出和GND之间靠近舵机的位置并联一个100μF以上的电解电容可以吸收电压波动立竿见影地消除抖动。5.3 功能扩展与美化建议基础功能实现后你可以考虑以下升级让项目更具挑战性和趣味性增加用户反馈视觉在面板上加一个LED。待机时呼吸闪烁检测到手时快速闪烁出糖时常亮。听觉添加一个无源蜂鸣器出糖时播放一小段旋律。代码实现只需在dispenseCandy()函数中加入控制LED和蜂鸣器的语句即可。计数与显示添加一个I2C LCD屏幕如1602实时显示“剩余糖果数量”或“今日已售”等信息。每出糖一次在代码中用一个变量减1并更新屏幕显示。多种触发模式除了超声波可以增加一个物理按钮实现“手动模式”。或者增加一个光敏电阻实现“天黑自动停止服务”的趣味功能。外观美化用彩色卡纸、贴纸或喷漆装饰外壳。用激光切割亚克力板制作一个更酷的前面板并丝印上Logo和指示灯标识。设计一个带坡度的屋顶让机器看起来更像真正的自动售货机。这个项目的魅力在于它有一个坚实可靠的核心但边界是开放的。从解决“如何让糖一颗颗稳定落下”这样的具体问题到思考“如何让它更智能、更美观”每一步都是学习和创造的过程。我自己的第一个版本也是用纸板和胶带做的粗糙但能动起来那种喜悦感是无与伦比的。后来迭代了三四版用了激光切割和3D打印增加了计数功能每一次改进都解决了之前遇到的一个实际问题。所以不要怕一开始做得简陋最重要的是动手做然后在玩的过程中你自然会知道下一步该优化哪里。