当前位置: 首页 > news >正文

QMK启用摇杆和鼠标按键功能

  虽然选择了触摸屏,我仍选择为机械键盘嵌入摇杆模块,这本质上是对"操作连续性"的执着。
  值得深思的是,本次开发过程中借助DeepSeek的代码生成与逻辑推理,其展现的能力已然颠覆传统编程范式,需求描述可自动转化为功能实现,算法优化能自主完成多目标博弈,这昭示着技术生产关系的根本性变革。
  技术演进正在重构价值坐标系,边缘计算设备通过蒸馏更好的模型实现端侧智能,使AI能力呈指数级渗透产业格局,算力资本形成的新型生产资料,正在重塑技术话语权分配机制,工程师的核心竞争力将从代码实现转向需求抽象、系统架构与伦理把控在这场人机协同的认知革命,真正的危机并非技术替代,而是思维范式的停滞。
  当AI解构了执行层的技术壁垒,人类智慧的战场必将向更高维度迁移——那些涉及跨领域创新、价值判断与复杂系统设计的领域,正是技术人亟待开垦的新边疆,但愿技术人可以在这样的狭缝中获得存在的意义。
  言归正传还是回到我们的QMK键盘增加摇杆功能,首先要了解一下QMK 生成键盘的整体文件结构:
qmk_firmware/keyboards/demo_keyboard/
├── config.h
├── keymaps/
│ └── default/
│ ├── keymap.c
├── rules.mk
└── keyboard.json
keyboard.json功能:定义键盘的硬件配置、布局、功能和元数据。示例
rules.mk功能:定义编译选项和功能开关。
config.h功能:定义键盘的硬件配置和宏。
keymaps/default/keymap.c功能:定义默认键位布局,开启自定义功能。

所以增加摇杆和鼠标就需要在这些文件里面进行修改

在rules.mk中启用摇杆和鼠标按键功能

POINTING_DEVICE_ENABLE = yes
POINTING_DEVICE_DRIVER = analog_joystick
MOUSEKEY_ENABLE = yes
# DEBUG_ENABLE = yes
# CONSOLE_ENABLE = yes  # 启用调试输出

在config.h中添加摇杆和鼠标键的读取对应端口

