基于Arduino的泡茶机器人

embedded/2024/10/17 21:44:49/

打造你的完美泡茶助手

引言

你是否曾遇到过泡出的茶太淡或太苦?通过这个项目,你可以创建一个设备,为你的茶包提供完美的浸泡时间。只需附上一个茶包并放置你的杯子,设备就会开始工作!它将完美地按照你的喜好浸泡你的茶。
实物图:
在这里插入图片描述
在这里插入图片描述

材料清单

  • 4毫米厚的木材
  • Arduino Uno
  • SG90伺服电机
  • 超声波传感器
  • Arduino电缆和软排线
  • 胶带
  • 双面胶带
  • 夹子(或其它小夹具)
  • 杯子

所需机器/工具:

  • 3D打印机
  • 激光木材切割机
  • 热熔胶枪

制作步骤

步骤1:切割木质基座

在这里插入图片描述

首先,我们需要一个基座来构建我们的泡茶机器。使用激光切割机切割4毫米厚的木材。

开始根据提供的模板激光切割4毫米木材。如果你的激光切割机支持svg文件,可以使用.svg文件。我也包含了原始的Adobe Illustrator文件,以防你的激光切割机需要特定的导出设置。

注意:附带的图片中的前面板没有为超声波传感器预留孔。但是.svg和.ai文件中为这个传感器预留了空间。

步骤2:组装木质基座

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

当然,在我们切割出木质模板后,我们还需要将其组装起来。

这一步你需要以下材料:

  • 胶带
  • 双面胶带
  • 步骤1中切割的木材
  • 热熔胶枪
  • 超声波传感器

首先,取“前面板”(带有两个小孔的面板),将你的超声波传感器“眼睛”插入孔中。然后使用一些热熔胶保持超声波传感器的位置。我不得不弯曲我的4个连接针脚,因为它们朝下。针脚应该像图片中那样朝外。

基座板
开始组装,在“基座1”模板顶部添加一些双面胶带。确保不要在圆形开口处粘贴胶带。

在“基座1”和“基座2”之间夹上双面胶带,然后将“基座2”板紧紧压在“基座1”板上。这将形成一个约8毫米厚的基座板,由两个基座板组成。

盒子
在组装基座板后,我们需要制作放在上面的“盒子”。首先取一个“侧板”并将其滑入基座板,另一侧重复此步骤。

现在插入带有已连接超声波传感器的前面板。你可能需要稍微抬起侧面以将其放入。

通过将“顶部”件放在侧面和前板上来组装屋顶。

你可以用一些胶带或热熔胶来固定“盒子”,具体取决于你的喜好。我使用了胶带将盒子的侧面固定在一起。

注意:完成所有这些步骤后,你应该还剩下一块木材,这块木材将在后面的步骤中使用。

步骤3:打印

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

现在我们想要打印一个保护和安装套件,用于我们的Arduino。下载并打印2个Arduino.stl文件,以获得套件的顶部和底部。

组装套件
首先将你的Arduino放入套件的底部部分。如果你有所需的螺丝,可以用螺丝固定,但我直接放了进去。然后取套件的顶盖,轻轻地将其放在底部盖和Arduino上,封闭套件。

对于我们的伺服电机,我们需要一些铰链系统来允许提起茶包。为此,请使用附件中提供的“臂”,“基座”和“盖子”.stl文件。

组装伺服铰链
首先取你的伺服电机,将其放入base.stl的合适插槽中。取cover.stl打印件并像图片一样放在基座上。我使用了双面胶带来固定它,但如果你有合适的螺母和螺栓,也可以使用它们。

在盖子上好后,你可以将臂部连接到基座上。为此,取下伺服臂,将大孔放在现在空的伺服臂连接部分上,然后轻轻旋转臂部,直到另一端适合基座孔。在它点击到位后,用螺丝将原始伺服臂连接到伺服上,并确保你得到所需的旋转,以不限制后续的旋转。

步骤4:电子设备

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

让我们使其移动。

