描述
<p>注:*为必填项。</p>
<p>【请在报名阶段填写 ↓】
<em> 1、个人网站 <a href="http://www.lab-z.com" target="_blank">www.lab-z.com</a> 一直在使用 Arduino 制作各种设备
</em> 2、一些特定情况下,公司的机器不支持USB接口,因此想在电脑上使用USB接口的键盘鼠标会遇到问题。对于传统的有线鼠标可以通过淘宝上的转接器直接完成(能够实现这一点是因为USB鼠标芯片能够直接识别当前所用的接口),但是非常不幸的是无线鼠标并没有这样的接口,因此无法通过这种转接器来完成转接。因此,使用 Arduino 制作一个能将无线USB转接为 PS/2、的设备。</p>
<p>< br>
【请在竞赛阶段填写 ↓】
* 1、描述项目详情
USB是由英特尔等多家公司联合在1996年推出的一种外部总线标准,用于电脑与外部设备的连接和通讯。相比之前的串口并口等等接口,USB具有方便扩展,可连接多种外设以及支持热插拔等等优点。因为上述优点,USB接口迅速普及,很快就应用于键盘鼠标和主机的连接。在USB普及之前,PS/2接口是专门为键盘鼠标设计的接口,更早之前还有串口作为鼠标接口。键盘鼠标可以通过这个接口接入电脑中,PS/2和USB这两种接口从外形到协议都是截然不同的。通常如果想将一个 USB键盘鼠标设备接入到PS2接口上可以使用下面这个转接器。
<img src="//image.lceda.cn/pullimage/CCGVPi1DmnOvJ8h48Hi7iVJhd32vEkVAv4QFaNJq.jpeg" alt="67472cadb2d51ea235e7f99818d26186.jpg">
实际上其中没有任何元件只是物理连接,将USB6的D+ D-连接到 PS2的CLK 和DATA。通过键盘鼠标设备在上电的时候判断接口类型自动选择协议。非常不幸的是,很多无线键盘鼠标的接收器并没有这个功能,因此,用户无法在PS2接口上使用USB无线键盘鼠标,当然市场上也从未出见过PS2接口的无线键盘鼠标。这次就是使用 Arduino 制作一个将无线鼠标转接为PS2的设备。</p>
<p>* 2、描述项目所面临的挑战及所解决的问题
基本原理如下:鼠标将移动和按键数据通过无线协议发送给USB接收器,接收器取得数据后以HID协议上报给Arduino
USB Host Shield,接下来 Arduino 负责将USB数据解析出来再转化为 PS2协议发送给主机:
<img src="//image.lceda.cn/pullimage/LIUMF8a5lfi1gFrBbkYPcyy969ODDPV3aZZMhW8n.jpeg" alt="tbl.jpg"></p>
<p>【参考1】对于 X 方向有 Byte 1 的 Bit 4 (X
sign bit)来表示方向(正负),还有 Byte 1的 Bit 6 (X overflow) 以及Byte
2 来表示移动距离。所以 PS/2 鼠标的 X 移动范围是 -255 ~ +255 。</p>
<p>* 3、描述项目硬件、软件部分涉及到的关键点
这次转接的目标是罗技 M105 无线鼠标,此外还有下列元件</p>
<table>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
<tr>
<td>元件</td>
<td>数量</td>
<td>选择理由</td>
</tr>
<tr>
<td>USB Host Shield Mini</td>
<td>1</td>
<td>为了保证转接器体积小,这次选择 USB Host Shield Mini来作为USB Host;</td>
</tr>
<tr>
<td>3.3V Arduino Pro Micro</td>
<td>1</td>
<td>常见的 Arduino Pro Micro 是5V 这次选择的是3.3V版本的,因为这个版本信号也都是3.3V电平可以直接和 USB Host Mini Shield 进行通讯。如果选择5V版本,只有加入电平转换电路才能正常通讯;</td>
</tr>
<tr>
<td>PS2 公头线</td>
<td>1</td>
<td>用于将PS2连接到PC端</td>
</tr>
<tr>
<td>3mm 铜柱螺丝</td>
<td>若干</td>
<td>整体固定</td>
</tr>
</table>
<p>电路图如下:
<img src="//image.lceda.cn/pullimage/KG5lmj0qxhvfibBMly9lkjwq1mHyNBGnPrmndjLp.png" alt="image002.png"></p>
<p>上述主要分为 2部分,一个是USB
Host Mini 对 Arduino Pro Micro 3.3V 的连接,双方是通过SPI进行通讯的。这里再次强调必须是 3.3V 版本的 Arduino Pro Micro才能直接通讯;另外一部分是Arduino 对PS2的通讯,因为 Arduino 是 3.3V,所以需要使用下面这个电路来进行双向电平转换,来自 Arduino D3_3.3V 和 D3_5V 进行通讯,
<img src="//image.lceda.cn/pullimage/V1IX1SlWx7ufHiKSDjcdtD0Zz4HQAf7BSiDmLck9.png" alt="image003.png"></p>
<p>PCB 设计如下:</p>
<p><img src="//image.lceda.cn/pullimage/OJkMglMl7zWpRymwJxPl5yfrtZiS5fAOw8TIImrY.png" alt="image004.png"></p>
<p>预览:
<img src="//image.lceda.cn/pullimage/nZr9SaXJeAL5a5guRsoIdmS8UEFzYXliCh58ohMV.png" alt="image005.png">
硬件确定后即可开始软件设计。第一步:USB 数据的解析。特别注意,不同的鼠标发出来的格式不同,这里使用的是罗技 M185无线鼠标。首先用USBLyzer 分析USB接收器的 HID 数据,抓取到的如下:
<img src="//image.lceda.cn/pullimage/sfs6pgl6gQmKHNhX3El83tf5vIQxdV7t9iYubIuz.png" alt="image006.png"></p>
<p>再通过实验确定数据格式:</p>
<p><img src="//image.lceda.cn/pullimage/m6ysb32cvfg7RlwDGmeFM2EwsBzDF0JZwfscCe2o.png" alt="image007.png">
每次鼠标接收器会发送8字节的数据给主机:AA XX BB CC DD EE FF GGAA 的低三位对于鼠标三个按键;XX 一直为00;BB CC 给出 x 方向移动数据(0xCCBB); DD EE 给出 y 方向的移动数据(0xEEDD); FF 是滚轮移动的距离;GG 这里在 Descriptor 中的描述是 AC Pan, 这是一种水平方向的滚轮,但是在笔者使用的M185上并不存在这个滚轮,所以始终为0。鼠标发送的格式就是下面这个结构体。
<code>struct USBMouseData_LogitechM185{</code>
<code>struct {</code>
<code>unsigned char _left_btn : 1; // 1 byte</code>
<code>unsigned char _right_btn : 1;</code>
<code>unsigned char _middle_btn : 1;</code>
<code>unsigned char _dummy : 5;</code>
<code>};</code>
<code>char na1;</code>
<code>int _delta_x;</code>
<code>int _delta_y;</code>
<code>char _delta_z;</code>
<code>char na2;</code>
<code>};</code>< br>
< br>
鼠标的解析在之前的文章中介绍过很多次,这里就不过多复述。还有一个需要注意的地方是USB
Host Library 会比对本次数据和上一次的数据,如果有差别那么就不会将新的数据发送给上层。这个设计会影响鼠标的滚轮,因为滚轮转动数据量不大,经常只是滚动一行,这样会出现滚动并不灵敏的情况,因此在 \USB_Host_Shield_Library_2.0\hiduniversal.cpp 中做如下修改:</p>
<p><code>bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) { for(uint8_t i = 0; i < len; i++) if(buf1[i] != buf2[i]) return false; if (buf1[6]!=0) return false; //LABZDebug return true;}</code>< br>
< br>
只要USB 传来的数据中,第七个数值不为零,就认为这个数据应该发送给上层处理。USB 数据会在 void on_usb_data(USBMouseData_LogitechM185* data) 函数中处理。这里对收到的鼠标 X Y移动数据进行处理。PS2 鼠标的移动范围是-255 到 +255,罗技 M185 鼠标的移动范围是-32767到+32767.通常的想法是使用 MAP 函数进行处理,但是这样做的结果会导致鼠标灵敏度下降。经过研究发现这是因为大部分的移动数值很小,使用MAP 函数会将这个数值变得更小,导致灵敏度下降。于是,编写mousemap() 函数,对于超过255的移动直接变成 255\, 对于绝对值小于 255的数值不做处理。</p>
<p><code>int mousemap(int value) { if (value< -255) {return -255;} if ((value>=-255)&&(value< =255)) {return value;} if (value>255) {return 255;}}</code>< br>
< br>
经过上面的处理后,通过 PS2MouseSample() 函数即将数据通过 PS2 接口发送给主机端。网上有很多 Arduino PS/2 的库,但是大多数是Arduino作为PS2
Host ,这里我们需要将 Arduino 作为 PS2 Device,因此使用 <a href="https://github.com/harvie/ps2dev" target="_blank">https://github.com/harvie/ps2dev</a> 这个库。最初我使用一个 PS/2 转USB 的转接线来进行实验(理论上,现在的 PS/2 已经支持了热插拔,但是我确实见过热插拔烧坏主板的事情,稳妥起见并不建议在主板上进行PS/2 设备的热插拔)。</p>
<p><img src="//image.lceda.cn/pullimage/Kvowf5EpQmUAEvQZUtjRet7IyJ7FZXXiyTDYMWL1.jpeg" alt="image008.jpg"></p>
<p>但是实验中发现 PS2Dev 库无法在上面工作,后来试用了DSLogic逻辑分析仪【参控2】,发现这个竟然无法解析PS/2协议,最终入手了Kingst
LA2016usb逻辑分析仪。
<img src="//image.lceda.cn/pullimage/w0A9UMTEZChGwaQWM5IDApM2FL5GmsfQwW0cVJPX.png" alt="image009.png">
* 4、项目材料清单展示
这次转接的目标是罗技 M105 无线鼠标,此外还有下列元件</p>
<table>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
<tr>
<td>元件</td>
<td>数量</td>
<td>选择理由</td>
</tr>
<tr>
<td>USB Host Shield Mini</td>
<td>1</td>
<td>为了保证转接器体积小,这次选择 USB Host Shield Mini来作为USB Host;</td>
</tr>
<tr>
<td>3.3V Arduino Pro Micro</td>
<td>1</td>
<td>常见的 Arduino Pro Micro 是5V 这次选择的是3.3V版本的,因为这个版本信号也都是3.3V电平可以直接和 USB Host Mini Shield 进行通讯。如果选择5V版本,只有加入电平转换电路才能正常通讯;</td>
</tr>
<tr>
<td>PS2 公头线</td>
<td>1</td>
<td>用于将PS2连接到PC端</td>
</tr>
<tr>
<td>3mm 铜柱螺丝</td>
<td>若干</td>
<td>整体固定</td>
</tr>
</table>
<p>* 5、项目图片上传
<img src="//image.lceda.cn/pullimage/KEf7LpaXCOr77Z3ZzHTtQVqsW3J0x1AI89W8ZlaM.png" alt="pic1.png">
<img src="//image.lceda.cn/pullimage/EFSLhjCIGirNLkZGhsG1jccVYVhXI8ZUF7G1klLB.jpeg" alt="pic2.jpg"></p>
<p>* 6、演示您的项目并录制成视频上传
6.1、视频上传大赛官网
6.2、B站视频标题和链接 <a href="https://www.bilibili.com/video/BV1zK411T7nN/" target="_blank">https://www.bilibili.com/video/BV1zK411T7nN/</a> 无线鼠标转PS2鼠标</p>
<p><em> 7、是否首次公开发布
首次发表
7.1、项目之前是否发表过或获奖,请说明 未发表过
7.2、若项目是在原有基础上优化,请说明优化部分
</em> 8、开源文档
源代码可以在附件中下载到</p>
<p>* 9、参考文献
参考:</p>
<ol>
<li><a href="https://isdaman.com/alsos/hardware/mouse/ps2interface.htm" target="_blank">https://isdaman.com/alsos/hardware/mouse/ps2interface.htm</a></li>
<li><a href="http://www.lab-z.com/dslogic/" target="_blank">http://www.lab-z.com/dslogic/</a> DSLogic逻辑分析仪试用</li>
<li><a href="http://www-ug.eecg.toronto.edu/msl/nios_devices/datasheets/PS2%20Keyboard%20Protocol.htm" target="_blank">http://www-ug.eecg.toronto.edu/msl/nios_devices/datasheets/PS2%20Keyboard%20Protocol.htm</a>
*0xFA (Set All Keys Typematic/Make/Break) - Keyboard responds with "ack" (0xFA). Sets all keys to their normal setting (generate scan codes on make, break, and typematic repeat)
4. <a href="https://github.com/liumazi/MzMouse" target="_blank">https://github.com/liumazi/MzMouse</a></li>
</ol>
评论(4)