1. 项目概述与设计思路泡茶这事儿讲究起来挺麻烦的。水温、时间、茶叶量哪个环节差了点儿味道就天差地别。尤其是冲泡时间说好三分钟一转身接个电话就忘了回来茶汤又苦又涩白白浪费了好茶叶。市面上倒是有一些定时泡茶器但要么功能单一要么价格不菲最关键的是它们往往不够“听话”——没法灵活调整高度适应不同的杯具或者中途想改变冲泡时间也无能为力。于是我琢磨着自己动手做一个。我的核心需求很明确第一它得足够“聪明”能精确计时并自动完成茶叶的浸泡与分离第二它要足够“灵活”能轻松适配从马克杯到小茶壶的各种容器第三操作必须“直观简单”最好一只手就能完成所有设置另一只手还能空出来加水、拿茶叶。这就是“Teatimer 2.0”智能泡茶机项目的由来。它不是一个花架子而是为了真正解决日常饮茶中的痛点通过Arduino这个开源硬件平台将机械控制、人机交互和一点小小的自动化逻辑结合起来打造一个既实用又有趣的DIY智能家居小装置。整个项目的核心思路是构建一个以用户交互为起点、以机械执行为终点的闭环控制系统。用户通过旋转编码器这个“指挥官”输入指令设置高度、时间Arduino作为“大脑”处理这些指令并驱动伺服电机这个“手臂”执行升降动作同时通过LCD显示屏这个“嘴巴”实时反馈系统状态。如果需要还可以加上MP3模块这个“广播员”进行语音提示。这个流程清晰地将嵌入式系统的几个关键模块——输入、处理、输出、执行——串联了起来非常适合作为学习物联网和智能设备开发的入门实践项目。2. 核心组件选型与功能解析2.1 控制核心Arduino开发板为什么选择Arduino Leonardo在这个项目中主控板需要具备几个关键能力足够的数字I/O引脚连接多个外设、稳定的5V输出为传感器供电、以及可靠的PWM脉冲宽度调制信号输出以精确控制伺服电机。Arduino Leonardo完全满足这些要求。它基于ATmega32u4微控制器原生支持USB通信这使得它在连接电脑上传程序时更为稳定。相较于经典的UnoLeonardo的USB芯片直接集成在主控芯片内省去了额外的USB转串口芯片在需要用到硬件串口Serial1与MP3模块通信时避免了软件模拟串口可能带来的时序冲突和不稳定问题。注意如果手头只有Arduino Uno项目也能完成但连接DFPlayer Mini MP3模块时必须使用SoftwareSerial库来模拟串口因为Uno的唯一硬件串口RX/TX通常被用于程序上传和监控。这可能会在同时驱动伺服电机和刷新LCD时引入轻微的时序延迟或冲突需要更仔细的代码调试。2.2 人机交互界面旋转编码器与LCD屏旋转编码器KY-040是本项目交互的灵魂。它集成了旋转和按压两种操作。旋转用于无级调整数值高度、时间按压按下轴用于确认选择或进入下一菜单。这种交互逻辑非常符合直觉类似于老式收音机的调谐旋钮单手即可流畅操作。KY-040内部是两个机械触点旋转时会产生两路相位差90度的方波信号CLK和DT。通过检测这两路信号的先后顺序就能判断是顺时针还是逆时针旋转实现数值的增减。LCD 1602 I2C显示屏负责状态反馈。选择I2C接口版本是至关重要的简化步骤。传统的1602屏需要连接多达6根线RS, RW, E, D4-D7而I2C版本仅需4根线VCC, GND, SDA, SCL通过一个背面的小转接板与Arduino通信。这极大地节省了宝贵的I/O口并简化了布线。显示屏会清晰展示欢迎语、当前设置的高度、倒计时时间等信息让整个操作过程一目了然。2.3 执行机构伺服电机MG995伺服电机担任了“机械臂”的角色。伺服电机与普通直流电机的最大区别在于它可以接收PWM信号并精确地转动到指定的角度如0-180度。我们正是利用这一特性通过编程让电机转动特定角度从而带动连接在其轴上的“茶漏臂”升降到预设的高度。选择180度型号而非360度连续旋转型号是因为我们需要的是精确的位置控制而不是速度控制。MG995扭矩大约13kg/cm足以轻松提起装有茶叶和水的茶漏。关键参数调校伺服电机的控制信号是周期为20ms50Hz的PWM波其中高电平的脉宽在0.5ms到2.5ms之间变化对应着0度到180度的位置。在Arduino中我们可以使用内置的Servo库用servo.write(angle)命令轻松控制库函数会自动生成对应的PWM信号。但需要注意的是不同品牌、甚至同品牌不同批次的伺服电机其脉宽与角度的对应关系可能存在微小偏差。这就是为什么在项目后期需要进行MIN_HEIGHT和MAX_HEIGHT参数校准以确保机械臂的升降范围既满足使用需求又不会因过度转动而撞击外壳导致损坏。2.4 可选模块DFPlayer Mini MP3模块这是一个提升体验感的加分项。DFPlayer Mini是一个小巧而强大的MP3解码模块可以直接读取SD卡或TF卡中的音频文件并通过一个简单的串口指令集进行控制。我们用它来播放两段音频开机问候语和泡茶完成提示音。它的加入让这个DIY设备有了一丝“智能产品”的亲和力。接线时需特别注意其RX引脚接收端不能直接连接Arduino的TX引脚5V电平必须串联一个1kΩ的电阻进行限流以保护模块的输入引脚。3. 电路系统搭建与接线详解电路连接是整个项目的“神经系统”确保信号和电力准确无误地传递。虽然原理图看起来简单但实际动手时清晰的接线表和一丝不苟的操作能避免很多后续的调试麻烦。3.1 电源方案设计与避坑电源是首先要考虑清楚的问题。最初我尝试使用常见的9V方块电池或适配器为Arduino供电但遇到了显示异常的问题。LCD屏幕会闪烁甚至熄灭。经过排查和测量发现当伺服电机动作尤其是从静止状态启动时会产生一个较大的瞬时电流。Arduino板载的5V稳压芯片如AMS1117输出电流能力有限通常约800mA-1A这个电流冲击可能导致其输出电压瞬间被拉低造成连接在同一5V总线上的LCD显示屏因供电不足而复位或关闭。解决方案放弃从Arduino的VIN或电源接口输入高压再降压的方案改为直接使用5V/2A的USB电源适配器通过Arduino的Micro-USB口供电。这种方式的优势在于USB适配器本身提供了稳定且足额的5V输出Arduino板在此模式下更像一个“直通”的分配器其板载稳压电路不工作从而避免了电流瓶颈。实测证明这种方式非常稳定。你也可以选择使用一个外部的5V/3A开关电源同时为Arduino和伺服电机供电需共地但USB方案最为简便安全。3.2 分步接线实操与验证建议在将所有元件装入木盒之前先在面包板上完成所有连接并做初步测试。这能确保每个模块都是好的代码基本功能正常避免封装好后发现问题再拆解的尴尬。第一步连接旋转编码器将KY-040模块插入面包板。其五个引脚分别为CLK时钟、DT数据、SW开关、VCC、GND地。CLK- Arduino数字引脚11DT- Arduino数字引脚10SW- Arduino数字引脚3(注意该引脚需要在代码中启用内部上拉电阻)- Arduino5VGND- ArduinoGND第二步连接LCD I2C显示屏找到显示屏背面的I2C转接板通常是一个蓝色或黑色的小板它只有4个引脚GND- ArduinoGNDVCC- Arduino5VSDA- ArduinoSDA(在Leonardo上这是物理引脚2)SCL- ArduinoSCL(在Leonardo上这是物理引脚3) 连接后通电屏幕可能会亮起但无字符。这时需要找到转接板上一个很小的电位器通常用十字螺丝刀调节缓慢旋转它直到屏幕出现一排黑色方块或清晰的字符。这个电位器调节的是LCD的对比度电压。第三步连接伺服电机伺服电机通常有三根线颜色标准为棕色GND、红色VCC、橙色信号。棕色(GND)- ArduinoGND红色(VCC)- Arduino5V橙色(Signal)- Arduino数字引脚8第四步可选连接DFPlayer Mini MP3模块这是接线中最需要小心的一步。将模块插入面包板确保引脚没有短路。VCC- Arduino5VGND- ArduinoGNDRX- 串联一个1kΩ电阻后连接到Arduino的TX(引脚1)TX- Arduino的RX(引脚0)SPK1和SPK2- 连接到一个4Ω或8Ω的小扬声器两端。重要提示在连接MP3模块的RX线时务必串联那个1kΩ电阻DFPlayer Mini的RX引脚逻辑电平是3.3V而Arduino的TX输出是5V。直接连接长期使用可能会损坏模块。这个电阻起到了限流和分压的作用是必要的保护措施。完成所有接线后检查一遍是否有松动或短路。然后就可以通过USB线将Arduino连接到电脑准备上传程序了。4. 机械结构设计与组装工艺电路是项目的灵魂机械结构则是其骨骼和肌肉。一个稳固、精准的机械结构是泡茶机可靠运行的基础。我选择了木材作为主要材料因为它易于加工、成本低且外观有温暖的质感。4.1 木制外壳的加工与组装材料清单中给出了具体的木板尺寸你可以根据手头材料微调。核心是制作一个六面体的盒子前面板需要开多个孔洞。开孔规划与切割在前面板150mm x 200mm的板子上用铅笔精确标记出所有开孔位置。LCD方孔根据你的LCD屏实际尺寸通常是80mm x 36mm左右画框然后用线锯或曲线锯小心切割。孔可以比屏幕略小这样屏幕可以从背后安装并卡住。机械臂竖槽这是一个关键孔。它需要允许连接茶漏的臂上下自由运动。画一个宽约10mm高约120mm的竖长条形孔。这个孔的位置要居中偏上为下方的伺服电机留出空间。编码器圆孔在面板右下角便于右手操作钻一个直径约8mm的孔用于固定编码器的旋转轴。扬声器音孔在面板侧面或背面钻一系列小孔阵列组成音孔用于透出提示音。箱体组装使用直角夹辅助将底板、两个侧板、前面板对齐。先用细钻头如2mm在所有连接处预钻导引孔这能防止木头开裂。然后使用提供的4.5mm x 30mm自攻螺丝进行固定。先组装底板和两个侧板再固定前面板。热熔胶在这里可以作为辅助固定和密封缝隙的好帮手在螺丝固定前在接合处涂上热熔胶能增加强度并减少晃动。4.2 伺服电机支架与机械臂制作这是机械部分的核心目标是让伺服电机牢固地安装在箱体内并能平稳地带动机械臂升降。制作电机安装板切割一块PVC硬泡沫板或薄木板作为电机座板。将MG995伺服电机用附送的小螺丝固定在这块板上。然后切割四块小木块约15mm立方体作为电机座板与箱体之间的支撑柱。用热熔胶将这四块小木块粘在座板的四个角下方。安装与定位将组装好的电机座板放入箱内使其位于机械臂竖槽的正后方。通过竖槽观察调整座板位置确保未来伺服电机转轴的中心对准竖槽的中心线。位置确定后用热熔胶将四个支撑柱的下方粘在箱体底板上。为了更牢固可以在木块侧面也打上少量热熔胶使其与侧板粘连。制作与安装机械臂取一根5mm x 15mm x 230mm的木条作为主臂。在一端钻一个小孔用于悬挂茶漏钩在距离该端约30mm处钻一个与伺服电机舵盘固定螺丝匹配的孔通常是M2规格。关键步骤来了先不要将臂装上电机。给系统通电Arduino程序初始化后伺服电机会自动归中转动到90度位置。在这个位置将伺服电机的舵盘那个白色的塑料圆盘安装到电机轴上然后将木臂通过螺丝固定到舵盘上。此时臂杆的方向就是系统的“中间位置”。这样做的目的是让我们在软件中校准MIN_HEIGHT和MAX_HEIGHT时有一个明确的物理参考点避免机械臂在极限位置卡死。最终固定将连接好臂杆的伺服电机组件通过座板上的安装孔用3mm x 15mm的螺丝最终紧固在之前粘好的支撑柱上。确保所有螺丝拧紧但注意不要过度用力导致塑料舵盘开裂。5. 软件程序解析与关键代码逻辑硬件搭建完毕接下来就是赋予它“智慧”的软件部分。项目的核心代码逻辑清晰主要分为初始化、状态机循环、中断处理三大部分。5.1 核心状态机设计整个泡茶机的工作流程是通过一个“状态机”来管理的。状态机就像一个有多个档位的开关机器在任何时刻只处于一个特定状态并根据输入编码器动作切换到下一个状态。// 定义状态枚举 enum State { WELCOME, // 欢迎状态显示欢迎语 SET_HEIGHT, // 设置高度状态 SET_TIME, // 设置时间状态 BREWING, // 冲泡倒计时状态 TEA_READY // 完成状态 }; State currentState WELCOME;程序主循环loop()中通过一个switch-case语句来根据currentState执行不同的操作WELCOME状态显示欢迎信息播放欢迎音如果启用等待用户按下编码器。SET_HEIGHT状态显示当前臂杆高度值。旋转编码器可以增加/减少高度值该值会映射到伺服电机角度LCD实时更新。按下编码器确认高度并切换到SET_TIME状态同时伺服电机转动到指定高度。SET_TIME状态显示当前设置的冲泡时间秒。旋转编码器调整时间。按下编码器开始冲泡进入BREWING状态。BREWING状态开始倒计时。LCD显示剩余时间。此时依然可以旋转编码器来增加或减少剩余时间这是一个非常实用的功能让你可以灵活调整冲泡强度。如果减少到0则立即停止。倒计时归零后伺服电机缓慢抬起臂杆防止水花四溅播放完成提示音进入TEA_READY状态。TEA_READY状态显示“Tea is Ready!”。按下编码器返回WELCOME状态。5.2 旋转编码器中断处理为了实现流畅、无延迟的旋转检测我们必须使用中断。中断可以让Arduino在干其他事如更新显示时立即响应编码器的转动事件。// 引脚定义 #define ENCODER_CLK 11 #define ENCODER_DT 10 #define ENCODER_SW 3 // 变量声明 volatile int lastEncoded 0; // 必须用volatile因为在中断中修改 long encoderValue 0; void setup() { ... pinMode(ENCODER_CLK, INPUT_PULLUP); pinMode(ENCODER_DT, INPUT_PULLUP); // 为CLK和DT引脚附加中断当引脚电平变化时触发updateEncoder函数 attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), updateEncoder, CHANGE); attachInterrupt(digitalPinToInterrupt(ENCODER_DT), updateEncoder, CHANGE); ... } void updateEncoder() { // 读取两个引脚当前状态组合成一个2位二进制数 int MSB digitalRead(ENCODER_CLK); int LSB digitalRead(ENCODER_DT); int encoded (MSB 1) | LSB; // 与上一次状态组合成一个4位索引查表判断方向 int sum (lastEncoded 2) | encoded; if(sum 0b1101 || sum 0b0100 || sum 0b0010 || sum 0b1011) encoderValue; if(sum 0b1110 || sum 0b0111 || sum 0b0001 || sum 0b1000) encoderValue--; lastEncoded encoded; }这段代码是编码器解码的核心。它利用了KY-040旋转时CLK和DT输出波形相位差的关系通过一个状态查表法非常高效且去抖地判断出旋转方向并更新encoderValue变量。主循环中只需要读取这个变量的变化就能知道用户调整了多少“格”。5.3 伺服电机控制与高度校准伺服电机控制本身很简单但校准过程是保证机械可靠性的关键。#include Servo.h Servo myServo; #define MIN_HEIGHT 20 // 对应伺服电机角度下限臂杆最低位置 #define MAX_HEIGHT 85 // 对应伺服电机角度上限臂杆最高位置 #define START_HEIGHT 20 // 开机初始高度 int currentHeight START_HEIGHT; void setArmHeight(int height) { // 将高度值0-100映射到伺服电机角度MIN_HEIGHT - MAX_HEIGHT int angle map(height, 0, 100, MIN_HEIGHT, MAX_HEIGHT); // 限制角度在安全范围内 angle constrain(angle, MIN_HEIGHT, MAX_HEIGHT); myServo.write(angle); delay(15); // 给伺服电机一点时间转动到位 }校准流程实操在代码中先将MIN_HEIGHT和MAX_HEIGHT都设置为一个中间值例如60。上传程序通电。伺服电机会转到90度位置因为map函数将高度50映射到角度60接近90。通过编码器进入SET_HEIGHT状态尝试增加高度值。观察机械臂向上转动。当臂杆即将碰到外壳顶部或感觉电机堵转发出滋滋声时停止增加。记下此时LCD显示的高度值假设为85。尝试减少高度值直到臂杆到达最低的、不会碰到茶壶或杯底的安全位置记下此时高度值假设为20。将这两个值85和20分别更新到代码的MAX_HEIGHT和MIN_HEIGHT宏定义中。START_HEIGHT可以设为MIN_HEIGHT这样开机时臂杆处于收起状态。重新上传程序。现在高度调整的范围就被安全地限制在了机械结构的物理极限内。5.4 低功耗待机功能为了让设备更省电、更安全我加入了一个简单的待机功能。当设备在WELCOME状态无操作超过15分钟可通过#define INTERVALL_SHUTDOWN调整或者用户长按编码器2秒系统会进入“半待机”模式。void enterSleepMode() { lcd.noDisplay(); // 关闭LCD背光对于I2C LCD可能是lcd.noBacklight() myServo.detach(); // 断开伺服电机信号线使其停止供电并释放扭矩 // 注意Arduino本身仍在运行但功耗显著降低 } void wakeUp() { lcd.display(); // 开启LCD myServo.attach(SERVO_PIN); // 重新附着伺服电机 currentState WELCOME; }这个实现并非真正的单片机深度睡眠因为旋转编码器的中断检测需要MCU保持运行。但关闭显示器和伺服电机这两个“耗电大户”已经能让待机电流从约150mA下降到50mA以下对于长期插电使用的设备来说既实用又简单。6. 系统集成、调试与问题排查当所有硬件和软件模块准备就绪最后的集成与调试是项目成功的关键。这个过程就像组装一台精密钟表需要耐心和细致。6.1 分模块测试与联调不要急于把所有东西塞进盒子。遵循以下步骤基础系统测试仅连接Arduino、编码器、LCD。上传一个简单的测试程序确保编码器旋转能改变LCD上显示的数字按下编码器能切换模式。这验证了核心交互逻辑。伺服电机测试接上伺服电机。上传一个让伺服电机随编码器旋转而摆动的程序。观察运动是否平滑有无异响。同时用手轻轻捏住舵盘感受其扭矩是否足够MG995应该很有力。MP3模块测试可选接上MP3模块和扬声器。使用一个简单的串口测试程序发送指令让其播放SD卡中的特定文件。确保音频能正常播放音量适中。整体功能联调将所有模块连接好上传完整的“Teatimer 2.0”固件。按照设计流程操作一遍开机欢迎、设置高度观察臂杆是否跟随移动、设置时间、开始冲泡观察倒计时显示、完成冲泡观察臂杆是否自动抬起。检查每个环节是否顺畅。6.2 常见问题与解决方案速查表在实际组装和调试中你可能会遇到以下问题。这里提供一个快速排查指南问题现象可能原因排查步骤与解决方案LCD屏幕不显示或显示乱码1. 电源接触不良或电压不足。2. I2C地址不对。3. 对比度未调节。1. 检查5V和GND连接用万用表测量电压是否稳定在5V左右。2. 扫描I2C地址使用Wire库示例程序并在代码lcd.init()中更正。3.最重要调节LCD背面I2C转接板上的蓝色电位器直到字符清晰。旋转编码器操作无反应或跳变1. 接线错误特别是CLK和DT接反。2. 中断引脚冲突或未启用内部上拉。3. 机械编码器接触不良。1. 对照接线表检查CLK、DT引脚是否接对。2. 在setup()中确认引脚模式设置为INPUT_PULLUP。3. 尝试更换一个编码器模块。KY-040质量参差不齐。伺服电机不转动或抖动1. 电源功率不足。2. 信号线接触不良。3. 机械负载过重或卡死。1.最常见原因确保使用5V/2A以上的USB电源适配器供电避免使用电脑USB口或弱电源。2. 检查信号线橙色是否连接牢固。3. 断开机械臂空载测试电机是否正常转动。检查机械结构是否有阻碍。伺服电机转动角度不准确1.MIN_HEIGHT/MAX_HEIGHT参数未校准。2. 舵盘安装的物理零点不对。1. 严格按照第5.3节的校准流程重新校准极限角度。2. 断电手动将臂杆放到理想的最低位置然后装上舵盘确保此时在代码中write(MIN_HEIGHT)对应这个物理位置。MP3模块无声音1. RX引脚未串电阻或电阻损坏。2. 音频文件格式或命名错误。3. 音量设置为0或扬声器损坏。1.务必检查DFPlayer Mini的RX和Arduino的TX之间是否串联了1kΩ电阻。2. 确保SD卡为FAT32格式音频文件为MP3或WAV格式并命名为0001.mp3, 0002.mp3等。3. 在代码中调整MP3_VOLUME值范围0-30尝试直接短接扬声器到手机音频口测试扬声器。系统运行一段时间后复位1. 电源不稳定伺服电机动作时电压跌落。2. 代码中有内存泄漏或死循环。1. 再次确认并更换为更强大的5V电源如手机快充头。2. 检查中断服务函数updateEncoder()是否过于复杂或执行时间过长确保其中没有delay()或打印语句。机械臂运动不顺畅、有噪音1. 木制部件摩擦过大。2. 伺服电机轴与舵盘不同心。3. 螺丝拧得过紧导致部件变形。1. 在机械臂与外壳开槽的接触边缘涂抹一点蜡烛蜡或润滑脂。2. 重新安装舵盘确保安装平整螺丝不要一次拧死稍微留点活动余量再慢慢紧固。3. 检查所有木制结构是否因螺丝过紧而扭曲适当松解。6.3 最终装配与美化调试无误后就可以进行最后的装配了。将面包板上的电路用热熔胶或尼龙扎带妥善固定在箱体底部。USB电源线从后板预留的孔穿出。确保所有线缆都有一定的松弛度不会因为机械臂的运动而被拉扯。你可以根据自己的喜好对木盒进行打磨、上漆或涂木蜡油让它看起来更精致。在茶漏臂的末端可以安装一个小钩子或3D打印一个夹子用于悬挂不同样式的茶漏或茶包。完成所有这些你的智能泡茶机就正式诞生了。把它放在厨房或办公桌上享受一杯时间刚刚好的茶这份满足感远超茶汤本身。这个项目带给你的不仅仅是一个工具更是一次对嵌入式系统从感知、决策到执行完整链条的深度实践。