描述
<div class="document">
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">注:* 为必填项</p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"><strong><span style="color: #0093e6;">请在报名阶段填写 ↓</span></strong></p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">* 1、项目功能介绍</h3>
<hr class="horizontal-splitline normal-bold-2">
<p>这是一个能够将USB 手柄转为无线手柄的设备。这样,你可以将有线的 USB 手柄变为无线的手柄进行游戏。之所以做这个项目是因为我发现Linux 系统在支持多HID设备上和 Windows上有所不同。之前设计的,能够在 Windows上工作正常的USB转蓝牙设备无法在 Linux 系统上正常工作。因此,这次制作一个能够将2个USB手柄同时转为2个USB手柄的设备。</p>
<p>这次带来的方案是有两部分:发射端和接收端。</p>
<p>发射端是 ESP32 C3 配合 CH9350实现的,它能够实现USB手柄数据的读取和无线信号的发送。其中 CH9350负责USB手柄数据的解析;解析后的数据由ESP32 C3通过ESP-Now发送出去。CH9350是 WCH (就是出品 Ch340 的那个公司)推出的USB HID 转串口通讯控制芯片。就是说USB 手柄连接到这个芯片之后,数据会转化为串口输出。关于这个芯片的功能介绍如下:</p>
<ul>
<li>支持12Mbps全速USB传输和1.5Mbps低速USB传输,兼容USB V2.0。</li>
<li>上位机端USB端口符合标准HID类协议,不需要额外安装驱动程序,支持内置HID类设备驱动的Windows、Linux、macOS等操作系统。</li>
<li>同一芯片可配置为上位机模式和下位机模式,分别连接USB-Host主机和USB键盘、鼠标。</li>
<li>支持USB键盘鼠标在BIOS界面使用,支持多媒体功能键,支持不同分辨率USB鼠标。</li>
<li>支持各种品牌的USB键盘鼠标、USB无线键盘鼠标、USB转PS2线等。</li>
<li>上位机端和下位机端支持热插拔。</li>
<li>提供发送状态引脚,支持485通讯。</li>
<li>串口支持115200/57600/38400串口通信波特率。</li>
<li>内置晶振和上电复位电路,外围电路简单。</li>
<li>支持5V、3.3V电源电压。</li>
<li>提供LQFP-48无铅封装,兼容RoHS。</li>
</ul>
<p>发射端方案的优点是:成本比较低,体积比较小,容易DIY焊接(ESP32 C3 是我用过的最容易焊接的ESP32芯片)。能够同时支持2个USB设备,就是说你可以同时使用2个USB手柄,同时转化为无线给主机使用。</p>
<p>接收器使用的是ESP32-S2 ,它带有USB Device ,能够方便的将自身模拟为一个USB手柄。因此,无论 Windows 还是 Linux 只要支持USB 手柄,在操作系统端看起来插入的就是一个USB手柄,完全不会碰到兼容性问题。这里使用淘宝直接购买的Mini ESP32-S2 开发板,体积小,价格便宜。</p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">*2、项目属性</h3>
<hr class="horizontal-splitline normal-bold-2">
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">原创项目首次公开</p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">* 3、开源协议</h3>
<hr class="horizontal-splitline normal-bold-2">
<p><strong class="ql-size-13">Public Domain</strong></p>
<p style="line-height: 1.8;"> </p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"><strong><span style="color: #0093e6;">请在竞赛阶段填写 ↓</span></strong></p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">*4、硬件部分</h3>
<hr class="horizontal-splitline normal-bold-2">
<p>接下来首先进行电路的设计。</p>
<p>1. 主控 ESP32 C3 部分。这款主控内置了 USB 下载电路,我们设计一个 USB接口即可工作。此外,复位与下载按钮是必须的,当出现问题无法下载时,这两个按钮随时可以帮助恢复。</p>
<p><img src="//image.lceda.cn/pullimage/GidFSS0OxPyiyYiuyMoF1kyUVsny23KZWRsB6viZ.png" alt=""></p>
<p>2. 接下来时CH9350部分,它外部电路非常简单,只需要一个 3.3uf和一个 0.1uf电容即可工作。外部的 LED1和 LED2用来指示USB工作状态,没有有效数据时会亮,有数据传输时会熄灭。其中的USB3 是一个双层USB座子,这样我们可以同时使用两个USB手柄。</p>
<p> <img src="//image.lceda.cn/pullimage/I0UXd32kAPpGTbIB7mfNabs7tGSRdI4RadFdXOMR.png" alt="" width="779" height="386"></p>
<p> </p>
<p>3.我们使用 TLV1117将5V 转为3.3V,同时还预留一个假负载,用来避免在使用充电宝供电,输出小于50ma 一段时间后自动关机的问题。</p>
<p> </p>
<p> <img src="//image.lceda.cn/pullimage/GKL4k6LiGxPSKOf8YK5ajxxWLRBtjjQUZm9dlq78.png" alt="" width="252" height="225"><img src="//image.lceda.cn/pullimage/R3WGQthHj6BWnsal0dB9NZgRW1FD95o4WNJFSiIA.png" alt="" width="281" height="300"></p>
<p> </p>
<p>电路比较简单PCB设计也相对简单:</p>
<p><img src="//image.lceda.cn/pullimage/mwnZvSbba7ZlaO6Ms1Ojudm8EQptSlsumdXV8mFR.png" alt="" width="1430" height="949"></p>
<p>预览如下:</p>
<p><img src="//image.lceda.cn/pullimage/CLP16DEwoj9CCV8eeWMsCRihmS1y5XB9wYCtinc8.png" alt="" width="779" height="489"></p>
<p>上面就是硬件设计,接下来就可以着手软件的设计。</p>
<p> </p>
<p> *5、软件部分</p>
<hr class="horizontal-splitline normal-bold-2">
<p>同样,分成发送端和接收端分别介绍。</p>
<p>发送端的主要工作是:USB 手柄数据的获取,获得数据的发送。</p>
<p>对于USB 手柄数据的获取和之前的并没有多少差别,只需要解析来自串口的数据即可;特别注意代码加入了判断,只有收到和之前数据不同的时候才会发送;</p>
<p>我们使用 ESP-Now 进行数据发送。对于 Arduino 开发来说,这个非常简单。创建 ESPNow 对象,然后指定发送的地址即可:</p>
<p>// 创建esp_now_peer_info_t类型变量存储有关peer方的信息。</p>
<p>esp_now_peer_info_t peerInfo0;</p>
<p>esp_now_peer_info_t peerInfo1;</p>
<p> </p>
<p>// ESP32 接收器 MAC 地址</p>
<p>uint8_t broadcastAddress0[] = {'L', 'A', 'B', 'Z', '-', '0'};</p>
<p>uint8_t broadcastAddress1[] = {'L', 'A', 'B', 'Z', '-', '1'};</p>
<p> </p>
<p>之后每次收到改变后的USB手柄数据,可以使用下面的函数进行发送</p>
<p>// Send message via ESP-NOW</p>
<p> esp_err_t result = esp_now_send(broadcastAddress1, (uint8_t *) &Data[i + 6], 7);</p>
<p>对应的接收端的设计如下:</p>
<p>1. 程序开始处,设置当前ESP32 的MAC地址,作为接收数据的地址。发送端同时支持2个USB手柄,因此我们通过GPIO 判断设置2个Mac。这样,我们的程序刷到2个ESP32 S2主板上之后,根据外部跳线可以选择不同的 Mac 非常方便。</p>
<p> if (digitalRead(ADDRESSPIN2) == HIGH) {</p>
<p> esp_wifi_set_mac(WIFI_IF_STA, &newMACAddress0[0]);</p>
<p> } else {</p>
<p> esp_wifi_set_mac(WIFI_IF_STA, &newMACAddress1[0]);</p>
<p> }</p>
<p> if (DEBUGMODE) {</p>
<p> Serial.print("[NEW] ESP32 Board MAC Address: ");</p>
<p> Serial.println(WiFi.macAddress());</p>
<p> }</p>
<p>2. 为了实现USB 手柄,我们使用USB 手柄相同的 Report 描述符,这样在操作系统端看起来插入的就是一个 HID 手柄。</p>
<p> CustomHIDDevice(void) {</p>
<p> static bool initialized = false;</p>
<p> if (!initialized) {</p>
<p> initialized = true;</p>
<p> HID.addDevice(this, sizeof(report_descriptor));</p>
<p> }</p>
<p>}</p>
<p>3. 接收到的来自ESP NOW 的数据会出现在 OnDataRecv() 这个回调函数中,我们接收之后无需额外处理直接作为USB数据发送给主机即可。</p>
<p>// 创建一个回调函数,当 ESP32 通过 ESP-NOW 接收到数据时将被调用</p>
<p>void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {</p>
<p> if (DEBUGMODE) {</p>
<p> // 收到的数字,例如:</p>
<p> // 128 128 128 128 31 0</p>
<p> // 发过来的数据直接就是 RAW 格式</p>
<p> for (uint8_t i = 0; i < len; i++) {</p>
<p> printf("%02x ", incomingData[i]);</p>
<p> }</p>
<p> printf("\n");</p>
<p> }</p>
<p> </p>
<p> if (HID.ready()) {</p>
<p> Device.send((uint8_t *)&incomingData[0]);</p>
<p> }</p>
<p>}</p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt pap-left-indent-1.6em" style="line-height: 1.8;"> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">*6、BOM清单</h3>
<hr class="horizontal-splitline normal-bold-2">
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> 使用立创EDA设计:</p>
<table style="border-collapse: collapse; width: 480pt;" width="640">
<tr style="height: 14.4pt;">
<td style="height: 14.4pt; width: 48pt;" width="64" height="19">ID</td>
<td style="width: 48pt;" width="64">Name</td>
<td style="width: 48pt;" width="64">Designator</td>
<td style="width: 48pt;" width="64">Footprint</td>
<td style="width: 48pt;" width="64">Quantity</td>
<td style="width: 48pt;" width="64">Manufacturer Part</td>
<td style="width: 48pt;" width="64">Manufacturer</td>
<td style="width: 48pt;" width="64">Supplier</td>
<td style="width: 48pt;" width="64">Supplier Part</td>
<td style="width: 48pt;" width="64">Price</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">1</td>
<td>BAU1</td>
<td>BAU1</td>
<td>HDR-TH_2P-P2.54-V</td>
<td align="right">1</td>
<td>826629-2</td>
<td>TE Connectivity</td>
<td>LCSC</td>
<td>C86471</td>
<td align="right">2.55</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">2</td>
<td>BAU0</td>
<td>BAU2</td>
<td>HDR-TH_2P-P2.54-V</td>
<td align="right">1</td>
<td>826629-2</td>
<td>TE Connectivity</td>
<td>LCSC</td>
<td>C86471</td>
<td align="right">2.55</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">3</td>
<td>0.1uf</td>
<td>C1,C8</td>
<td>C1206</td>
<td align="right">2</td>
<td>C1206X104K1RAC7800</td>
<td>KEMET(基美)</td>
<td>LCSC</td>
<td>C600091</td>
<td align="right">0.4961</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">4</td>
<td>3.3uf</td>
<td>C2</td>
<td>C1206</td>
<td align="right">1</td>
<td>TCC1206X7R561K501DT</td>
<td>CCTC</td>
<td>LCSC</td>
<td>C377112</td>
<td align="right">0.0764</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">5</td>
<td>0.1uf</td>
<td>C3</td>
<td>C1206</td>
<td align="right">1</td>
<td>TCC1206X7R561K501DT</td>
<td>CCTC</td>
<td>LCSC</td>
<td>C377112</td>
<td align="right">0.0764</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">6</td>
<td>1uf</td>
<td>C6,C7,C9,C10</td>
<td>C1206</td>
<td align="right">4</td>
<td>C1206X104K1RAC7800</td>
<td>KEMET(基美)</td>
<td>LCSC</td>
<td>C600091</td>
<td align="right">0.4961</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">7</td>
<td>EN</td>
<td>EN1</td>
<td>SW-SMD_L4.0-W2.9-LS5.0</td>
<td align="right">1</td>
<td>TS342A2P-WZ</td>
<td>SHOU HAN</td>
<td>LCSC</td>
<td>C557591</td>
<td align="right">0.2033</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">8</td>
<td>Header2.0*5</td>
<td>H1</td>
<td>HEADER2.0*5</td>
<td align="right">1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">9</td>
<td>IO9</td>
<td>IO9</td>
<td>SW-SMD_L4.0-W2.9-LS5.0</td>
<td align="right">1</td>
<td>TS342A2P-WZ</td>
<td>SHOU HAN</td>
<td>LCSC</td>
<td>C557591</td>
<td align="right">0.2033</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">10</td>
<td>204-10SURD/S530-A3-L</td>
<td>LED1,LED2</td>
<td>LED-TH_BD3.0-P2.54-FD</td>
<td align="right">2</td>
<td>204-10SURD/S530-A3-L</td>
<td>EVERLIGHT(亿光)</td>
<td>LCSC</td>
<td>C99771</td>
<td align="right">0.1609</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">11</td>
<td>SS8050_C2150</td>
<td>Q1</td>
<td>SOT-23-3_L2.9-W1.3-P1.90-LS2.4-BR</td>
<td align="right">1</td>
<td>SS8050</td>
<td>CJ</td>
<td>LCSC</td>
<td>C2150</td>
<td align="right">0.0929</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">12</td>
<td>10K</td>
<td>R2</td>
<td>R1206</td>
<td align="right">1</td>
<td>CR1206J405R1G</td>
<td>LIZ(丽智电子)</td>
<td>LCSC</td>
<td>C102372</td>
<td align="right">0.02</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">13</td>
<td>1K</td>
<td>R3,R4</td>
<td>R1206</td>
<td align="right">2</td>
<td>R1206RXX102XJ04LTC</td>
<td>Shenzhen Eyang Tech Development</td>
<td>LCSC</td>
<td>C267247</td>
<td align="right">0.0243</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">14</td>
<td align="right">20</td>
<td>R5</td>
<td>R1206</td>
<td align="right">1</td>
<td>PTFR1206B10K0P9</td>
<td>ResistorToday</td>
<td>LCSC</td>
<td>C351536</td>
<td align="right">1.2904</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">15</td>
<td>1K</td>
<td>R6</td>
<td>R1206</td>
<td align="right">1</td>
<td>CR1206J405R1G</td>
<td>LIZ(丽智电子)</td>
<td>LCSC</td>
<td>C102372</td>
<td align="right">0.02</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">16</td>
<td align="right">100</td>
<td>R9</td>
<td>R1206</td>
<td align="right">1</td>
<td>PTFR1206B10K0P9</td>
<td>ResistorToday</td>
<td>LCSC</td>
<td>C351536</td>
<td align="right">1.2904</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">17</td>
<td>CH9350L</td>
<td>U1</td>
<td>LQFP-48_L7.0-W7.0-P0.50-LS9.0-BL</td>
<td align="right">1</td>
<td>CH9350L</td>
<td>WCH</td>
<td>LCSC</td>
<td>C109472</td>
<td align="right">24.5</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">18</td>
<td>ESP32-C3-WROOM-02 模组</td>
<td>U2</td>
<td>ESP32-C3-WROOM-02 模组</td>
<td align="right">1</td>
<td>ESP32-C3-WROOM-02-H4</td>
<td>espressif</td>
<td>LCSC</td>
<td>C2944070</td>
<td align="right">18.01</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">19</td>
<td>TLV1117LV33DCYR</td>
<td>U3</td>
<td>SOT-223_L6.7-W3.5-P2.30-BR</td>
<td align="right">1</td>
<td>TLV1117LV33DCYR</td>
<td>TI</td>
<td>LCSC</td>
<td>C15578</td>
<td align="right">0.9603</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">20</td>
<td>Double layer DIP 90° white</td>
<td>USB3</td>
<td>USB-A-TH_USB-M-51</td>
<td align="right">1</td>
<td>Double layer DIP 90° white</td>
<td>ValuePro</td>
<td>LCSC</td>
<td>C2341</td>
<td align="right">0.8867</td>
</tr>
<tr style="height: 14.4pt;">
<td style="height: 14.4pt;" align="right" height="19">21</td>
<td>USB-211-BCW</td>
<td>USB4</td>
<td>USB-A-TH_USB-211-BCW</td>
<td align="right">1</td>
<td>USB-211-BCW</td>
<td>XUNPU</td>
<td>LCSC</td>
<td>C720520</td>
<td align="right">0.4656</td>
</tr>
</table>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">*7、大赛LOGO验证</h3>
<hr class="horizontal-splitline normal-bold-2">
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"><img src="//image.lceda.cn/pullimage/EEuR0jpYsI393Xm5bPAKhQD7TuEeytNekaxg1YSi.jpeg" alt="" width="4055" height="2047"></p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;">* 8、演示您的项目并录制成视频上传</h3>
<hr class="horizontal-splitline normal-bold-2">
<p style="line-height: 1.8;"> </p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"><span style="color: #95a5a6; font-size: 14px;">视频要求:请横屏拍摄,分辨率不低于1280×720,格式Mp4/Mov,单个视频大小限100M内;</span></p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"><span style="color: #95a5a6; font-size: 14px;">视频标题:立创电赛:{项目名称}-{视频模块名称};如立创电赛:《自动驾驶》-团队介绍。</span></p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> </p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"><span style="font-size: 14px;">更多详情:<a href="/posts/15a52db9fd7d40c492eb505280278e45" target="_blank">https://diy.szlcsc.com/posts/15a52db9fd7d40c492eb505280278e45</a></span></p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height: 1.8;"> </p>
</div>
评论(4)