我有一个项目需要定期读取外部IMU陀螺仪数据并将数据发送到Android手机。
我正在使用一个小巧的2.0主板通过I2C查询IMU并使用原始HID通过USB发送它。我正在使用RawHID变量,该变量在teensyduino的usb_rawhid的usb_api.h中声明。
我已经读过使用中断传输的全速USB可能具有1ms的最大延迟,并且希望实现这1ms的最大延迟。我不确定要寻求什么来实现这个最大延迟,并希望了解指针。我的最终目标是每2 ms(500 Hz)接收一次陀螺仪数据。
我所知道的一些事情可能是一个问题:
1)我已将RAWHID_TX_SIZE更改为6个字节(陀螺仪值仅需6个字节),RAWHID_TX_INTERVAL设置为1 ms(最快)。 当前在我不需要的界面中指定了OUT端点,我不确定删除它是否可以改善延迟。
2)Android将teensy识别为" hiddev USB HID v1.11 Device"。我不确定这是完整的原始HID还是它试图解析它。 Teensy正在使用上面指定的原始HID。
3)在Android中,一个特定的线程试图在UsbRequest上排队(),然后是requestWait()。数据到达时的处理速度非常快(即:将其存储在全局变量中),但我受线程调度程序的支配。
所以这些是我所知道的一些指针(并不完全确定它们如何影响最大延迟)。我很乐意听取人们的反馈,并指出如何改善我的最大USB延迟的新方向。查找有关减少中断传输的USB延迟的信息很吓人。
答案 0 :(得分:3)
对于USB,它都是轮询。每1毫秒你有一个"帧"由无或多个传输描述符组成,其中每个传输描述符告诉USB控制器轮询哪个USB设备。
通常,USB控制器使用传输描述符开始帧以进行中断传输。这意味着,使用单个中断传输描述符,您(几乎)可以保证每ms进行一次轮询。如果你的设备有一个要发送的中断,它会在轮询时返回它;所以你最糟糕的情况是你会得到1毫秒的延迟。
可以要求USB控制器不经常轮询设备(例如等时传输)。还可以要求USB控制器在相同的1ms帧中多次轮询设备;然而,因为它通常会中断转移描述符,所以你几乎可以在几乎同时使用"几乎1 ms"之间存在差距,因此无法帮助解决最坏情况延迟。
大多数情况下,据我所知,对于"< 2毫秒"要求USB规格/协议,USB控制器,内核的USB控制器驱动程序和内核的USB HID驱动程序根本不是问题。问题是及时将USB HID驱动程序中的数据发送到用户空间进程/线程。
不幸的是,Linux / Andriod不是一个实时操作系统。它不提供任何保证。您将受到线程调度程序(也可能是JVM的垃圾收集器)的支配。你可能无能为力。
我建议您首先找出每2 ms接收一次陀螺仪数据的原因。举一个简单的例子,你可以为陀螺仪数据添加一个时间戳,让接收线程重建历史记录"从那些时间戳开始,接收线程根本不需要低延迟?