3

我有一个项目需要定期读取外部 IMU 陀螺仪数据并将数据发送到 Android 手机。

我正在使用一个 teensy 2.0 板通过 I2C 查询 IMU,并使用原始 HID 通过 USB 发送它。我正在使用在 teensyduino 的 usb_rawhid 的 usb_api.h 中声明的 RawHID 变量。

我已经读到使用中断传输的全速 USB 可以有 1ms 的最大延迟,并且希望达到这个 1ms 的最大延迟。我不确定要寻找什么来实现这个最大延迟,并且想请教一下指针。我的最终目标是每 2 毫秒(500 赫兹)接收一次陀螺仪数据。

我知道的一些事情可能是一个问题:

1)我已将 RAWHID_TX_SIZE 更改为 6 个字节(陀螺仪值我只需要 6 个字节),并将 RAWHID_TX_INTERVAL 设置为 1 ms(最快)。当前在我不需要的接口中指定了一个 OUT 端点,我不确定删除它是否可以改善延迟。

2) Android 将 teensy 识别为“hiddev USB HID v1.11 设备”。我不确定这是否是完整的原始 HID 或者它是否正在尝试解析它。Teensy 使用上面指定的原始 HID。

3) 在 Android 中,一个特定的线程试图在 UsbRequest 上排队(),然后是 requestWait()。数据到达时的处理非常快(即:将其存储在全局变量中),但我受制于线程调度程序。

所以这些是我知道的一些指针(并且不完全确定它们如何影响最大延迟)。我很想听听人们的反馈,并可能指出如何改善我的最大 USB 延迟的新方向。寻找有关减少 USB 中断传输延迟的信息是很可怕的。

4

1 回答 1

4

对于 USB,一切都是轮询。每 1 毫秒,您就有一个“帧”,由一个或多个传输描述符组成,其中每个传输描述符告诉 USB 控制器轮询哪个 USB 设备。

通常,USB 控制器以传输描述符开始帧以进行中断传输。这意味着使用单个中断传输描述符(几乎)可以保证每毫秒轮询一次。如果您的设备有要发送的中断,则在轮询时将其返回;所以你会得到 1 毫秒的延迟作为最坏的情况。

可以要求 USB 控制器不那么频繁地轮询设备(例如同步传输)。也可以要求 USB 控制器在同一个 1ms 帧内多次轮询设备;但是,由于它通常首先会中断传输描述符,因此您希望几乎同时轮询两次,并且之间存在“几乎 1 ms”的间隙,因此这无助于最坏情况下的延迟。

大多数情况下,据我所知,对于“< 2 ms”的要求,USB 规范/协议、USB 控制器、内核的 USB 控制器驱动程序和内核的 USB HID 驱动程序根本不是问题。问题是及时将数据从 USB HID 驱动程序获取到用户空间进程/线程。

不幸的是,Linux/Andriod 不是实时操作系统。它不提供任何保证。您将受制于线程调度程序(也许还有 JVM 的垃圾收集器)。您可能对此无能为力。

我建议首先找出为什么需要每 2 毫秒接收一次陀螺仪数据。举个简单的例子,你可以给陀螺仪数据添加一个时间戳,让接收线程从这些时间戳“重建历史”,这样接收线程就不需要低延迟了吗?

于 2015-01-16T05:45:18.107 回答