创客杂谈
首发于创客杂谈
【智造万物】如何使用游戏手柄控制机器人

【智造万物】如何使用游戏手柄控制机器人

在制作一些 Arduino 机器人项目时,我们通常希望能便捷地控制机器人。常用的方法有:红外遥控器、手机 App 控制、USB 设备(键鼠/手柄)控制等。其中红外遥控器的控制距离和稳定性都不是很好,手机 App 的实现难度又比较高,比较理想的其实还是使用通用 USB 设备控制机器人。本文将以一款 USB 无线游戏手柄为例,讲解如何解析 USB 设备的通信协议,并实现对机器人的控制。

为了让 Arduino 能读取 USB 设备的数据,必须使用一块芯片——CH375B。这块芯片可以将 USB 数据转为串口数据,发送给 Arduino。本文使用的是 Makeblock USB Host 模块,其中就带有一块 CH375B 芯片。Makeblock 为这个模块提供了库文件,可以通过简单地调用库函数来实现初始化、读取等操作,不再需要发送一系列指令。简单地安利一下,常规的 CH375 库只能使用串口与 CH375 芯片通信,而 Makeblock 封装后的库可以使用任意两个引脚模拟串口,不需要占用硬件串口资源。库文件可以在这里下载: Makeblock-official/Makeblock-Libraries · GitHub

先将 USB Host 模块连接到 Makeblock Orion 上,并将无线 USB 游戏手柄的接收器查到 USB Host 模块上。这个游戏手柄是淘宝上随意买的一款,一般来说 CH375 支持的设备都是普通的 USB 设备,高端的游戏键鼠和手柄可能会不兼容。

然后编写一段程序,将 USB Host 接收到的数据通过串口发送到 PC 端查看。

#include "MeOrion.h"
#include "SoftwareSerial.h"

MeUSBHost usbhost(PORT_3);

int length = 0;

void parseJoypad(unsigned char *buf)   //print the data from USB Host
{
    for(int i = 0; i < length; i++)
    {
        Serial.print(buf[i]);
        Serial.print(" - ");
    }
    Serial.println(buf[length]);
}

void setup()
{
    Serial.begin(57600);
    usbhost.init(USB1_0);  //USB1_0 or USB2_0
}

void loop()
{
    if(!usbhost.device_online)
    {
        usbhost.probeDevice();
        delay(1000);
    }
    else
    {
        length = usbhost.host_recv();
        parseJoypad(usbhost.RECV_BUFFER);
        delay(5);
    }
}

串口读到的数据如下图:

反复操作游戏手柄并观察接收到的数据,可以总结出操作和数据之间的规律:

//  手柄代码(红灯亮)
//  默认:128-127-128-127-15-0-0-128
//  左一:128-127-128-127-15-1-0-128
//  右一:128-127-128-127-15-2-0-128
//  左二:128-127-128-127-15-4-0-128
//  右二:128-127-128-127-15-8-0-128
//  三角:128-127-128-127-31-0-0-128 (0001 1111)
//  方形:128-127-128-127-143-0-0-128 (1000 1111)
//  叉号:128-127-128-127-79-0-0-128 (0100 1111)
//  圆圈:128-127-128-127-47-0-0-128 (0010 1111)
//  左微动: 128-127-128-127-15-64-0-128
//  右微动: 128-127-128-127-15-128-0-128
//  向上:128-127-128-127-0-0-0-128 (0000 0000)
//  向下:128-127-128-127-4-0-0-128 (0000 0100)
//  向左:128-127-128-127-6-0-0-128 (0000 0110)
//  向右:128-127-128-127-2-0-0-128 (0000 0010)
//  左上:128-127-128-127-7-0-0-128 (0000 0111)
//  左下:128-127-128-127-5-0-0-128 (0000 0101)
//  右上:128-127-128-127-1-0-0-128 (0000 0001)
//  右下:128-127-128-127-3-0-0-128 (0000 0011)
//  选择:128-127-128-127-15-16-0-128
//  开始:128-127-128-127-15-32-0-128
//  摇杆:右X-右Y-左X-左Y-15-0-0-128

调用 usbhost.host_recv() 函数后,接收到的数据将保存在以 usbhost.RECV_BUFFER 为起始地址的缓存中。想要用这个手柄控制机器人,只需要在 Arduino 的 loop 函数里调用 host_recv() 函数,并在 parseJoypad() 函数中,访问 RECV_BUFFER 地址读取内容,并根据这些内容来控制机器人。

编辑于 2016-07-12

文章被以下专栏收录