资讯详情

基于Arduino的智能泡茶机(1)——机械系机械创新比赛总结技术点与不足处

1.智能泡茶机项目需求

1.1.目标项目需求(总体:机械结构 电控)

  1. 机械为主,电控为辅。
  2. 突出机械创新点。
  3. 项目主要机械部分需要ANSYS有限元分析。
  4. 符合时代智能家居的理念。

1.2.作品完成后现有功能

  • 可以通过控制执行器完全泡茶。
  • 语音控制,按钮输入功能。
  • 设计一套符合型号的设计APP。
  • 语音提示。

2.泡茶机组件选型

元器件名称 数量 作用
MG995舵机 19 主要执行器控制泡茶机的动作
HC-05号蓝牙模块 1 在手机和单片机之间建立桥梁
跟踪避障模块 3 用于检测茶杯(人机交互)
水泵(接食用水) 1 抽水
继电器 1 用Arduino来控制水泵何时通电
手机 1 用于蓝牙连接、语音识别、触摸屏(按钮)
降压器(220V转5V) 1 传感器和执行器供电
Arduino Uno板 2 用于控制手、茶壶机械手
Arduino Mega板 1 主控板用于通信两外两Arduino Uno板
16路舵机驱动板 1 通过IIC通信驱动舵机减少了大量IO占用

注意:

  1. Arduino供电问题:Arduino供电问题:因为在泡茶及运行的时候,我们不可能说是把Arduino板连接在电脑上运行,所以我们这里的解决方案是用充电插头给它Arduino板供电,或使用稳压模块Arduino来供电。
  2. Arduino通信问题:在上述组件选择中,我使用了两个Uno板和一个Mega板,在通信上,我的思路是让Mega板作为上位机,其他板Uno板作为下位机,在通信上还是有一些问题的,比如通信上会有延迟,我们可以在这里使用它Arduino软串口可以解决通信延迟问题,但这个前提是你占用的IO不然一个软串口会占两个IO口的位置。因为我在设计的时候,IO它被广泛使用,所以我没有使用这个解决方案。或者你用两个Mega板替换你的两个Uno板,因为Mega板有四个通信口。

3.项目中需要使用的软件

软件名称 用途
Mixly(或中文称米思齐) 这是图形编程,用于传感器检测会快很多(这个软件是给孩子学编程的,所以……很简单)
Arduino 主要的Arduino假如你,编译器VS编译器里有Arduino模块也行
App Inventor 基于Java的一个APP制作网页(也有软件版,可以在中国大学慕课找到相关课程)
Fritzing 这是一个用于电路接线的软件
ANSYS 17.0 这是一个强大的有限元分析软件,用于材料应力分析等。(19版以上有中文,没学过专门课程很难用)

注意: 在控制方面,我们主要使用它Arduino来编程。 App Inventor是图形编程,使用起来比较简单。使用百度语音时,记得让手机联网,否则无法唤醒。 每次都有蓝牙Arduino复位后可能需要重新连接。

4、Arduino函数主要用于编程

4.1.舵机控制函数

在泡茶机中,我们主要的执行器就是MG955舵机。舵机有两种驱动方式:一种是使用Arduino自带的Servo二是使用第三方库Adafruit_PWMServoDriver.h。注意:不管你是你使用哪一种方式,delay函数只是给舵机足够的时间,并不是控制舵机转动时长。如果你要控制舵机请看4.2。

4.1.1、Servo库

Servo函数的主要成员(以下是Uno板为例)

函数名 用途
attach() 设置舵机接口,注意Arduino 0016前只能收到9和10引脚
write() 将舵机旋转到指定角度(只有0-180度)
writeMicroseconds() 写一个微秒在标准舵机中,参数设置为1000为完全逆时针方向,2000为完全顺时针方向,1500为中间。但不同的制造商可能会有所不同
read() 读取舵机当前角度,返回0-180度
attached() 传入一个Servo变量,判断是否附加在引脚上,然后返回true,否则返回false
detach() 将servo如果所有变量都与引脚分离,servo变量是分开的,第9和第10教会可以使用analogWrite()函数进行PWM输出

