
前一篇写了正在开发中M60键盘的功耗,这篇就来聊一聊键盘的延迟~
键盘按键的延迟,即按下按键到电脑响应按键之间的时间差,其影响因素包括:通信协议限制(USB和蓝牙)、矩阵矩阵扫描方式(周期扫描或者中断检测扫描)、防抖方式、键盘微处理器处理速度、电脑处理速度,甚至键程……
其中,关键因素是通信协议限制,现在广泛使用的是USB和蓝牙,其它方式很多也是通过USB转换,同样受到USB限制。
测键盘的延迟比较难,简化一点,我们测一测的键盘响应速度,从响应速度大致可以了解键盘的延迟。这里用跑Python的M60键盘在Surface Book上测试,先说结论:
M60键盘采用USB连接,可以稳定地每 1.1~1.2ms 处理一个按键事件(按下或释放);而采用低功耗蓝牙连接,则可以大概 3ms 处理一个按键事件,但波动相对大。
USB对延迟的影响
键盘是USB中的标准 HID (Human Input Device) 设备,HID设备采用USB协议的中断传输方式 (Interrupt Transfer),虽然名字中有中断二字,但实际上是电脑以大致的周期轮询设备,其中,最小的轮询间隔 (即中断间隔,Interrupt Interval) 可设置为1ms,即最高频率为1000Hz。因此,很多游戏键盘以1000Hz矩阵扫描频率,高了也没多少用。
怎么测键盘的延迟呢?这里设计了一个小实验:
在Python键盘上,模拟字母a到z依次按下、释放、发送给电脑,在键盘端测量每次按键扫描、发送的处理时间,同时也在电脑端测量a到z按下、释放的时间间隔。
其中,键盘上的程序是这样的:
import time
import usb_hid
from matrix import Matrix
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
matrix = Matrix()
keyboard = Keyboard(usb_hid.devices)
def alphabet_test():
data = []
t = time.monotonic_ns()
for i in range(26):
t1 = time.monotonic_ns()
matrix.scan()
keyboard.press(Keycode.A + i)
t2 = time.monotonic_ns()
matrix.scan()
keyboard.release(Keycode.A + i)
t3 = time.monotonic_ns()
data.append((t2 - t1) // 100000 / 10.)
data.append((t3 - t2) // 100000 / 10.)
average = (time.monotonic_ns() - t) // (26 * 2 * 100000) / 10.
print('average: {}, max: {}, min: {}, data: {}'.format(average, max(data), min(data), data))
while True:
n = matrix.wait(10)
if not n:
continue
keys = [matrix.get() for _ in range(n)]
if keys[0] & 0x80:
continue
alphabet_test()
电脑端使用了keyboard库,代码如下:
import time
import keyboard
data = lambda: None
data.events = None
# {"event_type": "down", "scan_code": 29, "name": "ctrl", "time": 0, "is_keypad