这一步你需要以下材料:

  • 你的Arduino Uno及其套件
  • 超声波传感器(在前木板上)
  • 伺服电机
  • Arduino电缆和软排线
  • 双面胶带或热熔胶枪

电子设备
我们想要将Arduino Uno连接到伺服电机和超声波传感器。为了连接这些组件,我使用了第一张图片中提供的布线方案。

首先,将超声波传感器的GND和VCC引脚连接到Arduino的GND和3.3V端口。TRIG和ECHO引脚应按顺序连接到端口2和3。

你想将伺服电机的GND和PWR引脚连接到Arduino的5V和GND引脚。伺服数据应连接到引脚4。理想情况下,你只会将伺服PWR连接到外部电源,但在我的情况下,我不需要它。

代码

#include <Servo.h>
// pins
const int trigPin = 2; // trig pin for ultrasonic sensor
const int echoPin = 3; // echo pin for ultrasonic sensor
const int servoPin = 4; // pin for writing to servo// distance
float minCheckDistance = 2.0; // min check distance in CM
float maxCheckDistance = 8.0; // max check distance in CM
float echoDuration, distance;
float averageDistance[10] = {0};// servo
Servo serv;
const int minPos = 75; // servo maximum position while dipping
const int maxPos = 100; // servo minimum position while dipping
const int restingPos = 130; // servo resting position when not dipping
int targetPos = restingPos;
int pos = restingPos;// time
unsigned long time = millis();
unsigned long startTime = time;
unsigned long dipDuration = 60000; // duration of commenced dipping in milliseconds
bool dipping = false;
bool reset = false;void setup() {// enable pinspinMode(trigPin, OUTPUT);pinMode(echoPin, INPUT);serv.attach(servoPin);serv.write(pos);delay(300);
}void loop() {time = millis();// insert a distance into the arraydistance = checkDistance();for (int i = 0; i < 9; i++) {averageDistance[i] = averageDistance[i + 1];}averageDistance[9] = distance;// handle the setting down cup and removing it againif (checkAverageDistance()) {if (time >= startTime + dipDuration && dipping) {dipping = false;reset = true;} else if (!dipping && !reset) {startTime = time;dipping = true;}} else if (!checkAverageDistance()) {dipping = false;reset = false;}// handle servoif (!dipping) {targetPos = restingPos;} else {if (pos >= maxPos) {targetPos = minPos;} else if (pos <= minPos) {targetPos = maxPos;}}moveServo();delay(50);
}void moveServo() {if (pos < targetPos) {pos += 1;serv.write(pos);} else if (pos > targetPos) {pos -= 1;serv.write(pos);}
}float checkAverageDistance() {// check if the average distance in the last 10 echoes is still around our target (3 echoes or more)int avg = 0;for (byte i = 0; i < 10; i++) {if (averageDistance[i] <= maxCheckDistance && averageDistance[i] >= minCheckDistance) {avg++;}}return avg >= 3;
}float checkDistance() {// pulse the signal so we get echoesdigitalWrite(trigPin, LOW);delayMicroseconds(2);digitalWrite(trigPin, HIGH);delayMicroseconds(10);digitalWrite(trigPin, LOW);echoDuration = pulseIn(echoPin, HIGH);return (echoDuration * 0.0343) / 2;
}

这段代码为我们的泡茶设备提供动力,通过使用超声波传感器读取物体(茶杯)的距离,我们可以选择开始移动伺服电机。如果茶杯放在传感器前,伺服电机将开始在两个位置(minPos和maxPos)之间来回摆动,持续选择的时间(dipDuration)。如果杯子被移除,伺服电机将被告知返回到休息位置(restingPos)。通过改变这4个值(minPos,maxPos,dipDuration,restingPos),你可以告诉伺服电机浸泡的高度、低度、持续时间和不浸泡时的位置。

将代码更改为你首选的设置,并上传到你的Arduino Uno。

步骤5:手臂

在这里插入图片描述

对于设备的最后部分,我们需要一些东西来握住茶包。