市面上的Arduino板的0-13引脚(共14路)可以接舵机。如果解决不了,可以参考4.1.2的16路du 注意:我们在这里主要使用的一些attach()、write()这两个函数。本项目不能使用其他函数。 例子:

  • 在全球定义中创造Servo 变量:Servo servo_9; //创造全局Servo 变量
  • 在Arduino的setup中初始化:servo_9.attach(9); //附加到Arduino的9号引脚
  • 发送PWM数据给9号引脚:servo_9.write(60); ///让舵机转60度
  • 给舵机足够的时间: delay(100); ///向舵机延迟100毫秒

4.1.2、Adafruit_PWMServoDriver.h库

注意:这个库是购买16路舵机驱动板时的芯片资料,我们拿到的一般是一个压缩包。这时需要先打开Arduino编译器的文件位置->libraries,然后再把压缩包放到libraries中。 左图为16路舵机驱动板。

在Adafruit_PWMServoDriver.h库中主要的函数如下

函数名 作用
Adafruit_PWMServoDriver(uint8_t addr = 0x40) Adafruit_PWMServoDriver库的构造函数,默认地址为0X40
begin(void) 启动函数,无参数
reset(void) 复位函数,无参数
setPWMFreq(float freq) 设置刷新频率,我这里使用的是60Hz
setPWM(uint8_t num, uint16_t on, uint16_t off) 发送off(脉冲长度计数)给16路舵机的num接口

注意:如果使用舵机驱动板的话还需要用到#include <SPI.h>和#include <Wire.h>,这两个库是Arduino的自带库(不需要额外下载的),他们是用于IIC通信时使用的。 例子:

  • 在全局变量中定义:Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0X40); //创建一个16路舵机驱动板变量
  • 在Arduino的setup函数中:pwm.begin(); //驱动板开启
  • 在Arduino的setup函数中:pwm.setPWMFreq(60); //模拟伺服系统以60赫兹的频率更新
  • 启动舵机:pwm.setPWM(0, 0, 600);
  • 给一定的时间延时:delay(100);

4.2、解决舵机运行速度和加速度的方式

对于不同厂家生产出来的舵机转速是有一定差异的,下面是我在一个淘宝卖家上的截图。

        我们可以看到在4.8V和6.V时的空载速度是不同的(单位是秒/60°)。随着舵机的规格不同,速度也是有些差异的。就拿上面的9KG铜齿舵机来说,4.8V时的空载速度为140ms转完一圈,那么大概就是2.4ms转一度。这也说明你给他140ms它能转一圈,但是你给它120ms的话它是不会转一圈的(即转速不会加快),除非是提高电压!同理,也不能说是给200ms它就会慢慢转,他只会用140ms,剩下的的60ms它只会在那边干等着。

此外,舵机也算是电机,只是他是一个特殊的电机(我们这里就把他看成是一个小型的电机),根据《执行元件及控制》中电机的特性曲线可以只知道电机在开始工作的时侯转速的偏慢的,那我们把电机映射成舵机的话,我们可以得出舵机小幅度转动的话旋转的速度是会更慢一些的。

所以,我们可以根据这两个特性来对将要旋转的度数进行划分。

下面我就用一个demo来描述一下舵机转速主要解决方式,这里我使用的是上文中第一种控制方式(使用Servo.h库函数),舵机选用上面9KG扭矩的舵机,接上4.8V电压让其空转。

#include <Servo.h>
Servo servo_2; 			//创建一个全局的Servo 变量
int Degree = 0;			//记录当前角度
int Target = 0;			//记录将要旋转的目标角度
int Velocity = 20;		//记录舵机每度的延时时间,可作为旋转速度
int Acceleration = 1;		//加速度
int readnum = 0;		//用于存储随机数
void setup(){ 
        
	servo_2.attach(2);	//这里我是使用2号引脚
}