/*
Copyright 2025 <JohnsonLv>This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/#pragma once#define ANALOG_JOYSTICK_X_AXIS_PIN GP26
#define ANALOG_JOYSTICK_Y_AXIS_PIN GP27
#define MOUSE_BTN1_PIN GP15

在keymap.c中添加,保留以前的键盘键的映射,然后添加一些关于摇杆的函数

/// Copyright 2023 QMK
// SPDX-License-Identifier: GPL-2.0-or-later#pragma once#include QMK_KEYBOARD_H
#include "pointing_device.h"
#include "print.h"
#include "timer.h"  // 用于 timer_read32 和 timer_elapsed32// 定义摇杆的灵敏度
#define JOYSTICK_SENSITIVITY 1static bool debounce = false;
static uint32_t debounce_timer = 0;// 初始化独立按键的 GPIO
void keyboard_post_init_user(void) {setPinInputHigh(MOUSE_BTN1_PIN);  // 设置为输入模式,启用内部上拉电阻
}// 新增参数定义(需根据实际需求调整)
#define MAX_CURSOR_SPEED  10  // 最大光标速度
#define SPEED_REGULATOR    3   // 速度调节系数// 非线性映射函数(基于 IBM 专利逻辑)
void joystick_ibm_algorithm(int16_t x, int16_t y, int16_t* x_out, int16_t* y_out) {static int16_t z_prev = 0;  // 静态变量保存上一次的 z 值// --- 核心算法逻辑 ---// 1. 计算近似平方根的 z 值int16_t ax = abs(x);int16_t ay = abs(y);int16_t z = ax + ay - ((2 * (ax < ay ? ax : ay)) / 3);// 2. 动态调整光标移动if (z > 4) {// 计算动态变化的 zi 值(包含释放补偿)int16_t zi = (z - z_prev) * 6 + z;// 计算最终坐标(避免除以零)int16_t x_calc = (zi == 0) ? 0 : (x * z * MAX_CURSOR_SPEED) / (zi * SPEED_REGULATOR);int16_t y_calc = (zi == 0) ? 0 : (y * z * MAX_CURSOR_SPEED) / (zi * SPEED_REGULATOR);*x_out = x_calc;*y_out = y_calc;} else {*x_out = 0;*y_out = 0;}// 3. 保存当前 z 值供下次使用z_prev = z;
}// 处理独立按键和摇杆的函数
void my_process_joystick(void) {// 获取摇杆的 X/Y 轴值int16_t x_raw= joystick_state.axes[0];int16_t y_raw= joystick_state.axes[1];// 创建鼠标报告report_mouse_t mouse_report = {0};// 应用 IBM 算法int16_t x_mapped, y_mapped;joystick_ibm_algorithm(x_raw, y_raw, &x_mapped, &y_mapped);// 检测独立按键状态(按下时为低电平)bool btn_state = !readPin(MOUSE_BTN1_PIN);  // 按下时为 true// 消抖逻辑if (btn_state && !debounce) {debounce = true;debounce_timer = timer_read32();mouse_report.buttons |= KC_BTN1;  // 触发左键} else if (!btn_state && debounce) {if (timer_elapsed32(debounce_timer) > 5) {  // 消抖时间 5msdebounce = false;mouse_report.buttons &= ~KC_BTN1;  // 释放左键}}// 发送鼠标报告pointing_device_set_report(mouse_report);pointing_device_send();
}// 键盘矩阵扫描后的钩子函数
void matrix_scan_user(void) {my_process_joystick();
}// 键盘布局定义(无需为独立按键分配矩阵键位)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {[0] = LAYOUT_numpad_4x4(KC_1,   KC_2,   KC_3,   KC_4,KC_5,   KC_6,   KC_7,   KC_8,KC_9,   KC_0,   KC_A,   KC_B,KC_C,   KC_D,   KC_BTN2, KC_BTN3  // 保持矩阵中的键位不变)
};

  在上面的这段算法中借用了 https://patents.google.com/patent/US5570111A, IBM的一个专利技术

以下是这段基于 IBM 专利的摇杆算法的逐层解析,我将用 「物理直觉 → 数学实现 → 代码表达」 的逻辑链解释其精妙之处:

1. 近似矢量长度(模拟平方根)物理需求:

需要计算摇杆偏移的「矢量长度」,但避免耗时的真实平方根运算。数学实现:
通过线性组合近似替代 x 2 + y 2 \sqrt{x² + y²} x2+y2 ,专利给出的公式: z = ∣ x ∣ + ∣ y ∣ − ( 2 ∗ m i n ( ∣ x ∣ , ∣ y ∣ ) ) / 3 z = |x| + |y| - (2 * min(|x|, |y|)) / 3 z=x+y(2min(x,y))/3
代码实现:

int16_t ax = abs(x);
int16_t ay = abs(y);
int16_t z = ax + ay - ((2 * (ax < ay ? ax : ay)) / 3);

效果说明:当摇杆沿对角线移动时(x=y),公式简化为 ( 4 / 3 ) ∗ x (4/3) * x (4/3)x,接近真实平方根 2 ∗ x ≈ 1.414 x \sqrt2*x ≈ 1.414x 2 x1.414x当摇杆沿单轴移动时(如 x=0),公式退化为 y,与真实值一致平衡了计算效率和准确性


2. 动态响应补偿(预测释放动作)

物理需求
当用户松开摇杆时,光标会因惯性继续移动,需要模拟「减速回弹」效果。

数学实现
通过差分计算摇杆速度变化:
z i = z + 6 ∗ ( z − z p r e v ) zi = z + 6*(z - z_{prev}) zi=z+6(zzprev)
z p r e v z_{prev} zprev是上一帧的 z 值)

代码实现

int16_t zi = (z - z_prev) * 6 + z; // 放大变化量的影响

效果说明

  • 快速释放时(z 急剧减小): z i zi zi会远小于 z z z,导致 x c a l c / y c a l c x_{calc}/y_{calc} xcalc/ycalc分母增大,光标减速
  • 保持摇杆时(z 稳定): z i ≈ z zi ≈ z ziz,光标匀速移动
  • 推动摇杆时(z 增大): z i > z zi > z zi>z,分母增大,光标加速更平缓

3. 非线性速度映射

物理需求
摇杆偏移量与光标速度呈非线性关系(小偏移精细控制,大偏移快速移动)。

数学实现
速度公式:

x_calc = (x * z * MAX_CURSOR_SPEED) / (zi * SPEED_REGULATOR)

代码实现

int16_t x_calc = (zi == 0) ? 0 : (x * z * MAX_CURSOR_SPEED) / (zi * SPEED_REGULATOR);

参数控制

参数作用调整建议
MAX_CURSOR_SPEED最大移动速度值越大光标移动越快
SPEED_REGULATOR整体灵敏度调节值越大光标移动越慢
6 (zi的系数)惯性响应强度值越大释放时的减速越明显

4. 死区处理与噪声过滤

物理需求
消除摇杆中心位置的微小抖动。

数学实现
z ≤ 4 时强制归零:

if (z > 4) { ... } else { *x_out=0; *y_out=0; }

效果说明

  • 过滤摇杆电阻器的噪声
  • 提供明确的中心死区

整体算法流程图

原始输入 (x,y)  ↓  
计算近似矢量长度 z  ↓  
动态补偿 → 计算 zi (包含惯性预测)  ↓  
非线性映射 → 输出 (x_calc, y_calc)  ↓  
保存 z 值 → 供下一帧使用

实际调试技巧

  1. 参数联动调整

    • 先固定 SPEED_REGULATOR=1,调整 MAX_CURSOR_SPEED 确定最大速度
    • 然后增大 SPEED_REGULATOR 微调灵敏度
    • 最后调整 zi 的系数(代码中的 6)控制惯性效果
  2. 边界保护
    添加范围限制防止溢出:

  x_calc = MAX(-127, MIN(x_calc, 127)); // 确保在鼠标协议范围内

这个算法通过巧妙的近似和差分计算,在极低的计算开销下实现了符合人体工学的光标控制特性,正是这种「用简单数学模拟复杂物理直觉」的设计,让它成为经典。

在这里插入图片描述

相关文章:

QMK启用摇杆和鼠标按键功能

虽然选择了触摸屏&#xff0c;我仍选择为机械键盘嵌入摇杆模块&#xff0c;这本质上是对"操作连续性"的执着。   值得深思的是&#xff0c;本次开发过程中借助DeepSeek的代码生成与逻辑推理&#xff0c;其展现的能力已然颠覆传统编程范式&#xff0c;需求描述可自动…...

Unity实现按键设置功能代码

一、前言 最近在学习unity2D&#xff0c;想做一个横版过关游戏&#xff0c;需要按键设置功能&#xff0c;让用户可以自定义方向键与攻击键等。 自己写了一个&#xff0c;总结如下。 二、界面效果图 这个是一个csv文件&#xff0c;准备第一列是中文按键说明&#xff0c;第二列…...

基于物联网技术的实时数据流可视化研究(论文+源码)

1系统方案设计 根据系统功能的设计要求&#xff0c;展开基于物联网技术的实时数据流可视化研究设计。如图2.1所示为系统总体设计框图&#xff0c;系统以STM32单片机做为主控制器&#xff0c;通过DHT11、MQ-2、光照传感器实现环境中温湿度、烟雾、光照强度数据的实时检测&#x…...

list容器(详解)

1. list的介绍及使用 1.1 list的介绍&#xff08;双向循环链表&#xff09; https://cplusplus.com/reference/list/list/?kwlist&#xff08;list文档介绍&#xff09; 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭…...

Elasticsearch基本使用详解

文章目录 Elasticsearch基本使用详解一、引言二、环境搭建1、安装 Elasticsearch2、安装 Kibana&#xff08;可选&#xff09; 三、索引操作1、创建索引2、查看索引3、删除索引 四、数据操作1、插入数据2、查询数据&#xff08;1&#xff09;简单查询&#xff08;2&#xff09;…...

17.3.4 颜色矩阵

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 17.3.4.1 矩阵基本概念 矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合&#xff0c;类似于数组。 由…...

FPGA 时钟多路复用

时钟多路复用 您可以使用并行和级联 BUFGCTRL 的组合构建时钟多路复用器。布局器基于时钟缓存 site 位置可用性查找最佳布局。 如果可能&#xff0c;布局器将 BUFGCTRL 布局在相邻 site 位置中以利用专用级联路径。如无法实现&#xff0c;则布局器将尝试将 BUFGCTRL 从…...

机器学习10

自定义数据集 使用scikit-learn中svm的包实现svm分类 代码 import numpy as np import matplotlib.pyplot as pltclass1_points np.array([[1.9, 1.2],[1.5, 2.1],[1.9, 0.5],[1.5, 0.9],[0.9, 1.2],[1.1, 1.7],[1.4, 1.1]])class2_points np.array([[3.2, 3.2],[3.7, 2.9],…...

【Block总结】CoT,上下文Transformer注意力|即插即用

一. 论文信息 标题: Contextual Transformer Networks for Visual Recognition论文链接: arXivGitHub链接: https://github.com/JDAI-CV/CoTNet 二. 创新点 上下文Transformer模块&#xff08;CoT&#xff09;: 提出了CoT模块&#xff0c;能够有效利用输入键之间的上下文信息…...

linux库函数 gettimeofday() localtime的概念和使用案例

在Linux系统中&#xff0c;gettimeofday() 和 localtime() 是两个常用的时间处理函数&#xff0c;分别用于获取高精度时间戳和将时间戳转换为本地时间。以下是它们的概念和使用案例的详细说明&#xff1a; 1. gettimeofday() 函数 概念 功能&#xff1a;获取当前时间&#xf…...

编程题-电话号码的字母组合(中等)

题目&#xff1a; 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 解法一&#xff08;哈希表动态添加&#xff09;&#x…...

EasyExcel使用详解

文章目录 EasyExcel使用详解一、引言二、环境准备与基础配置1、添加依赖2、定义实体类 三、Excel 读取详解1、基础读取2、自定义监听器3、多 Sheet 处理 四、Excel 写入详解1、基础写入2、动态列与复杂表头3、样式与模板填充 五、总结 EasyExcel使用详解 一、引言 EasyExcel 是…...

基于“蘑菇书”的强化学习知识点(二):强化学习中基于策略(Policy-Based)和基于价值(Value-Based)方法的区别

强化学习中基于策略&#xff08;Policy-Based&#xff09;和基于价值&#xff08;Value-Based&#xff09;方法的区别 摘要强化学习中基于策略&#xff08;Policy-Based&#xff09;和基于价值&#xff08;Value-Based&#xff09;方法的区别1. 定义与核心思想(1) 基于策略的方…...

民法学学习笔记(个人向) Part.2

民法学学习笔记(个人向) Part.2 民法始终在解决两个生活中的核心问题&#xff1a; 私法自治&#xff1b;交易安全&#xff1b; 3. 自然人 3.4 个体工商户、农村承包经营户 都是特殊的个体经济单位&#xff1b; 3.4.1 个体工商户 是指在法律的允许范围内&#xff0c;依法经…...

物业管理系统源码驱动社区管理革新提升用户满意度与服务效率

内容概要 在当今社会&#xff0c;物业管理正面临着前所未有的挑战&#xff0c;尤其是在社区管理方面。人们对社区安全、环境卫生、设施维护等日常生活需求愈发重视&#xff0c;物业公司必须提升服务质量&#xff0c;以满足居民日益增长的期望。而物业管理系统源码的出现&#…...

租房管理系统助力数字化转型提升租赁服务质量与用户体验

内容概要 随着信息技术的快速发展&#xff0c;租房管理系统正逐渐成为租赁行业数字化转型的核心工具。通过全面集成资产管理、租赁管理和物业管理等功能&#xff0c;这种系统力求为用户提供高效便捷的服务体验。无论是工业园、产业园还是写字楼、公寓&#xff0c;租房管理系统…...

Ollama教程:轻松上手本地大语言模型部署

Ollama教程&#xff1a;轻松上手本地大语言模型部署 在大语言模型&#xff08;LLM&#xff09;飞速发展的今天&#xff0c;越来越多的开发者希望能够在本地部署和使用这些模型&#xff0c;以便更好地控制数据隐私和计算资源。Ollama作为一个开源工具&#xff0c;旨在简化大语言…...

Baklib推动数字化内容管理解决方案助力企业数字化转型

内容概要 在当今信息爆炸的时代&#xff0c;数字化内容管理成为企业提升效率和竞争力的关键。企业在面对大量数据时&#xff0c;如何高效地存储、分类与检索信息&#xff0c;直接关系到其经营的成败。数字化内容管理不仅限于简单的文档存储&#xff0c;更是整合了文档、图像、…...

DeepSeek-R1 论文. Reinforcement Learning 通过强化学习激励大型语言模型的推理能力

论文链接&#xff1a; [2501.12948] DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning 实在太长&#xff0c;自行扔到 Model 里&#xff0c;去翻译去提问吧。 工作原理&#xff1a; 主要技术&#xff0c;就是训练出一些专有用途小模型&…...

DOM 操作入门:HTML 元素操作与页面事件处理

DOM 操作入门:HTML 元素操作与页面事件处理 DOM 操作入门:HTML 元素操作与页面事件处理什么是 DOM?1. 如何操作 HTML 元素?1.1 使用 `document.getElementById()` 获取单个元素1.2 使用 `document.querySelector()` 和 `document.querySelectorAll()` 获取多个元素1.3 创建…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...

李沐--动手学深度学习--GRU

1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...

C++ 类基础:封装、继承、多态与多线程模板实现

前言 C 是一门强大的面向对象编程语言&#xff0c;而类&#xff08;Class&#xff09;作为其核心特性之一&#xff0c;是理解和使用 C 的关键。本文将深入探讨 C 类的基本特性&#xff0c;包括封装、继承和多态&#xff0c;同时讨论类中的权限控制&#xff0c;并展示如何使用类…...