前面写了三篇文章,讲解了如何用 LabVIEW
可视化界面,方便直观高效地确定出 Arduino 编程时所需的参数。这些参数包含有搬运车夹持器爪子张合角度;直线导轨上夹持器的升降高度和速度;以及小车走直线时的左右电机 PWM
值。这三篇文章的题目是:《 Makeblock
搬运遥控车之夹持器控制》,《 Makeblock
搬运遥控车之直线导轨控制》和《 Makeblock
搬运遥控车之车身行动控制》。 下面就要谈谈如何用 SONY PS2手柄来遥控这个 MakeBlock搬运车。这些确定好的重要参数,直接会用到遥控车的 Arduino程序中,比如向前拨动手柄摇杆,小车左右电机按照事先设定好的 PWM值,能向前走出直线。按下手柄某个按钮,夹持器的爪子收紧到规定角度,刚好紧紧抓住物料。 SONY PS2手柄来遥控 MakeBlock搬运车全景图如图 1所示。
图 1 SONY PS2手柄遥控 Makeblock搬运遥控车全景图
PlayStation 2,简称 PS2,是日本 Sony旗下的索尼电脑娱乐 SCEI(Sony Computer Entertainment Inc.),于 2000年 3月 4日推出的家用型 128位游戏系统,这套系统里就包含 PS2电玩手柄。这个作品就是想把平时我们用来玩电子竞技游戏的输入设备,用到遥控这台 MakeBlock搬运小车。
要应用 SONYPS2电玩手柄遥控小车,首先要了解 SONY PS2手柄是如何应用到 Arduino控制器中的。
图 2 基于 PS2手柄的遥控器组成
图 2中,基于 PS2手柄的遥控器组成有 SONYPS2电玩手柄,手柄接收器, ArduinoUNO控制器, XBee无线数传, 8.4V锂聚合物电池。这个遥控器经过了两次无线数传,才把手柄上的操作命令传递给被控搬运车的 Arduino MEGA2560控制器。一次是 SONY手柄通过红外信号把信息传递给它的自带红外接收器,二次是与红外接收器相连的 Arduino UNO控制器通过 XBee无线数传模块传递给小车上的 ArduinoMEGA2560控制器。之所以不把 SONY手柄红外接收器直接连到 Arduino MEGA2560控制器,可能是因为红外接收器的工作电压为 5V,而搬运车上 Arduino MEGA2560控制器数字端口的电压,我用稳压扩展板调成了 6V(这个电压更适合给小车上的舵机供电),总之采用一次无线通信的方法是不成功的。
红外接收器如何用杜邦线连接到 Arduino UNO控制器?请按照下面接线示意图,从 PS2手柄接收器的 9个引脚中找出 6个引脚 用六根杜邦线 与 Xbee传感器扩展板的 10、 11、 12、 13数字端子以及 3.3V、 GND端子连接起来,就可以实现 Arduino控制器与 PS接收器的硬件联系。对于实现这样的硬件联系, Xbee传感器扩展板非常好用,因为它具有 3.3V的端子,而且所有端子都是插针,方便用现成的杜邦线连接。
图 3 PS2红外接收器与 Arduino控制器连线示意图
不仅硬件连线方便,而且使用专门为 PS2X_lib库文件,编写程序也特别简单。
PS2X_lib库文件的 zip文件请下载: http://yunpan.cn/QNUdyd3E27jz7(访问密码: 2c9c)
可以将 zip文件下载并解压缩后,复制到 Arduino安装目录下的 libraries文件夹里面。然后在程序里就可以引入 PS2X_lib库文件,并直接使用这个库文件中的函数,采集手柄操作信息了。
图 4 PS2电玩手柄
图 4电玩手柄遥控操作方法:按下 PS2手柄前端的 R2按钮时,搬运小车驱动电机设置高速,按下 PS2手柄前端的 L2按钮时,驱动电机设置低速。 PS2手柄的 circle按钮按下时,设置舵机角度为 120度,夹持器处于打开状态, Rectangle按钮按下时,设置舵机角度为 16度,夹持器处于夹紧状态。 Triangle按钮处于按下状态时,每 0.05s以舵机角度加 4度的速度打开夹持器, error按钮处于按下状态时,每 0.05s以舵机角度减 4度的速度夹紧夹持器。上下拨动 PS2手柄左摇杆,控制夹持器升降电机正转或者反转,使夹持器下降或者上升。上下左右拨动 PS2手柄右摇杆,则控制搬运车前后左右行驶。
遥控器主机程序:
//程序任务:PS2手柄数据采集,发送给搬运车接收机
//电机速度程度、小车行驶方向、升降电机转向、舵机角度信息。
#include <PS2X_lib.h> //声明PS2X库文件
PS2X ps2x; // 定义ps2x为PS2X类变量
int speed_flag=1;//电机速度程度标识,1为高速、0为低速
int PS_LY;//PS2手柄左摇杆Y轴数据
int PS_RY;//PS2手柄右摇杆Y轴数据
int PS_RX;//PS2手柄右摇杆X轴数据
int servo_angle=90; //初始化舵机角度为90度
//初始化
void setup(){
Serial.begin(9600); //启动串行通信
//初始化PS2与Arduino控制器接口
ps2x.config_gamepad(13,11,10,12,true, true);
}
//主程序
void loop(){
ps2x.read_gamepad();//读PS2数据
//如果按下PS2手柄前端的R2按钮时
if(ps2x.NewButtonState(PSB_R2))
speed_flag=1;//搬运小车电机设置高速
//如果按下PS2手柄前端的L2按钮时
if(ps2x.NewButtonState(PSB_L2))
speed_flag=0;//搬运小车电机设置低速
//如果PS2手柄的circle按钮按下时
if(ps2x.NewButtonState(PSB_RED))
//设置舵机角度为120度,夹持器处于打开状态
servo_angle=120;
//如果PS2手柄的Rectangle按钮按下时
if(ps2x.NewButtonState(PSB_PINK))
//设置舵机角度为16度,夹持器处于夹紧状态
servo_angle=16;
//如果PS2手柄的Triangle按钮处于按下状态时
if(ps2x.Button(PSB_GREEN))
{
if(servo_angle>=16)
{
//每0.05s,以舵机角度加4度的速度打开夹持器
servo_angle=servo_angle+4;
if(servo_angle>120)
servo_angle=120;
delay(50);
}
}
//如果PS2手柄的error按钮处于按下状态时
if(ps2x.Button(PSB_BLUE))
{
if(servo_angle<=120)
{
//每0.05s,以舵机角度减4度的速度夹紧夹持器
servo_angle=servo_angle-4;
if(servo_angle<16)
servo_angle=16;
delay(50);
}
}
//把PS2手柄左摇杆Y轴数据读到变量PS_LY
PS_LY=ps2x.Analog(PSS_LY);
//把PS2手柄右摇杆Y轴数据读到变量PS_RY
PS_RY=ps2x.Analog(PSS_RY);
//把PS2手柄右摇杆X轴数据读到变量PS_RX
PS_RX=ps2x.Analog(PSS_RX);
//把PS2手柄操作数据从遥控器发到搬运车的接收端
Serial.write(0xff); //发送数据开始传送的标识字节
//发送搬运小车的电机速度程度标识
Serial.write(speed_flag);
//发送用于判断夹持器升降电机是正转还是反转的数据
Serial.write(PS_LY);
Serial.write(PS_RY); //发送用于判断搬运车是前进还是后退的数据
Serial.write(PS_RX); //发送用于判断搬运车是右转还是左转的数据
Serial.write(servo_angle);//发送实时舵机角度字节
delay(100); //等待数据发送成功
} 复制代码
被控搬运车从机程序:
/*程序任务:接受遥控器发送的数据,并控制小车行驶、夹持器的升降。
夹持器夹紧程度。*/
#include <Servo.h> //引入舵机头文件
Servo clamper_servo;
//把编码器正交编码板OUTA信号连接到Arduino控制器的数字端口2,
//数字端口2是Arduino的外部中断0的端口。
#define PinA 2 //外部中断0
int N11 =6; //升降直流电机驱动板的电机使能端口连接到数字接口6
int N12 =7; //升降直流电机驱动板的电机转向端口连接到数字接口7
int P11_left =8; //连接小车左轮电机的PWM控制端口到数字接口8
int P12_left =9; //连接小车左轮电机的转向控制端口到数字接口9
int P21_right =10; //连接小车右轮电机的PWM控制端口到数字接口10
int P22_right =11; //连接小车右轮电机的转向控制端口到数字接口11
int Limit=12; //夹持器上限位开关连接到数字端口12
byte working_state=0;//升降电机正反转和停止标识字节
byte Start=0xff; //数据开始传送的标识字节
int speed_flag=1; //电机速度程度标识,1为高速、0为低速
int PS_LY;//存储接受到的PS2手柄左摇杆Y轴数据
int PS_RY;//存储PS2手柄右摇杆Y轴数据
int PS_RX;//存储PS2手柄右摇杆X轴数据
int pos1; //舵机角度
int power;//电机转速PWM值
//初始化
void setup()
{
Serial1.begin(9600); //串口波特率设置,开始串口通信
pinMode(PinA,INPUT); //升降伺服电机正交编码板的OUTA信号端设置为输入模式
pinMode(N11, OUTPUT); //升降直流电机驱动板的控制端口设置为输出模式
pinMode(N12, OUTPUT);
digitalWrite(N11, LOW); //升降电机停止
digitalWrite(N12, LOW);
delay(20);
pinMode(Limit,INPUT); //夹持器上限位开关数字端口12设置为输入模式
pinMode(P21_right, OUTPUT); //小车直流电机驱动板的控制端口设置为输出模式
pinMode(P22_right, OUTPUT);
pinMode(P11_left, OUTPUT);
pinMode(P12_left, OUTPUT);
digitalWrite(P21_right, LOW); //小车右电机停止
digitalWrite(P22_right, LOW);
delay(20);
digitalWrite(P11_left, LOW); //小车左电机停止
digitalWrite(P12_left, LOW);
delay(20);
clamper_servo.attach(4); //初始化舵机角度为90度
clamper_servo.write(90);
}
void left_advance(int left_val)//小车左轮前进
{
digitalWrite(P11_left,LOW);
analogWrite(P12_left, left_val);
}
void left_back(int left_val) //小车左轮后退
{
digitalWrite(P12_left,LOW);
analogWrite(P11_left,left_val);
}
void right_advance(int right_val)//小车右轮前进
{
digitalWrite(P22_right,LOW);
analogWrite(P21_right,right_val);
}
void right_back(int right_val)//小车右轮后退
{
digitalWrite(P21_right,LOW);
analogWrite(P22_right,right_val);
}
void left_stop()//小车左轮停止
{
digitalWrite(P11_left, LOW);
digitalWrite(P12_left, LOW);
}
void right_stop()//小车右轮停止
{
digitalWrite(P21_right, LOW);
digitalWrite(P22_right, LOW);
}
//主程序
void loop()
{
//如果Arduino控制板的读缓冲区中存在上位机下达的字节
if(Serial1.available()>0)
{
delay(30);
Start=Serial1.read();
//如果接受到用于标识数据开始传送的字节0xff,
//则接下来读取遥控器发来的数据。
if(Start==0xff)
{
//电机速度程度标识,1为高速、0为低速
speed_flag=Serial1.read();
//PS2手柄左摇杆Y轴数据用于控制升降电机转向
PS_LY=Serial1.read();
//PS2手柄右摇杆Y轴数据用于控制小车前进或后退
PS_RY=Serial1.read();
//PS2手柄右摇杆Y轴数据用于控制小车左转或右转
PS_RX=Serial1.read();
pos1= Serial1.read();
}
if(speed_flag==1)
power=180; //设置为高速,高速时,电机PWM值为180
if(speed_flag==0)
power=100; //设置为低速,高速时,电机PWM值为100
// 如果左摇杆向前摇动
if(PS_LY<37)
{
working_state=2; //升降电机反转
}
//如果左摇杆向后摇动
if(PS_LY>217)
{
working_state=1; //升降电机正转
}
// 如果左摇杆居中
if(PS_LY>=37 && PS_LY<=217)
{
working_state=0; //升降电机停止
}
if(working_state==1)
{
analogWrite(N11,power); //升降电机以PWM值为180的转速转动
digitalWrite(N12,LOW); //电机正转
}
else if(working_state==2)
{
digitalWrite(N11,LOW); //升降电机反转
analogWrite(N12,power); //电机以PWM值为180的转速转动
}
else if(working_state==0)
{
digitalWrite(N11, LOW); //升降电机停止
digitalWrite(N12, LOW);
}
//如果电机处于反转状态,同时夹持器又触碰到上限位开关
if (digitalRead(Limit) == LOW && working_state==2 )
{
digitalWrite(N11, LOW); //升降电机停止
digitalWrite(N12, LOW);
working_state=0;
}
// 如果右摇杆向前摇动
if(PS_RY<37) //小车前进
{
left_advance(power);
right_advance(power);
}
// 如果右摇杆向后摇动
if(PS_RY>217) //小车后退
{
left_back(power);
right_back(power);
}
// 如果右摇杆向左摇动
if(PS_RX<37) //小车左转
{
left_advance(0);
right_advance(power);
}
// 如果右摇杆向右摇动
if(PS_RX>217) //小车右转
{
left_advance(power);
right_advance(0);
}
// 如果右摇杆居中
if(PS_RY>=37 && PS_RY<=217 && PS_RX>=37 && PS_RX<=217)
{
left_stop(); //小车停止
right_stop();
}
clamper_servo.write(pos1);//控制夹持器上的舵机动作
}
} 复制代码
Arduino 为啥这么红,我想Arduino单片机较其他微控制器有以下5点优势:1、您学习Arduino单片机可以完全不需要了解其内部硬件结构和寄存器设置,仅仅知道它的端口作用即可,所以不需要硬件知识,只要会C语言,就可立即为Arduino单片机编程。2、Arduino软件语言为精简指令系统,所需掌握的指令不多,但指令的功能却很强大,往往一条指令就可以完成一整套操作,而且指令的可读性也好,属于低门槛的语言,轻松上手,快速应用。3、针对周边I/O设备的Arduino编程,由于很多I/O设备都随之带有库文件或者样例程序,所以在自己的程序中,可以引用库文件中的函数,或复制样例程序,然后修改下其中的参数,即可迅速编写出复杂的程序任务,从而放大了您的编程能力。4、Arduino开源硬件在创客界十分流行。所谓开源产品定义,不仅是其软硬件底层信息完全公开,而且还在于产品的应用资讯可以从Arduino相关网站、博客里的大量共享资源里获得,所以在共享资讯的辅助下,能激发出您创意作品的灵感,并加快您创作作品的效率。5、国内在开源硬件的制造能力非常强,涌现出被意大利Arduino公司认可的代理商,如DFRobot、Seeed Studio公司,这些公司提供了丰富的质优价廉Arduino及周边产品,所以在国内学习和应用Arduino具有得天独厚的硬件资源优势。