这一步你需要以下材料:

  • 步骤1中的最后一块木材
  • 双面胶带
  • 胶带
  • 热熔胶枪
  • 夹子或其它小夹

完成结果

在这里插入图片描述
是时候测试你的泡茶助手了。

首先,将Arduino连接到电源。然后选择你最喜欢的茶叶,烧些开水,倒入杯中。使用夹子将茶包固定在泡茶机的臂上。然后,魔法就发生了。将你的杯子放在圆形的凹槽上,让它将茶包浸入杯中。

希望你喜欢这个项目,并在构建过程中找到乐趣!如果你有任何问题或需要帮助,欢迎在评论区交流。

作者:Svan.


注意:本博文为不得在未经本人同意进行转载或者二次创作,违者必究!!!


http://www.ppmy.cn/embedded/126875.html

相关文章

OceanBase管理着工具-oat安装

https://www.oceanbase.com/softwarecenter-enterprise https://www.oceanbase.com/docs/enterprise-oat-doc-cn-1000000000762607 (base) [rootlnpg soft]# pwd /db/ob/soft (base) [rootlnpg soft]# ll 总用量 4274536 -rw-r--r-- 1 root root 1730447360 6月 26 14:06 oa…

【深度学习】经典的深度学习模型-01 开山之作:CNN卷积神经网络LeNet-5

【深度学习】经典的深度学习模型-01 开山之作&#xff1a;CNN卷积神经网络LeNet-5 Note: 草稿状态&#xff0c;持续更新中&#xff0c;如果有感兴趣&#xff0c;欢迎关注。。。 0. 论文信息 article{lecun1998gradient, title{Gradient-based learning applied to document r…

【OceanBase诊断调优】—— 错误码 5065 和 5066 的区别

适用版本&#xff1a;V2.1.x、V2.2.x、V3.1.x、V3.2.x 5065 与 5066 是两个近似的报错。 OB_ERR_QUERY_INTERRUPTED(-5065): Message: Query execution was interrupted。 含义为执行中断, 例如终端执行 SQL 过程中按 ctrlc 终止 SQL 执行会报 -5065。 OB_ERR_SESSION_INTER…

Transformer总体架构

Transformer 一、Transformer架构解析1.1 认识Transformer1.2 Transformer总体架构 二、Transformer架构实现2.1 输入部分的实现2.1.1 文本嵌入层2.1.2 位置编码器 2.2 编码器部分的实现2.2.1 生成掩码2.2.2 注意力机制2.2.3 多头注意力机制2.2.4 前馈全连接层2.2.5 规范化层2.…

LeetCode 每日一题 2024/10/7-2024/10/13

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 10/7 871. 最低加油次数10/8 1436. 旅行终点站10/9 3171. 找到按位或最接近 K 的子数组10/10 3162. 优质数对的总数 I10/11 3164. 优质数对的总数 II10/12 3158. 求出出现两…

Vue3 props

组件与组件之间不是完全独立的&#xff0c;而是有交集的&#xff0c;组件与组件之间可以传递数据&#xff0c;通过props属性可以让子组件接收父组件传递过来的数据。 以父组件-App.vue&#xff0c;子组件-Person.vue为例&#xff1a; 将子组件当作HTML中的标签一样&#xff0c…

并发——笔试面试总结

1. 进程之间通信的途径有哪些&#xff1f;并说一下他们的通信机制原理 进程间通信的途径包括管道、消息队列、共享内存、信号量、套接字等&#xff0c;以下是几种常见的进程间通信方式及原理&#xff1a; (1) 管道(Pipe) 通信机制原理&#xff1a;管道是一种半双工的通信方式&a…

PE结构之绑定导入表

打印绑定导入表 //打印 绑定导入表 BOOL PrintBoundImport(__in char* m_fileName) {char* Filebuffer NULL;if (!GetFileBuffer(m_fileName, &Filebuffer)) return FALSE;PIMAGE_DOS_HEADER LPdosHeader NULL;PIMAGE_NT_HEADERS LPntHeader NULL;LPdosHeader (PIMAGE…