Arduino打造 USB转蓝牙鼠标的装置

去年的这个时候,我做了一个 USB键盘转蓝牙的装置【参考1】,有很多朋友根据我的方法成功制作出自己的转接装置。本文将介绍如何用Arduino打造一个USB鼠标转蓝牙的装置。

从原理上来说,Arduino 通过 USB Host Shield 驱动 USB 鼠标,将其切换为 Boot Protocol 模式,该模式下鼠标会用固定的格式和Arduino通讯,这样避免了不同设备需要单独解析 HID Protocol的问题 。之后,Arduino将解析出来的鼠标动作通过串口,以规定的格式告知蓝牙模块,最后在手机或者电脑端即可以蓝牙鼠标的方式进行动作。

usbtobluetooth

使用的硬件如下

Arduino Uno  1块
USB Host Shield

 

1块
带面包板的Shield板

 

1块
XM-04-HID-M 蓝牙HID鼠标模块 1块
18650电池(选配)

 

2节
18650 电池盒(选配) 1个

 

最主要的配件如下

 

image004

和之前的键盘转接装置相比,最大的不同在于本文代码使用了USB Host Shield 2.0的库,大量的底层操作都被封装起来,编程上非常简单,完全可以专注于“做什么”而不是“如何做”,这也是 Arduino的魅力所在。

代码需要用到 USB Host Shield2.0这个库,安装的方法很简单,打开 Sketch->Include Library->Manage Libraries 调出 Library Manager,直接搜索 “USB Host”字样,然后点击Install即可。

(我们需要安装的是 USB Host Shield Library 2.0,这是用起来驱动 USB Host Shield的。另外那个 USBHost是给Due 用的)

image003

USB Host 解析出来的鼠标数据格式如下:

struct MOUSEINFO {

 

struct {

uint8_t bmLeftButton : 1;        //鼠标左键按下标记

uint8_t bmRightButton : 1;     //鼠标右键按下标记

uint8_t bmMiddleButton : 1; //鼠标中键按下标记

uint8_t bmDummy : 5;            //保留

};

int8_t dX;         //水平方向移动偏移

int8_t dY;         //垂直方向移动偏移

};

 

Arduino和蓝牙模块是通过串口进行通讯的,通讯报文长为8字节,每个字节分别如下【参考3】:

BYTE1 0x08 固定值(包长度)
BYTE2 0x00 固定值
BYTE3 0xA1 固定值
BYTE4 0x02 固定值
BYTE5 Button 1/2/3
BYTE6 X-Axis(-127~127)
BYTE7 Y-Axis(-127~127)
BYTE8 Whell (-127~+127)

 

我们需要做的只是将USB HOST 解析出来的MOUSEINFO转发给串口模块即可。

#include <hidboot.h>

#include <SPI.h>

 

#define BIT0  1

#define BIT1  2

#define BIT2  4

 

class MouseRptParser : public MouseReportParser

{

protected:

         void OnMouseMove     (MOUSEINFO *mi);

         void OnLeftButtonUp   (MOUSEINFO *mi);

         void OnLeftButtonDown      (MOUSEINFO *mi);

         void OnRightButtonUp (MOUSEINFO *mi);

         void OnRightButtonDown    (MOUSEINFO *mi);

         void OnMiddleButtonUp      (MOUSEINFO *mi);

         void OnMiddleButtonDown         (MOUSEINFO *mi);

};

 

void SendToBT(MOUSEINFO *mi)

{

     byte  Button=0;

    

     if (mi->bmLeftButton)

       Button |= BIT0;

     else

       Button & !BIT0;

      

      if (mi->bmRightButton)

       Button |= BIT1;

     else

       Button & !BIT1;

      

      if (mi->bmMiddleButton)

       Button |= BIT2;

     else

       Button & !BIT2;

    

     /*

     Serial.println("L Mouse Move");

     Serial.print("dx=");

     Serial.print(mi->dX, DEC);

     Serial.print(" dy=");

     Serial.println(mi->dY, DEC);

     Serial.println(Button,DEC);

     */

   

   

     Serial.write(0x08);  //BYTE1    

     Serial.write(0x00);  //BYTE2

     Serial.write(0xA1);  //BYTE3

     Serial.write(0x02);  //BYTE4

     Serial.write(Button);  //BYTE5        

     Serial.write(mi->dX);  //BYTE6        

     Serial.write(mi->dY);  //BYTE7

     Serial.write(0);  //BYTE8          

}

 

void MouseRptParser::OnMouseMove(MOUSEINFO *mi)

{

    SendToBT(mi);

};

void MouseRptParser::OnLeftButtonUp   (MOUSEINFO *mi)

{

    //Serial.println("L Butt Up");

    SendToBT(mi);   

};

void MouseRptParser::OnLeftButtonDown       (MOUSEINFO *mi)

{

    //Serial.println("L Butt Dn");

    SendToBT(mi);   

};

void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi)

{

    //Serial.println("R Butt Up");

    SendToBT(mi);   

};

void MouseRptParser::OnRightButtonDown    (MOUSEINFO *mi)

{

    //Serial.println("R Butt Dn");

    SendToBT(mi);

};

void MouseRptParser::OnMiddleButtonUp      (MOUSEINFO *mi)

{

    //Serial.println("M Butt Up");

    SendToBT(mi);

};

void MouseRptParser::OnMiddleButtonDown          (MOUSEINFO *mi)

{

    //Serial.println("M Butt Dn");

    SendToBT(mi);   

};

 

USB     Usb;

 

HIDBoot<HID_PROTOCOL_MOUSE>    HidMouse(&Usb);

 

uint32_t next_time;

 

MouseRptParser                               Prs;

 

void setup()

{

    Serial.begin( 115200 );

    Serial.println("Start");

 

    if (Usb.Init() == -1)

        Serial.println("OSC did not start.");

 

    delay( 200 );

 

    next_time = millis() + 5000;

 

    HidMouse.SetReportParser(0,(HIDReportParser*)&Prs);

}

 

void loop()

{

  Usb.Task();

}

 

 

最终的成品,Arduino和其他Shield堆叠起来,使用电池独立供电

image002

特别注意的地方:

  1. 如果使用USB 供电,Arduino可能会遇到供电不足的问题(外围有USB Host Shield / USB Mouse / Bluetooth),解决办法是直接从圆形 DC 口接入电池,这就是本文使用18650电池的原因;
  2. 本文使用的蓝牙模块并非普通的串口蓝牙(HC05/06),而是专门的蓝牙鼠标模块。之前制作USB键盘转接设备的时候,很多朋友没有注意,购买的是 HC05/06这样的蓝牙串口模块,最后只得重新购买。关于蓝牙鼠标模块的更多信息可以在之前的介绍中看到【参考2】;
  3. 蓝牙 HID 模块默认波特率只有是 9600,在操作时有明显卡顿,需要对其下 AT 命令,将波特率升到 115200。

 

参考:

  1. http://www.arduino.cn/thread-17412-1-1.html U2B: USB键盘转蓝牙键盘的设备
  2. http://www.arduino.cn/thread-22076-1-1.html 介绍一个蓝牙鼠标模块
  3. XM-04-HID-M 蓝牙HID鼠标模块规格书0

发表评论

电子邮件地址不会被公开。 必填项已用*标注