FireBeetle "软"USB Host Shield

喜欢军事的朋友一定经常听过这句话,这就是“只要推力大,板砖也能飞上天”。实际上,这句话并非玩笑之语,确有出处。当年,F-22是从“先进战术战斗机”(简称ATF)计划发展而来的。早期,好几家公司一起竞标,分别是波音,通用动力,洛克希德,诺思罗普,和麦道公司。大家提概念设计方案。结果,可能是因为洛克希德曾经设计出F-117隐形飞机的缘故,走老路当然是最轻松的,所以,洛克希德最初提出的F-22前身方案,它就像是F-117的放大版。设计跟F-117这个怪胎一样,为了隐身性能,以牺牲空气动力学为代价,飞机设计总重36吨。后来,有个人是这么评价这种早期设计的,他就是洛克希德在ATF计划中的项目经理巴特·奥斯本(bart osborne),1998年,一家杂志对奥斯本进行采访【参考1】,而他是这样说的:“我们知道,这个设计将会存在严重的超音速问题,我们的设计当然可以超音速飞行,但肯定蠢得像猪。显然,只要推力大,板砖也能飞上天(With enough power, you can make a brick fly)”

这句话出处就是这么来的,他当时想表达的本意是这样的:我们设计的这种飞机, 在高空高速上肯定会存在很多问题,当然,这并不是说,这种设计不能超音速飞行,完全不是,因为只要推力,你也能让砖头飞上天,也能它超音速。

巴特·奥斯本的评价很中肯,洛克希德提交这个概念设计方案后,美国空军对这种设计的评价最差,在其他7个项目设计中,排倒数第一。【参考1】

对于我们来说,只要 CPU 足够快,GPIO 足够快,能够模拟出各种总线,最常见的是软串口,再稍微复杂一些的是I2C, SPI。最近有一个项目使用 ESP32 来模拟 USB Host,当前因为 GPIO 不够快,目前只能解析键盘鼠标这样的低速设备(Low Speed)。项目地址是:https://github.com/sdima1357/esp32_usb_soft_host 当然,对于Arduino 玩家来说可以直接使用下面这个库 :https://github.com/tobozo/ESP32-USB-Soft-Host

库可以同时支持4个 USB Host, 这里我设计一个 FireBeetle Shield 提供了 2个 USB Host。具体电路如下:

PCB 如下:

Soft USB Host 和 FireBeetle

可以看到板子上有2个 USB 母头和1个USB 公头,其中母头是给 USB Host使用的,公头是为了在供电不足情况下通过充电宝之类直接对设备供电。库可以支持4组USB Host ,经过实验在FireBeetle上可以使用下面的组合:

16131925
17151826

测试代码:

#include <ESP32-USBSoftHost.hpp>
#include "usbkbd.h" // KeyboardReportParser

  // default pins tested on FireBeetle
  // +  16 13 19 25
  // -  17 15 18 26
  #define DP_P0  25  // always enabled
  #define DM_P0  26  // always enabled
  #define DP_P1  19 // -1 to disable
  #define DM_P1  18 // -1 to disable
  #define DP_P2  -1 // -1 to disable
  #define DM_P2  -1 // -1 to disable
  #define DP_P3  -1 // -1 to disable
  #define DM_P3  -1 // -1 to disable



static void my_USB_DetectCB( uint8_t usbNum, void * dev )
{
  sDevDesc *device = (sDevDesc*)dev;
  printf("New device detected on USB#%d\n", usbNum);
  printf("desc.bcdUSB             = 0x%04x\n", device->bcdUSB);
  printf("desc.bDeviceClass       = 0x%02x\n", device->bDeviceClass);
  printf("desc.bDeviceSubClass    = 0x%02x\n", device->bDeviceSubClass);
  printf("desc.bDeviceProtocol    = 0x%02x\n", device->bDeviceProtocol);
  printf("desc.bMaxPacketSize0    = 0x%02x\n", device->bMaxPacketSize0);
  printf("desc.idVendor           = 0x%04x\n", device->idVendor);
  printf("desc.idProduct          = 0x%04x\n", device->idProduct);
  printf("desc.bcdDevice          = 0x%04x\n", device->bcdDevice);
  printf("desc.iManufacturer      = 0x%02x\n", device->iManufacturer);
  printf("desc.iProduct           = 0x%02x\n", device->iProduct);
  printf("desc.iSerialNumber      = 0x%02x\n", device->iSerialNumber);
  printf("desc.bNumConfigurations = 0x%02x\n", device->bNumConfigurations);
  // if( device->iProduct == mySupportedIdProduct && device->iManufacturer == mySupportedManufacturer ) {
  //   myListenUSBPort = usbNum;
  // }
}


static void my_USB_PrintCB(uint8_t usbNum, uint8_t byte_depth, uint8_t* data, uint8_t data_len)
{
  // if( myListenUSBPort != usbNum ) return;
  printf("in: ");
  for(int k=0;k<data_len;k++) {
    printf("0x%02x ", data[k] );
  }
  printf("\n");
}

usb_pins_config_t USB_Pins_Config =
{
  DP_P0, DM_P0,
  DP_P1, DM_P1,
  DP_P2, DM_P2,
  DP_P3, DM_P3
};


void setup()
{

  Serial.begin(115200);
  delay(200);
  Serial.println("USB Test");
  delay(1000);

  USH.init( USB_Pins_Config, my_USB_DetectCB, my_USB_PrintCB );

}

void loop()
{
  vTaskDelete(NULL);
}


运行结果, 上面是输出的Descriptor,下面是收到的鼠标数据:

目前这个库还存在一些兼容性问题,并非所有的鼠标都能正常工作。我测试了微软的IO1.01 是可以正常工作的。

参考:

  1. http://www.codeonemagazine.com/f22_article.html?item_id=179 Design Evolution Of The F-22 Raptor
  2. http://www.nanshannews.cn/cj/cj9059.html

发表评论

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