void loop(){ 
        
	Target = random(1, 180);	//这里我随机产生一个随机数作为目标角度
	Degree = Run_Servo(Degree ,Target,Velocity ,Acceleration);	//获取当前角度
	delay(1000);			//延时1秒后进行下一次转动
}
//舵机执行函数,输入当前度数、指定度数,速度级别,加速度
int Run_Servo(int Deg,int Tar,int v,int a){ 
        
	int flag = -1;			//记录是要顺时针转还是逆时针
	int Decode_Motor_Degree;	//记录将要转动的度数
	int Variable = 0;		//两个度数差
	//做差值,求两角度的差值
	Variable = Deg - Tar;
	//判断角度差是正值还是负值,并且设立标志位
	if(Variable>=0){ 
        
		flag = 1;
	}else{ 
        
		flag = -1;
	}
	for(int i = 1; i <= Variable*flag; i++){ 
        
		Decode_Motor_Degree = Deg+i*flag;
		servo_2.write(Decode_Motor_Degree);	//这里就是让舵机一度一度的往上加
		//下面为每度的延时时长
		if(Velocity>3){ 
        
			delay(Velocity-a*i);
		}else{ 
        
			delay(3);
		}
	}
}

注意:我们必须要给系统留一些裕度,所以在舵机每度延时方面不能小于2.4ms,为了保证系统稳定性,我们最少设置为3ms。上面对加速度的处理方面,我只是提供一个比较简陋的处理方式,没有考虑到过多的细节,大家可以对此进行优化。

5、三个Arduino之间的通信问题与解决方案

        在项目初期,我原本打算使用单单一个Uno板来完成整个项目的控制,但是由于经验不足,对于16路舵机驱动板运用不够熟悉,还有在项目期间遇到很多无法解决的问题,所以就放弃了这个想法。相比之下,使用多块Arduino板来控制会相对简单很多。         到最后版本我选择使用一个Mege板外加两个Uno板,其中Mega板作为上位机,两个Uno板作为下位机。使用串口通信。

  1. 第一版解决方案:在一个Uno板在控制机械手的时候记录好自己所需要用的时间,Mega板作为上位机,给下位机发出信号后,自己进入延时来等待下位机完成动作。 遇到的问题:如果使用这一方案的话会需要花费大量的时间来记录Uno板每个动作的时间,且容错率低,这一方案会浪费大量时间。
  2. 第二版解决方案:给他们3个Arduino板一个共同的时间,来控制时间方面。 遇到的问题:对于这里方面没有花费过多的研究,但是让三个时间同步,可以使用Mega板IIC连接两个Uno下位机,但是对于Uno板的IIC地址和通信不是很懂,所以放弃了这一方案。
  3. 第二版解决方案:借用网络通信的三次握手理念,但是我这里有点改动,就是如果没有接收到下位机的回应就会一直阻塞等待。这样的一个好处就是防止上一个动作还没做完,其他机械手就开始工作了,这样很容易让机械手相撞。

6、注意事项和解决方法

  • 有时候代码没错,但是舵机动不了 解决方法(5种情况):
    • 用一个简单的舵机驱动测试一下那个舵机,是不是单独的那个舵机损坏问题(舵机明显发热等现象)。
    • 上面的如果没问题看看是不是舵机的输入电压不够(一般都是这个问题)。
    • 检查是不是16路舵机驱动板的问题(检查不动的那个舵机在舵机驱动板上的接口),看看那个16路舵机驱动板的输出口电压是否足够(5V左右的电压)?
    • 检查这个舵机所在的舵机驱动板,看看这个驱动板上有没有那种执行起来比较奇怪的舵机(这种舵机它旋转起来转起来感觉很丝滑,不会发出正常舵机的转动的声音),这种舵机会影响16路多级驱动板上其他舵机的信号!
    • 接线问题,看看是不是舵机的信号线接触不良引起的。
  • 舵机没有被卡住,但是抖动严重 解决方法(检验与排除): 看看连接在同一16舵机驱动板(或者是面包板)上的其他舵机又没右哪个卡住了,某一个卡住的话也会影响其他舵机,这明显的现象就是有的舵机剧烈抖动,但是没有卡住现象。

最后,我在这里总结一下,毕竟有的同学是和我一样使用220V转5V的,一般这种加压器的接线旁边是可以调节输出电压的(一个可以用螺丝刀调节的三极管),所以在使用之前一定一定要先测一下输出电压再接上电路。舵机短时间正负极接错是没有多大问题的,但是接个30s多半就废了。

标签: 11传感器插头mg641234

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台