基于ESP32-C3构建一款无需重新刷写的无线宏键盘
通过USB自动配置的BLE宏键盘
在ESP32-C3上集成了三个按键和一个编码器。使用蓝牙进行输入,通过USB完成设置,配合桌面应用,你再也不用重刷固件来更改快捷键。
为什么需要这个
大多数DIY宏键盘都是USB HID设备。插入后即可输入,但会一直绑定到连接的设备上。这在你希望将键盘放在笔记本电脑旁的桌面上时尤其明显——如果电脑已经布满线缆,或者你想在笔记本和平板之间切换而无需断开任何连接时,就会遇到问题。
蓝牙HID解决了这个问题,却带来了另一个难题:一旦键盘变为无线,就很难直接修改按键功能。大多数BLE版本会在固件中硬编码宏指令,因此每次想要改变按钮2的功能(比如从粘贴改为静音),你都需要重新打开Arduino IDE,编辑字符串,然后重新刷写。
Flo则将这两项任务分担给两种传输方式:蓝牙负责按键输入,USB负责配置管理。将键盘插入任意设备,打开桌面应用程序,输入每个按键要执行的操作,然后按下发送键。宏就会被写入闪存并保持在其中。拔下键盘后,通过蓝牙连接仍可继续使用,并保留新的绑定设置。
功能说明
三个按键和一个带按压功能的旋转编码器,共可设置四个可分配的宏。旋转编码器可控制系统音量。
宏是一个简单的字符串,例如 ctrl+c、win+e、f5、esc,或像 hello 这样的单词,会逐字符输入。固件会解析字符串前缀中的修饰符,并将最后一个 + 后面的内容视为主按键。
默认设置为 a、b、ctrl+c 和 ctrl+v,这些键仅用于新刷机后的初始状态,以便用户在配置前能立即看到效果。
两种传输方式
通过 USB,板卡运行 115200 波特率的行协议:
•HELLO:板卡回复 ESP32-C3-READY。这是桌面程序在众多串口之间识别该设备的方式。
•SET1:通过 SET4:: 写入一个宏并确认。
•PRINT:输出当前的四个宏。
•TEST:读取所有输入引脚并报告 BLE 连接状态。此功能在构建过程中节省了大量时间。
通过蓝牙,它宣传自己是一个名为C3 MacroPad的HID键盘,使用ESP32-BLE-Keyboard库。主机会识别为普通键盘,因此被控制的设备无需驱动程序或设置。
两者不会相互干扰,因为串行处理程序仅在有字节等待时运行,而宏只有在BLE报告连接时才会触发。
硬件
•ESP32-C3 超迷你版。小巧、便宜,带有 BLE 功能,边缘呈梯形设计,便于直接安装在电路板上。
•三个线性机械开关。
•EC11 旋转编码器,带一个按钮开关。
•电路板和导线。
以上就是全部的材料清单。没有电阻,因为每个输入都使用内部上拉电阻;也没有二极管,因为四个输入无需矩阵布线即可实现信号处理。
引脚分配
•按钮 1:GPIO 7
•按钮 2:GPIO 8
•按钮 3:GPIO 9
•编码器时钟(CLK):GPIO 5
•编码器数据(DT):GPIO 4
•编码器开关:GPIO 2
所有这些引脚均设置为 INPUT_PULLUP 模式,每个开关的另一端连接至地。按下时读取值为低电平。
电路板组装
开关不能直接按 2.54 mm 网格排列。MX 样式引脚位于网格之外,因此每个开关的引脚需要略微弯曲,使其对齐最近的孔位后再进行焊接。先焊一个开关,检查间距是否与按键一致,再决定是否全部焊接,因为一旦引脚弯曲并焊接后,间距就固定了。
接线方式:每个开关连接一条线路到对应的 GPIO 引脚,并共用一条贯穿电路板的地线。编码器需要三条这样的线路,以及其自身的地线。
将超迷你板安装在接头(headers)上,而不是直接焊接在电路板上。USB端口是配置通道,因此你希望可以轻松访问它,并且如果将来刷写无法启动的程序时,还应具备拔出板子的选项。
固件
宏存储
偏好设置会写入ESP32的NVS分区,使用名为macropad_new的命名空间,其中包含m1到m4四个键。在启动时读取这四个键的值,代码如下:
第二个参数是备用值,因此即使板子的闪存为空,也能以可用内容启动,而不是崩溃。
宏解析
解析器首先查找修饰符子串,然后将最后一个+号之后的所有内容作为键值:
修饰符通过press()函数保存,主键通过write()函数输出,releaseAll()函数负责清理。名称键如enter、space、tab和esc映射到对应的HID常量;f1至f12由KEY_F1计算得出;单个字符则直接发送;而更长的内容则逐个字符输入。
编码器尝试了最多的方案
使用经典的时钟(CLK)与数据(DT)比较来检测中断,可以得到一个位置计数器:
这种方法在干净的信号下有效,但廉价的编码器如果没有硬件去抖动,则无法产生正确的计数。接触点在保持位期间会发生弹跳,中断服务例程(ISR)会多次触发,其中一些读数会出现在 DT 比较的错误侧。计数器在单次物理点击中会向上加3、向下减1、向上加2。
计数器可以隐藏这一问题,但音量却不能:顺时针旋转会使电平在上升过程中上下跳跃。
解决方法是在动作突变时设置方向锁。暂停后第一步设定方向,之后在500毫秒内每一步都强制保持相同方向,无论计数器显示什么:
旋钮旋转是一个连续的单一方向操作,因此该锁定机制能准确匹配面板的实际使用方式。代价是,在半秒内反向操作将被忽略。软件滤波比为已焊接电路板添加电容更经济,且500毫秒的时间窗口从未造成问题。
桌面应用程序
Flo 是一个单文件的 Tkinter 应用程序,采用深色主题并带有黄色强调色,固定尺寸为960x720,确保布局无需重新布线。
板卡检测
没有找到匹配的厂商ID。该应用会遍历每个串行端口,以115200波特率打开每个端口,发送HELLO消息,并持续监听返回ESP32-C3-READY的端口:
这种方法比按VID和PID过滤更慢,但更加通用,因为它不关心板卡使用的USB串口芯片或当前操作系统。扫描过程在后台线程中运行,因此窗口不会在工作时冻结,同时提供手动选择端口的下拉菜单,以便在自动检测出错时进行人工修正。
宏构建器
为了避免用户需要记忆字符串格式,该应用提供了用于Ctrl、Alt、Shift和Win键的复选框,以及一个按键输入框和一个下拉菜单,用于选择四个插槽中的哪一个进行写入。系统会自动为您组装字符串:
如果您已经知道要输入的内容,也可以直接在任意一个输入框中输入字符串。
发送
发送功能将依次写入四个宏,每条宏之间间隔100毫秒,然后读取板卡打印的内容,使错误能够被清晰地显示,而不是静默发生:
闪存并运行
固件需要在Arduino IDE中安装ESP32板的包,将板型设置为ESP32C3开发模块,并通过Sketch中的“包含库”功能,从T-vK发布的zip文件中安装ESP32-BLE-Keyboard库。该库未包含在库管理器中。
对于桌面应用程序:
然后像其他键盘一样,在操作系统的蓝牙设置中配对C3 MacroPad。
目前仍存在以下问题:
按住按钮会重复执行宏。编码器开关能正确检测边缘并保存先前状态,但三个主按键仅检查引脚是否读取为低电平,然后等待200毫秒。按住其中一个键时,每秒会触发五次。编码器按钮已具备解决此问题的模式,但需要将其复制到另外三个按键上。
功能键检测过于敏感。任何以f开头且长度不超过三个字符的宏都会被识别为功能键,因此宏fix会被解析为功能键零,完全不发送任何数据。长度验证还应确认字符串其余部分是数字。
编码器旋转被硬编码为音量控制。四个按键可以配置,但旋钮无法配置,这是最明显的缺失功能。需要在闪存中再添加两个插槽,并在应用中增加两个字段。
没有电池,蓝牙负责数据传输,电源仍通过USB供电,因此主机设备看到的是无线键盘,而键盘本身则通过线缆连接。
本文编译自hackster.io





