作为一个已经使用了 10 年 Dvorak 布局的码农,一直缺一把趁手的原生布局键盘,目前都采用了在操作系统内进行键位映射的方案来满足我的个人使用习惯。然而市面上可供选择的原生 Dvorak 布局键盘很少,所以我目前使用的键盘,都采用了操作系统内重映射键位的方式来实现键盘布局调整后的输入能力。
随着三年疫情结束,办公室里常年用的一把 Dell 赠品键盘键帽早已打油,丝印脱落。考虑到这年头客制化键盘市场也是风声水起,只是所谓名义上的客制化,卖的无非还都是标准键,只是给了玩家们根据自己喜好选择不同的材料零件组合罢了。就好比小时候玩的四驱车,无非也都是买来的零件自己拼装,并不是真正意义上的个性化定制。
伴随制造业生产能力的进步,PCB 定制以不再是以前那种需要花点代价才能完成的事情,加上 3D 打印 / CNC 加工都不再有那种高高在上的门槛,于是我有了自己来打造一把专属键盘的想法。
布局选择
之所以我当年转向选择 Dvorak 布局作为日常使用,而不是更为常见的 QWERTY 布局,主要有以下的原因:
-
提高打字速度和效率:Dvorak 布局的设计原则是将最常用的字母放在主行中,这样手指的移动距离更短,有助于提高打字速度。
-
减少手指疲劳:由于手指需要移动的距离更短,使用 Dvorak 布局可以减少手指疲劳,特别是在长时间打字时。
-
提高打字舒适度:Dvorak 布局试图使打字更加自然和舒适,这是通过减少手指移动并优化字母组合来实现的。
-
平衡左右手使用:Dvorak 布局旨在更均衡地分配左右手的打字工作量,与 QWERTY 布局相比,能更好地利用双手。
从输入键位的热力图统计来看,Dvorak 布局的键位布置明显更加合理,核心高频使用的按键都被布置在了键盘最为方便敲击的中排位置,左手中排刚好还是五个元音字母键。虽然可能对于中文输入的场景下,Dvorak 布局的优势可能并不明显,但是作为一个需要长期输入英文内容的程序员,过去 10 年里,使用 Dvorak 布局给我带来了极为舒适的输入体验。
当然,Dvorak 布局也存在其弊端,最大的问题在于常见的软件快捷键设计,都是基于 QWERTY 布局精心设计的位置,导致 Dvorak 布局下的常用快捷键几乎没有办法直接使用。但是也有可以补偿的措施,比如利用按键映射工具,或者使用原生针对 Dvorak 设计快捷键输入的键盘。
需求梳理
在 2015 年左右的时候,我也曾经一次性入手过两把 TypeMatrix 2030,当时心动的主要原因就是他们家的设计,天生就是为 Dvorak 布局做了定制。
显而易见的优点:
-
面向 Dvorak 布局原生设计
-
提供了键位变化后,对于常用复制粘贴快捷键不易使用的补偿快捷键设计
-
退格 / 删除 / 回车 按键中置,带来的最大好处是左右手都可以很轻松按到,对程序员友好
-
支持 Dvorak 布局与 Qwerty 切换
-
体积小巧,通过紧凑的布局 + 分层的逻辑甚至提供了小键盘的能力
-
键位采用横平竖直的棋盘格排列,视觉效果舒适,打字机键盘的错位设计,当初本身其实是为了控制输入速度而产生的
实际使用下来感受的不足:
-
做工简陋,只是不同的薄膜键盘,船壳形式的简易外壳
-
右侧提供的多媒体功能键有些多余
-
完全没有考虑防水设计
-
价格偏高,一把键盘需要 110 美刀,却只能得到这样的产品,着实性价比偏低
当年入手的两把 TypeMatrix 2030 最终都没有逃过进水后报废的宿命,主要问题都出现在薄膜导电材料遇水,尤其是热水之后,溶解就无法导电了,个别按键直接失效,键盘也就没用了。而且塑料薄膜上走细线的方式,没有手工完美修复的可能性。
TypeMatrix 2030 在键盘布局方面,其实我的使用感受是相当满意,如果当初不是因为进水报废,我很想长期使用下去。所以,在自己设计键盘时,也是优先考虑参考他家成熟的功能设计,再对应做一定的调整。
在轴体选择方面,早年我也使用过标准高度的机械键盘,我个人不是很喜欢过长的按键行程,作为一个工作涉及长期打字输入的人,过长的键程某种程度上会影响输入效率。第二点问题是,我也不喜欢可以制造按键声音的轴体,希望安静的环境内工作,也不在乎是否有按键的段落感,反而觉得线性轴,输入起来对手指的长期发力更友好。综合考虑下来,并实际对比尝试了几种轴体,决定考虑使用矮轴线性轴的方案。
基本目标:
-
沿用 TypeMatrix 2030 的键位布置思路
-
满足 Dvorak 布局的使用需要
-
保留回车等按键的中置设计
-
-
适当减少不必要的多媒体功能键
-
提供不同键盘布局的分层切换能力
-
使用矮轴线性轴体方案实现
-
不需要无线传输功能
先尝试设计了第一版,与原版设计一样,使用了 0.75U 高度的 F 功能键,以及大量不常见的 2U 键位,另外还有一个市面上根本不可能找到相同尺寸的 5 x 1.25U 空格键。加上又是矮轴,所以能选择成品键帽的可能性变得更小了,不考虑量产的情况下,PBT 开模具有些过于得不偿失。最终在完成第一版方案的电路以及固件验证后,决定对布局做出适当的调整,以兼容市面上现成键帽尺寸的方案来调整按键布局与尺寸。
键盘的基础键位设计,可以使用 Keyboard Layout Editor 在线完成
找不到 0.75U 高度的功能键,就直接调整为 1U 设计,常见 2U Backspace 与 2.5U Enter 键,就适当在功能键与主输入键区中间插入一条 0.25 高度的空隙,正好满足中置 Backspace 与 Enter 后的高度需要。空格键调整最常见的 6.25U 设计,并适当减少不常用的功能按键,比如右侧 Alt/Ctrl。最终设计出一版可以完美兼容成品键帽的布局。
电路实现
布局设计确定之后,下来的环节就是设计电路。考虑到键盘并不需要特别花里胡哨的功能,甚至 PBT 键帽也不需要背光,所以我选择了最为常见的 Atmega32U4 核心 MCU。其实也可以考虑用 STM32 方案,但会相应增加不必要的复杂度与成本,从扩展引脚的角度考虑,Atmega32U4 提供的管脚数量已经足够满足需要。
按键阵列
作为一个键盘,其核心的人机交互部分有简单的开关阵列组成,通过 MCU 的不同 GPIO 管脚发出时序扫描信号,可以判断出阵列中某一时刻哪些位置上的开关按键被导通。我采用了「列 → 行」的扫描方式,在每一个开关后面,需要串联一个二极管,保证扫描信号的单向导通,不会因为同时按下多个按键后,出现串信号导致判断错乱的问题。
由于前面已经完成了整体键位布局的设计,原理图设计时,只需要讲按键对应的开关以及二极管,放到预期的行列位置上,就完成了这部分的基本布局。
USB 接口
为了使用方便,USB 供电以及信号数据的传输,使用一个标准的 Type-C 接口来实现键盘与操作设备的连接。键盘在工作时也不需要使用到高速信号,电路设计相对也不复杂,主要考虑静电防护、接口屏蔽层接地、滤波等安全设计。
-
ESD 静电防护,我直接使用了一个 USBLC6-2SC6 二极管阵列来解决,如果要追求成本更低,也可以自己放几个二极管来达到相同效果,只是相对会占用更多的 PCB 面积。
-
供电滤波电路部分,使用一个小磁珠配合电容组合来实现,并配合一个自恢复保险丝,保证供电部分的电路安全。
-
接口的屏蔽外壳,通过一个 1MΩ 电阻和电容组合后接地。当然,作为最终终端设备,完全可以依赖主机 USB 接口的接地能力实现信号屏蔽接地。
实际情况下,即使不做这些安全措施,也并不会影响键盘本身的正常工作。但增加这部分设计,可以避免在电路异常情况,或者存在意外静电放电的情况时,导致意外烧毁 MCU,可以让键盘长期稳定的工作下去。反正时给自己定制的键盘,也不在乎这么点成本,所以该有的防护都可以设计上。
另外,值得一提的是,Type-C 接口的 A5/B5 用于协议检测,对于键盘,只需要通过下拉电阻接地即可。但是这里需要注意,规范的设计需要使用两个独立的下拉电阻,而不能共用一个,否则会遇到当年树莓派的问题,在使用一些带有芯片的缆线时,会导致 A5/B5 未经过下拉电阻,出现短接的情况,导致损坏。
MCU 接入
微控制器的电路设计,也比较简单,核心工作是正确的接入供电/地线/信号,通过一个晶振来提供时序信号,剩余大部分 GPIO 接口主要留给开关阵列部分。开关阵列行列与 MCU 管脚位置的对接,建议按照实际 PCB 线路布置初步完成后,抽出来的物理引线位置就近连接,也可以减少不必要的走线交叉,减少过孔布置。
RESET 引脚部分,按照标准设计,预留一个小开关即可,用于控制向 MCU 内烧写程序。实际只需要在 PCB 上留出两个不是特别明显的小贴片焊盘,在需要使用的时候,使用金属物体简单短接下,也可以达到同样的效果,并不需要真正安装一个几乎用不到的开关。
LED 指示灯
考虑到 MCU 还有剩余的管脚可以使用,索性就再提供几个简单的 LED 指示灯,用于显示锁定状态,键盘布局切换状态来使用。注意发光二极管需要配合限流电阻使用,如果直接将 LED 接通正负极,可能会电流过大、异常发热、光照过量等问题。具体电阻阻值的多少,需要根据实际 LED 的规格来实验确定,作为指示灯,建议使用低照度的 LED,避免指示灯亮度过于刺眼。
PCB 布局
由于已经有了使用 keyboard layout editor 生成的键盘布局,可以将对应的配置申明属性放到能对应生成键盘定位板布局的在线工具中,生成定位板 CAD 文件,获得相对精确的键盘实际布局位置。随后就可以按照对应网格位置,放置机械按键轴体的元件封装。
考虑元件的安装布置,PCB 正面需要安装机械按键轴体,以及直插式 LED 指示灯,其他贴片元件如果还要安装在相同的 PCB 正面,会有比较大的安装干扰问题。同时,还需要考虑到,实际制造过程,如果需要两面贴片安装,成本会显著高于单面贴片,所以最终的设计思路就是将所有的贴片元件安装到 PCB 的反面。
轴体选择上,在矮轴领域,国产轴相比于 Cherry 并没有显著的区别,甚至国产设计在键程、发声共鸣空腔设计上,有自己的独到想法和优势。轴体的布置上,考虑同时兼容凯华(Kailh) Choco v1/v2 系列的矮轴,以及 Cherry 的矮轴系列,给最终的 PCB 带来更为灵活的按键选择。简单参考 Github 其他项目的实现,组合焊盘和开孔位置,就可以实现自己想要的这种兼容性元件封装。选择了兼容性方案以后,也会带来一个问题是这样的设计就不具备考虑使用热插拔底座的可能性。不过我本人特别不喜欢热插拔那种不稳定连接的设计,总觉得轴体一定要焊接才舒服,所以这也不是什么大问题。
标准的机械键盘 1U 尺寸被规定在 0.75in (19.05mm),为了方便 PCB 元件放置,可以使用 0.79375mm(19.05mm/24) 的网格尺寸来方便布置。线宽部分,基础的信号线部分使用接近 10mil 的公制尺寸定在 0.25mm,而供电部分考虑到 USB 可能达到的电流大小,使用了 0.40mm 的线宽保证安全余量。考虑到这次键盘设计并不需要背光布置,实际工作电流远低于 USB 的电流上限,使用相同的线宽实际问题也不大。
其他布线过程还需要的注意事项还包括:
-
USB 信号线的走线需要平行等长布置,并且需要避免跨越不同敷铜平面。
-
USB 接口,MCU 下方,以及晶振的位置可以做地层敷铜,提高抗干扰能力。
-
晶振布置的位置尽可能靠近 MCU 本体。
剩下的工作就是参照原理图中的元件,将所有的元件对应的封装,放置到 PCB 上合适的位置,并完成最终的连线。为了方便走线,我选择了将大都数按键封装旋转 90° 放置,纵向走线尽量放置在 PCB 上层,横向走线放置在下层,减少过孔数量。并且所有元件的封装,也尽量都放置在网格点上,以保证最终布线的整齐美观。MCU 为了方便引脚连接,采用旋转 45° 的布置方式。
按照键盘的使用习惯,我把 USB 接口放置在了 PCB 中间上方的位置,保证在不同环境下键盘外部连线的便捷。USB 接口部分由于几乎是满配了安全设计,相对元器件密度比较高,被迫只能将两边对应的按键封装,转向不同的朝向,做对称布置。不过这样最终的效果,感觉看着还算比较舒适。
因为键盘按键参照了 TypeMatrix 横平竖直的网格布局,整体走向很规整,元件布置也相对简单舒适。不过还需要考虑一个问题,由于我计划做一个矮轴键盘,而通常键盘上达到 2U 大小的大键通常都会配合平衡感 + 卫星轴的方式,来实现按键的整体平衡。传统常规高度的机械键盘,通常会将卫星轴安装在定位板上,但是矮轴键盘如果这样设计,势必会到导致整体键盘厚度变厚。于是,我选择参考了市面上其他几款商业售卖的矮轴键盘设计,看到了将矮轴专用的卫星轴,直接安装在 PCB 板上的做法,以满足整体高度的需要。另外还有一个备选方案是,使用某些键盘上能看到的龙船卫星轴。为了验证不同的安装方案,直接做了一张白嫖的 PCB 小板用来验证几种机械安装结构。
最终体验下来,直接将 MX 卫星轴的矮轴特制版本,安装在 PCB 上的手感体验,以及可操作性,都是两个方案里最为舒适的,并且高度也可以完美贴合矮轴的轴体高度。所以最后剩下的就是在 PCB 的大键布置上,放置合适的卫星轴安装位置开孔。
最后,进一步控制 PCB 面积,优化成本以及最终键盘的重量,直插式 LED 指示灯的空间也尽可能压缩。在最终放置几个可能可以用的上,但实际上不需要使用的螺丝安装孔以后,打上标记丝印,最终的 PCB 设计就完成了。
外壳设计
在完成了前面核心的电路以及 PCB 设计之后,要将键盘最终打造成一个可用的工业产品,外壳设计也是必不可少的部分。开始正式设计外壳之前,需要选择确定键盘的安装结构。
安装结构选择
经过多年的发展,各厂商爱好者,已经尝试总结了各种机械键盘结构设计的类别,以及相应的特点,供键盘玩家们参考选择。
-
船壳结构 (Tray Mount) - 在低成本键盘中很常见的设计,直接将键盘 PCB 安装在一体成型的外壳上,由底壳安装孔实现支撑。优点是结构简单,零件数量少,组装制造成本可以非常低。但是这种结构的问题在于由于支撑点的布置问题,不同位置按键手感会存在差异性。
-
外壳安装 (Case Mount) - 一般分为 Top Mount 和 Bottom Mount 两种方式,区别在于一种将定位板固定在顶盖,而另一种则将定位板固定在底壳上。这两种安装方式,核心设计都在于由定位板来分散按键敲击以及整体接口支撑的各种受力,可以得到比较平衡一致的手感与使用体验。键盘敲击手感的体验,完全取决于定位板材质的选择。另外,由于 PCB 本身不受力,所以理论上不容易因为长期使用而出现可能的 PCB 变形,导致键盘出现故障。
-
三明治结构 (Sandwich Mount) - Case Mount 的变种形式,直接将定位板放大后,压在上盖和底壳之间,简化安装。但是对于各个零件的加工尺寸一致性较高,并且由于上下死死压住,整体手感相对偏硬。
-
无钢结构 (Plateless Mount) - 最为原始的形式,去掉了定位板,直接由 PCB 来作为结构支撑的主体。一般可以用类似船壳或者 Top Mount 的方式来安装。由于缺少额外的定位板,受限于 PCB 本身材质,敲击支撑会偏软,并且 PCB 相对更容易因收到机械冲击而被损坏。
-
嵌入式 (Integrated Plate) - 顶盖和定位板一体设计,相当于三明治结构的简化版本,减少了零件数量,手感也比较类似。同样偏硬,且由于一体化的设计,容易导致更明显的按键噪音放大效果。
-
垫片结构 (Gasket Mount) - 目前有些高端机械键盘喜欢使用的设计结构,在三明治结构基础上做了进一步改进,上下层之间加入了额外的缓冲材料充当垫片层,解决三明治结构手感偏硬的问题。缺点在于缓冲材料及安装结构的引入,导致成本一般相对偏高。
我个人喜欢相对偏硬,但是整体反馈一致的键盘敲击手感,在这些经典的结构设计里,Top Mount 的形式最符合我自己的个人偏好。虽然 Top Mount 零件设计相对复杂,但毕竟是自己想要的设计结构,所以还是要来折腾下。
机械结构设计
既然选择了矮轴的方案,在整体键盘厚度上,自然是能省一点高度,就省出一点来的逻辑,以保证最终成品的尽可能简洁与轻量化。无论上盖还是底壳,核心的设计思路都是只要能实现键盘主体的定位和安装,以及高度空间上不存在互相干扰,尽可能压低高度空间。把最简单的设计当作最美观的设计来看待。本着这一理念,还带来了两个好处,一是整体材料的节省带来的轻量化,二是由于空腔体积的压缩,按键空腔噪音可以被控制在比较低的水平上。
整体的设计过程,我还是选择了自己相对熟悉的方式。首先再 CAD 中依靠自己的空间想象,分层设计好精确的基础框架轮廓,然后用 SolidWorks 在基础线框的基础上来完成三维实体模型设计。虽然实际用三维工具本身也能够完成最终的效果,但我还是喜欢 CAD 工具命令式操作的准确与高效。难得来画几张设计图,让我回想起十多年前在大学里上机械制图课,还搞过手工绘图的美好回忆。
通过将 PCB 设计软件中生成的模型导出,可以在零件组合体中进行安装仿真,排查各个组件之间安装,可能出现的碰撞问题。通过模拟碰撞检查,在做底壳加强筋位置设计的时候,对于需要压缩厚度的优化,还是相当有用的。另外由于 USB Type-C 接口设计的位置,同时需要在顶盖和底壳上进行组合处理,也是实际后期模型检查的一项重点。
外壳设计主体分成了顶盖、定位板、底壳三个部分,按照 Top Mount 结构思路,设计不同组件之间的安装固定结构。起初还考虑要不要选择找淘宝店专门定制定位板的店家来做定位板,不过定位板材质上最终评估了软硬程度以后,我还是选择了和顶盖相同的铝合金材质,并且希望做相同工艺的阳极氧化,索性就一起考虑直接用 CNC 的方式来做了。内侧不必要的位置,适当开孔或者开槽打薄,实现减重效果。顶盖左侧边框适当略微加宽,并留出三个圆孔用于直接透出直插式 LED 指示灯,这样设计也省去了额外的导光塑料。
金属件在设计时,需要考虑组合安装时的公差,按照国标加工工艺,一般建议留出 0.1mm ~ 0.2mm 的加工误差余量。底壳我准备采用普通的 ABS 工程塑料 3D 打印,虽然可能打印的公差相对会偏大,不过由于塑料本身属于偏软质的材料,实际操作下来,加工精度带来的误差,对安装的影响并不大。所有组件之间,使用两种不同长度的 m2 平头螺丝进行固定,可以直接在铝合金顶盖上,做具体的螺纹攻丝设计。
固件编写
要使键盘能够正确按照设计预期实现基本输入功能,光完成硬件设计部分显然是不够的,还需要自己来实现固件逻辑的软件部分。作为一个采用有线方式连接,并且使用 Atmega32 方案作为键盘 MCU 的方案,可以直接选择社区中最为成熟的键盘固件框架 QMK 来完成键盘的固件逻辑部分。采用现成框架,就可以直接避免自己从头来造轮子。
毕竟平时本职工作常年跟写代码打交道,直接按照文档说明开个 qmk 工程并不麻烦。本身非标布局,打一开始就不想着能用图形化配置工具搞定固件实现了。而且我可能在某种程度上,对代码有种莫名的洁癖,不喜欢机器生成的某些不符合人类习惯的行为,总喜欢调成自己看的顺眼的形式,所以还是自己动手来写下固件逻辑。
QMK 框架本身已经实现了大部分的基础功能,比如按键指令的定义,不同布局分层的切换/组合,快捷键行为的实现,开关阵列的时序扫描等等一系列开发一个键盘会使用到的特性。自己要做的核心逻辑,一方面是对于不同分层布局的按键定义,另一方面是键盘布局的切换控制逻辑。MCU 的管脚定义,直接在 info.json
配置文件中声明即可。
键盘布局部分,使用了四个分层,分别实现默认的 Dvorak 布局,候选的 QWERTY 布局,功能组合按键,以小键盘数字区按键的输入能力。
enum mx_layers {
_DVORAK = 0,
_QWERTY,
_FN,
_NUMPAD
};
enum mx_keycodes {
TG_DV = SAFE_RANGE,
NUM_00
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Dvorak Layout (Default)
[_DVORAK] = LAYOUT_dvorak_matrix(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_DEL, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_BSPC,KC_6, KC_7, KC_8, KC_9, KC_0, KC_LBRC,KC_RBRC,
KC_TAB, KC_QUOT,KC_COMM,KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH,KC_EQL,
KC_A, KC_O, KC_E, KC_U, KC_I, KC_ENT, KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS,
KC_LSFT,KC_SCLN,KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_BSLS,KC_RSFT,
KC_LCTL,KC_LGUI, KC_LALT, KC_SPC, KC_HOME,KC_UP, KC_END, KC_PGUP,
MO(_FN), KC_LEFT,KC_DOWN,KC_RGHT,KC_PGDN
),
// Qwerty Layout
[_QWERTY] = LAYOUT_dvorak_matrix(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_DEL, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_BSPC,KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,KC_EQL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,KC_RBRC,
KC_A, KC_S, KC_D, KC_F, KC_G, KC_ENT, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,
KC_LSFT,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_BSLS,KC_RSFT,
KC_LCTL,KC_LGUI, KC_LALT, KC_SPC, KC_HOME,KC_UP, KC_END, KC_PGUP,
MO(_FN), KC_LEFT,KC_DOWN,KC_RGHT,KC_PGDN
),
// Functions
[_FN] = LAYOUT_dvorak_matrix(
_______,TG_DV, _______,_______,_______,_______,KC_INS, _______,_______,_______,_______,KC_PSCR,_______,TG(_NUMPAD),
_______,_______,_______,_______,_______,_______,KC_VOLU,_______,_______,_______,_______,_______,_______,_______,
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,KC_PSLS,KC_PAST,KC_PMNS,
_______,_______,_______,_______,_______,KC_VOLD,_______,_______,_______,KC_P7, KC_P8, KC_P9,
KC_CAPS,_______,_______,_______,_______,_______, _______,_______,_______,KC_P4, KC_P5, KC_P6, KC_PPLS,
_______,C(KC_INS), S(KC_INS), KC_MUTE, KC_P1, KC_P2, KC_P3, KC_PENT,
_______, KC_P0, NUM_00, KC_PDOT,KC_PENT
),
// Number Pad
[_NUMPAD] = LAYOUT_dvorak_matrix(
_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,
_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,KC_PSLS,KC_PAST,KC_PMNS,
_______,_______,_______,_______,_______,_______,_______,_______,_______,KC_P7, KC_P8, KC_P9,
_______,_______,_______,_______,_______,_______, _______,_______,_______,KC_P4, KC_P5, KC_P6, KC_PPLS,
_______,_______, _______, _______, KC_P1, KC_P2, KC_P3, KC_PENT,
_______, KC_P0, NUM_00, KC_PDOT,KC_PENT
),
};
自定义按键行为方面,重点关注了 Dvorak/QWERTY 键盘布局切换行为的控制,以及 TypeMatrix 上赋予多出的小键盘按键输入类似某些计算器上连续 "00" 的效果。同时,参照 TypeMatrix 设计,通过 Fn 和左侧按键组合,实现了对应的复制/粘贴快捷键功能,解决键盘布局影响常用快捷键带来的效率问题。
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Debug Output
#ifdef CONSOLE_ENABLE
uprintf("KL: kc: 0x%04X, col: %2u, row: %2u, pressed: %u, time: %5u, int: %u, count: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed, record->event.time, record->tap.interrupted, record->tap.count);
#endif
switch (keycode) {
case TG_DV:
// Toggle Dvorak Layer
if (record->event.pressed) {
if (IS_LAYER_ON_STATE(default_layer_state, _QWERTY)) {
default_layer_set(1 << _DVORAK);
set_single_persistent_default_layer(_DVORAK);
} else {
default_layer_set(1 << _QWERTY);
set_single_persistent_default_layer(_QWERTY);
}
}
return false;
case NUM_00:
// Double Zero
if (record->event.pressed) {
SEND_STRING("00");
}
return false;
default:
return true;
}
}
固件代码逻辑编写完成后,使用 qmk 编译出二进制文件,随后可以使用 qmk toolbox 配合 PCB 上的 RESET 短接控制,将其烧写到 MCU 的存储器中。
制造与组装
硬件部分的打样生产,就交给嘉立创来完成了。PCB 打样毕竟嘉立创老本行,SMT 贴片也相当好用,直接商城下单后,用到的所有贴片元器件都可以顺带贴好。流程也比较简单,不过由于我的电路设计使用的开源的 KiCAD,需要导入到立创 EDA 后,关联下加工物料,简单检查后,上传 PCB 图纸与贴片加工信息。下单确认时,重点关注下 MCU,晶振,集成电路元件,二极管的引脚位置,这部分的元器件只能说实现了自动定位,但是引脚的位置和极性,还需要确认一遍来保证,以确保最终的电路安装正确。
外壳部分,顶盖和定位板,也使用嘉立创三维猴的 CNC 加工服务,选择 6061 铝合金材质,并且额外做了深空灰阳极氧化表面处理。底壳部分也一起用三维猴的 ABS 3D 打印来完成。需要注意的是,由于有螺纹攻丝的工艺要求,按照加工建议还是单独输出二维图纸进行加工工艺的标注说明,这部分工作用 SolidWorks 完成还是比较顺畅的。
如果选择更软的 5 系列铝合金材质,也可以考虑不做攻丝加工,而直接打一个 1.8mm 的螺丝开孔,通过螺丝安装自己实现攻丝效果,成本也更低。
加工订单下单之后,就是几天的等待时间,PCB 订单处理相对较快,毕竟嘉立创老本行,3D 打印和 CNC 可能是因为我下单时候是国庆期间,因为放假因素,有订单积压的情况,稍微多等了几天。不过也差不多一周时间就完成了,效率还算能接受。
完成后的 CNC 成品顶盖和定位板,到手就可以轻松组合在一起,定位相当精准,基本严丝合缝。将轴体安装到定位板上的过程,也有种类似组装乐高积木的快感,轴体卡到定位板上,发出的“咔嗒”声极为舒适。
所有的准备工作到位后,接下来要做的就是将轴体先通过定位板固定好位置,焊接到 PCB 上,再对应安装好所有的卫星轴和平衡杆。最终键帽与轴体的选择上,考虑到更好的键帽适配性,凯华 1350 的猪鼻子设计其实并不适合旋转 90° 安装的布置方式,能选择的键帽也相对偏少,考虑到传统十字轴心的安装兼容性,相对静音的效果,最终我还是选择了 Cherry 的矮轴来作为键盘的按键轴体。
键帽选择方面,由于是 Dvorak 布局这样的异形键位布置,成品键帽只能选择类似 DSA 高度的所谓平胸键帽,即每行具有一致性设计的键帽形式。考虑到本身阳极氧化铝合金的顶盖颜色,整体的美观协调,最终我选了 NuPhy Air 96 的这套键帽来组成本次键盘设计最后的按键部分。PBT 材质可以提供相当舒适的长期输入体验,也不用担心键帽打油。
最终组装完成的效果,深空灰的铝合金材质,配上主体灰色风格的按键键帽,看起来还挺漂亮的。
后记
键盘的设计完成后,我打算自己实际使用一段时间,看看还有哪些想要迭代改进的地方,如果还有下次,可以尝试改进设计。目前觉得 Fn 快捷键组合的按键距离还是放的有点保守,不像是传统键盘使用的感觉,稍微有点别扭。我也很想找一个合适的编码器,来实现旋钮功能,不过要找一个能适应矮轴高度,且没有定位点限制的顺滑编码器,似乎并没有想象的那么容易。
本次自己动手设计键盘的经历,让我体验到了何同学/稚晖君们这些科技 Up 主们设计创造的快乐。以前凑来没有这样体验过从零开始全链路参与,设计并最终完成一个电子产品的制造的过程,两周左右的闲暇时间把全流程走完,还蛮有成就感的。这种体验就像 19 世纪凡尔纳科幻小说里强大的工程师那样,通过自己的智慧和双手,以工程化的方式化解一个又一个问题。
另外,不得不感叹生活在一个生产力强大(过剩)国家的美好,限制创意发挥的问题不再是缺少低成本生产制造出来的能力,瓶颈只在于缺少天马行空的想法上。如果将来有一天,可以实现集成电路的定制化加工,估计还能激发出进一步的设计创新。
参考资料
最后修改于 2023-12-12