前文:本文赠给正在开发如何精确测试鼠标DPI功能的码友
(一)术语简介
1.鼠标DPI介绍:
鼠标 DPI(Dots Per Inch,每英寸点数)是衡量鼠标精度的一个指标。
一般来说,如果已知鼠标移动的物理距离(通常以英寸为单位)和鼠标指针在屏幕上移动的像素距离,可以通过以下公式计算鼠标 DPI:
DPI = (像素距离 / 物理距离mm) * 25.4(因为 1 英寸等于 25.4 毫米)。
例如,鼠标在平面上移动了 2mm,屏幕上的鼠标指针移动了 800 像素,那么 DPI = (800 / 2) * 25.4 = 10160。
需要注意的是,不同的鼠标可能有不同的测量方法和精度,并且一些鼠标可以通过软件调整 DPI 设置。
此外,上述计算假设鼠标的移动是完全直线的(当然斜线可以采用勾股定理计算),实际情况可能会更加复杂。
2.单位换算:
1毫米=0.0393701英寸
1厘米=0.3937008英寸
(二)专业设备
1.奎享雕刻写字机器人
项目采用串口发送指令的方式向写字机中发送执行指令,以获取精确的移动距离
2.相关的数控G指令代码:
(1)定原点
G10 P0 L20 X0.000Y0.000Z0.000F1000\rG21\rG90\rF1000\rG1G90 Z0.0F1000\r
(2)来回画直线
G1 X30.000Y0.000F800\rG1 X0.00Y0.000F800\r
(3)循环画圆(半径设为1mm, 周长可以自己计算从而得出移动速度即指令的执行周期)
G2 X1.000Y1.000R1.000F800\rG2 X2.000Y0.000R1.000F800\rG2 X1.000Y-1.000R1.000F800\rG2 X0.000Y0.000R1.000F800\r
3.特殊字符规避
注意G指令发送时是否会受\r等特殊字符的影响,特殊字符如下需自己代码规避
\f 0x0c 换页符
\a 0x07 响铃符
\b 0x08 退格符
\t 0x09 水平制表符
\n 0x0a 换行键
\v 0x0b 垂直制表符
\r 0x0d 回车键
4.下面是我写的一个多线程
class LoopDpiSendCmdThread(QtCore.QThread):
cmd_sig = QtCore.pyqtSignal(str) # 命令发送信号
clear_info_sig = QtCore.pyqtSignal() # 清空日志信号
stop_thread = QtCore.pyqtSignal() # 停止线程信号
init_cmd = QtCore.pyqtSignal() # 首次命令信号
point_sig = QtCore.pyqtSignal() # 点坐标信号
def __init__(self, loop_data_dict, serial_object):
super().__init__()
self.loop_data_dict = loop_data_dict
self.serial_object = serial_object
self.interval_task = self.send_interval = None
def run(self):
"""异步执行的主线程"""
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
task = [self.start_loop_send_cmd_worker(self.loop_data_dict)]
# 根据输入数据创建多任务数
loop.run_until_complete(asyncio.gather(*task))
async def start_loop_send_cmd_worker(self, data_dict):
"""启动同步线程: 多任务并行执行"""
loop_times = data_dict.get("loop_times")
cmd_list = data_dict.get("func_cmd").split("\r")[:-1]
# 1.定点命令发送
self.cmd_sig.emit(data_dict.get("origin_cmd"))
# 等待串口返回结果响应完成(该步骤会阻塞主线程, 故放在子线程中)
self.serial_object.waitForReadyRead(100)
# 首次命令发送完成
self.init_cmd.emit()
loop_count = 0
while True:
# 统计循环次数
loop_count += 1
# awaken_times为0表示持续进行唤醒操作, 不为0表示唤醒指定次数后退出唤醒
if loop_times == 0:
if loop_count >= 1000:
self.clear_info_sig.emit()
loop_count = 0
else:
if loop_count > loop_times:
self.stop_thread.emit()
break
try:
# 发送指令
for cmd_str in cmd_list:
# 触发信号, 发送命令信息
self.cmd_sig.emit(cmd_str)
# 等待串口返回结果响应完成(该步骤会阻塞主线程, 故放在子线程中)
self.serial_object.waitForReadyRead(50)
# GPIO指令的延时
await asyncio.sleep(data_dict.get("send_interval"))
if data_dict.get("dpi_delay"):
self.point_sig.emit()
except Exception as e:
print(e)