arduino开发板通常用来控制直流伺服电机(舵机)这些比较简单的电机。
一.PS2手柄介绍
PS2 手柄由手柄与接收器两部分组成,手柄主要负责发送按键信息;接收 器与单片机(也可叫作主机,可直接用在 PS2 游戏机上)相连,用于接收手柄 发来的信息,并传递给单片机,单片机也可通过接收器,向手柄发送命令,配置 手柄的发送模式。
引脚说明
接收器引脚输出: 接收器图片(一定要注意端口顺序)
1. DI/DAT:信号流向,从手柄到主机,此信号是一个 8bit 的串行数据,同 步传送于时钟的下降沿。信号的读取在时钟由高到低的变化过程中完成。 2. DO/CMD:信号流向,从主机到手柄,此信号和 DI 相对,信号是一个 8bit 的串行数据,同步传送于时钟的下降沿。 3.NC:空端口; 4. GND:电源地; 5.VDD:接收器工作电源,电源范围 3~5V; 6.CS/SEL:用于提供手柄触发信号。在通讯期间,处于低电平; 第 4 页 共 7 页 7.CLK:时钟信号,由主机发出,用于保持数据同步; 8.NC:空端口; 9.ACK:从手柄到主机的应答信号。此信号在每个 8bits 数据发送的最后一 个周期变低并且 CS 一直保持低电平,如果 CS 信号不变低,约 60 微秒 PS 主 机会试另一个外设。在编程时未使用 ACK 端口
时钟频率 250KHz(4us),如果接收数据不稳定,可以适当的增加频率。 在通讯过程中,一串数据通讯完成后 CS 才会由低转高,不是 1 个字节通讯完 成后就由低转高,在通讯期间,一直处于低电平。在时钟下降沿时,完成数据(1bit) 的发送与接收,发送和接收是同时完成的。当单片机想读手柄数据或向手柄发送 命令时,将会拉低 CS 线电平,并发出一个命令“0x01”;手柄会回复它的 ID “0x41= 绿灯模式,0x73=红灯模式”;在手柄发送 ID 的同时,单片机将传送 0x42,请求数据;随后手柄发送出 0x5A,告诉单片机“数据来了”。 idle:数据线空闲,该数据线无数据传送。 一个通讯周期有 9 个字节(8 位),这些数据是依次按位传送。当有按键按下,对应位为“0”,其他位为“1”,例如当键“SELECT”被 按下时,Data[3]=11111110B。
我们大多数时候使用PS2手柄只需要简略的了解他的原理,PS2手柄原理的文章很多,更多的是要去看封装的函数,或者是我们导入的函数库,去学习我们应该如何调参。
二.arduino的PS2X_lib库文件
我们在arduino的开发板上想使用PS2手柄进行控制一些列电机,在硬件基础上要有arduino的扩展板,在软件上就要将PS2X_lib库文件导入我们的arduinoIDE开发软件中。下面是PS2X_lib的CPP文件和头文件。
链接:https://pan.baidu.com/s/18l1nyQCRMOUHF2LLD0J3Iw
提取码:qm82
我们下载完文件之后,要将cpp文件和头文件放在一个文件夹里,进行压缩,然后点击工具---导入库,将我们的库文件导入进IDE软件。这时候我们会遇到很多文件,我在开发中遇到最多的问题就是Error: 13 INTERNAL: Library install failed: archive is not valid: multiple files found in zip file top level。我总结的经验就是,要注意路径的问题,我们需要把这个压缩的zip文件放到arduino中的library文件中。
项目文件夹地址可能有关系,我们需要将包含库函数的文件放到我们的项目文件夹地址。
让编译软件能够找到库函数的位置。
当我们将库函数文件导入到编译软件中已经完成了一大步。
三.arduino编程
这里我只实现了控制一个舵机,多个舵机同理。
#include <Servo.h>
//导入库文件
#include "PS2X_lib.h"
//定义ps2手柄
PS2X ps2x;
int error;
int pose=0;
Servo myservo;
void setup() {
myservo.attach(9);
myservo.write(0);
do {
error = ps2x.config_gamepad(13, 11, 10, 12, true, true);
if (error == 0) { break; }
else { delay(100); }
} while (1);
}
void loop(){
ps2x.read_gamepad(false, 0);//读入手柄状态信息
// //键位码请看上面对应图
// if (ps2x.Button(PSB_PAD_UP)) {
// pose+=5;
// if(pose>=180)
// {
// pose=180;
// }
// myservo.write(pose);
// }//如果“上”按钮按下
// delay(100);
// if(ps2x.Button(PSB_PAD_DOWN))
// {
// pose-=5;
// if(pose<=0)
// {
// pose=0;
// }
// myservo.write(pose);
// } //下按钮
if (ps2x.Analog(PSS_LY) < 10) {
pose+=5;
if(pose>=180)
{
pose=180;
}
myservo.write(pose);
}//如果摇杆LY返回值小于10
if (ps2x.Analog(PSS_LY)>240){
pose-=5;
if(pose<=0)
{
pose=0;
}
myservo.write(pose);
}//如果摇杆LY返回值大于240
delay(10);//延迟10ms
}
在PS2手柄的库函数文件中
#define PSB_PAD_UP 0x0010
#define PSB_PAD_RIGHT 0x0020
#define PSB_PAD_DOWN 0x0040
#define PSB_PAD_LEFT 0x0080
这几个就是定义的按键,我们需要将其填入button函数中,使其相应的按键发挥作用。
#define PSS_RX 5
#define PSS_RY 6
#define PSS_LX 7
#define PSS_LY 8
这是摇杆的定义,我们知道PS2手柄的两个摇杆分别有X轴和Y轴两个轴,我们通过PS2手柄的模拟值进行判断,使其能够达到相应的效果,LX,LY就是左边摇杆的两个轴,RX,RY就是右边摇杆的两个轴。而在代码中模拟值小于10就是左边摇杆向上推,这个模拟值的定义是与我们的库函数有关的,你说为什么小于10就是向上推,这就是库函数中定义好的,你也可以修改。
这样我们就实现了arduino开发板搭配PS2手柄控制舵机.