黑科技:程序员如何打造属于自己的分体键盘

前言

作为一名程序员,键盘在手,天下我有啊,不整个高大上的键盘怎么提升B 格。之前一直想买个机械键盘,听说机械键盘敲代码时格外舒爽,实在是提升效率与 B 格的神器。

普通机械键盘

使用普通的键盘打字打久了手腕很容易感觉疲劳,因为敲键盘时手腕总是弯着的。于是乎就想买一个符合人体工程学的分体式机械键盘。

结果找了半天都没有比较中意的,找到几个人体工程学键盘,都是薄膜的,而且价格高得离谱,不就多个人体工程学光环嘛。。。身为程序员中的屌丝,岂能被金钱这种东西折腰呢?

带 “人体工程学光环” 键盘

为了不要这么纠结,就自己 DIY 一个咯,正好有台 3D 打印机(又一个装 B 神器,你值得拥有,O(∩_∩)O哈哈~),全部外壳自己打印,控制板用 Arduino Leonardo,原生支持键盘鼠标驱动,轴体考虑到成本,先买了 80 颗国产黑轴做实验,键帽也简单打印一下,说干就干.

准备

  • 工具
    • 3D打印机(打印外壳)
    • 电烙铁
    • 热熔胶(固定按键用)
    • 万用表
  • 硬件
    • Arduino Leonardo板(驱动板)
    • 黑轴轴体
    • 二极管+电阻+杜邦线+万能板
    • 小螺丝(外壳装配)
  • 软件
    • SolidWorks(3D建模,设计外壳,可用任何3D建模软件代替哦)
    • Arduino IDE 写Arduino键盘驱动(写键盘驱动程序)

是时候上点图了。。。

自己组装的三角洲式3D打印机

淘宝买的工具

步骤

先设计键位排布,使用 SolidWorks (任何3D建模软件都ok的,只是我比较熟系SolidWorks哦)画出简单的按键布局,先从左手开始,先完整的搞定左手能使用了,再做右手。设计好布局后制作支撑轴体的面板,然后设计电路,用飞线焊接,写代码测试按键是否都正常。电路正常后设计整个外壳,然后整体组装。这就完工啦

键位设计 右手之所以外形扭曲,是因为3D打印机打印面积有限

电路设计 由于 Arduino 板 io 口有限,必须使用矩阵扫描来实现按键。扫描方式就是:定义 n 个 io 口为扫描口,m 个接收口,组成一个 n*m 的矩阵。扫描口默认全部都是低电压,然后依次将每个扫描口单独置为高电压(即扫描动作),当这个高电压的扫描口上连接的某个按键有按下时,对应的接收口电压就也是高电压,这时就可以定位到是哪个按钮按下了,矩阵如图所示:

Arduino有 6 个模拟口,14 个数字口。我要做的键盘不超过 80 个键,所以使用8 个数字口进行脉冲扫描,6 个模拟口加 4 个数字口用来接收脉冲来定位按键,这样就实现了 8*10 的矩阵,支持 80 个键。还有 2 个数字键是空闲的,可以用于特殊按键定制。

按键冲突处理 如果按上图简单实现会存在冲突问题,当接收口上有多个按键被按下时,会存在回路,高电压的扫描口和低电压的扫描口发生短路,就不知道是哪个按键被按下了。一般键盘都是 5 键左右不冲突,也就是这个键盘有 5 个接收口,只要保证在同一个接收口上的按键不会同时按下就不会有冲突。

使用矩阵扫描方式就会有按键冲突问题,我使用二极管来处理冲突,保证不会出现回路问题,如图(R 是扫描口,C 是接收口):

电压动荡处理 二极管解决了冲突问题,但是不能解决电压动荡,电压不稳定有两方面,第一就是当扫描口高电压变为低电压时,接收口电压不会立即变成低电压,所以在接收口都需要加一个下拉电阻,让电压立马降下来。第二就是按键按下时接触片碰撞时导致的电压不稳,这个最好是通过加电容(和按键并联)去过滤波动电压,买元件时忘了买电容了,这里就简单粗暴了

最终电路设计

外壳设计(第一期简单点,不把电路板放到外壳内)

左手

右手

侧面

键帽设计

程序设计

#include "Keyboard.h"
#include "HID.h"

#define scanPin_len 8
int scanPin[] = {4,5,6,7,0,1,2,3}; // 扫描pin,(默认低电平,逐个输出高电平)
int scanPos = 0; // 当前扫描位

#define btnPinA_len 6
#define btnPinD_len 4
int btnPinA[] = {5,4,3,2,1,0}; // 按钮pin,模拟端口
int btnPinD[] = {8,9,10,11}; // 按钮pin,数字端口

#define btn_len 10
byte btn[scanPin_len][btn_len]; // 按钮状态
byte btnTmp[btn_len]; // 临时按钮状态

#define KEY_FN KEY_RIGHT_SHIFT // FN键
// 8*10的按键映射矩阵
uint8_t keyMap[scanPin_len][btn_len] = 
{
{'y','n','7','8',KEY_F6,'h','m','u','j',' '},
{'o','.','0','9',KEY_F7,'l',',','i','k',KEY_FN},
{'p','/','-',KEY_LEFT_ARROW,KEY_F8,';',KEY_UP_ARROW,'[','\'',KEY_DOWN_ARROW},
{KEY_F10,KEY_DELETE,'=',KEY_BACKSPACE,KEY_F9,KEY_F11,KEY_RETURN,']','\\',KEY_RIGHT_ARROW},
{KEY_ESC,KEY_LEFT_GUI,'`',KEY_LEFT_CTRL,KEY_TAB,'a','q','z',KEY_CAPS_LOCK,KEY_LEFT_SHIFT},
{KEY_F1,KEY_LEFT_ALT,'1',KEY_F2,'2','s','w','x','d','c'},
{KEY_F3,' ','4',KEY_F4,'3','e','r','b','f','v'},
{KEY_F5,'6','5',0,0,0,'t','g',0,0}
}; 

void setup() {
  Keyboard.begin();
  Keyboard.releaseAll();  

// 初始化扫描pin
  for(int i=0; i<scanPin_len; i++) {
    pinMode(scanPin[i], OUTPUT);
  }  

// 初始化按钮pin
  for(int i=0; i<btnPinD_len; i++) {
    pinMode(btnPinD[i], INPUT);
  }  

// 初始化按钮状态
  for(int i=0; i<scanPin_len; i++) {    for(int j=0; j<btn_len; j++) {
      btn[i][j] = 0;
    }
  } 

 for(int j=0; j<btn_len; j++) {
    btnTmp[j] = 0;
  }
}
 
 void loop() {  
 // 轮询设置scanPin
  for(int i=0; i<scanPin_len; i++) {    if(i == scanPos) {
      digitalWrite(scanPin[i], HIGH);
    } else {
      digitalWrite(scanPin[i], LOW);
    }
  }

  delay(5);  
 
 // 读取按键信息
  readBtn(); 
 
  // 处理状态有改变的btn
  for(int i=0; i<btn_len; i++) {
      if(btn[scanPos][i] != btnTmp[i]) {
      btn[scanPos][i] = btnTmp[i];
      
      if(btnTmp[i] == 1) {
        Keyboard.press(keyMap[scanPos][i]);
      } else {
        Keyboard.release(keyMap[scanPos][i]);
      }
    }
  }
 scanPos = (scanPos + 1) % scanPin_len; // 下一个
}
      
void readBtn() {
  // 先读模拟口,再读数字口
  // 5 -> 0
  int index = 0;  for(int i = 0; i < btnPinA_len; i ++) {
      int val = analogRead(btnPinA[i]);
      if(val > 600) {
        btnTmp[index] = 1;
    } else {
      btnTmp[index] = 0;
    }
    index ++;
  } 
           
   for(int i = 0; i < btnPinD_len; i ++) {
    btnTmp[index] = digitalRead(btnPinD[i]);
    index ++;
  }
}

制作图集

第一版键帽(3D 打印机精度还是有点欠缺,特别是处理弧线):

打印机底板想换成玻璃的,结果新买的毛玻璃打印时受热不均,碎了。。。还是乖乖用回美纹纸吧

在打印中,加热头松动掉落,还好机器有自动保护,没有造成火灾。幸亏代码不是我写的,要不然肯定会火灾的,^_^

打印过程中底座脱落,都打成鸟窝了。。。一路坎坷啊

轴体安装,再次简单粗暴的没有使用卫星轴

飞线,这是第一版没加二极管的连线,没有做 pcb,直接飞线连,简单高效,适合屌丝程序员,O(∩_∩)O哈哈~

ArduinoLeonardo 还没到货,拿 uno 测试按键

外壳组装效果

第一版键帽(字母是用美纹纸贴上去的,就是这么简单粗暴)

Leonardo 到货,测试驱动

右手组装成功(黑色更有感觉啊)

新版键帽(白色),美纹纸弱爆了,必须整高端点,然后发现白色材料打印效果很赞,光滑度也高了不少,打印材料还是相当重要的

电路板,裸露在键盘外还是挺有极客范的哦

最后效果,符合人体工程学的分体式设计,全键无冲,可任意自定义快捷键,甚至可任性滴修改键位布局哦(重新设计外壳即可)

总结

做完整个键盘感觉非常有成就感,也非常实用,截止目前已经用了快半年时间了,已经非常习惯机械键盘的按键反馈,也非常习惯分体键盘的布局,手腕也不再弯着,没有酸过了,简直好用到没朋友。最后来大致汇总下花费吧(拥有一款自己专属的机械键盘真的不是什么难事)

  • 80颗国产黑轴 104元
  • 元器件 24元(邮费贵,还有很多二极管和万能板没用到)
  • Leonardo 30元
  • 大概材料花费在160元左右,比普通的机械键盘便宜多了,而且还是分体的,所有按键可随意自定义(驱动程序都自己写的,还有啥不能改的,O(∩_∩)O哈哈~)

最后晒一下我在小黑屋的办公桌(这键盘是不是B格最高的? O(∩_∩)O~~)


本文系腾讯Bugly独家内容,转载请在文章开头显眼处注明作者和出处“腾讯Bugly(http://bugly.qq.com)”

原文发布于微信公众号 - 腾讯Bugly(weixinBugly)

原文发表时间:2016-04-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

极客DIY:手机文件直传U盘,三步教你做一根OTG传输线

FreeBuf科普 OTG,即On-The-Go,该技术就是实现在没有电脑的情况下,实现从设备间的数据传送。例如数码相机直接连接到打印机上,通过OTG技术,连接...

21350
来自专栏施炯的IoT开发专栏

PhoneFinder--寻找丢失的手机

    手机丢了怎么办?那就打电话给手机,如果运气好的话,捡到的好心人能够把手机还给你。如果手机是被偷的,那就没有办法了,即使手机开着,估计小偷也不会接电话。当...

29240
来自专栏极客慕白的成长之路

CTF线下防御战 — 让你的靶机变成“铜墙铁壁”

随着CTF的普及,比赛的形式也有了越来越多的花样,对于线下赛来说,开始出现了安全加固或者防御战之类的环节,亦或者因为拿下靶机后不希望其他攻击者进入而进行“争夺”...

37640
来自专栏小文博客

良心压缩软件Bandizip——无广告超精简

Bandizip 是一款来自韩国的开发商 Bandisoft 开发的 Windows 平台压缩软件,是一款完全免费的压缩软件。

880100
来自专栏FreeBuf

新年伊始,Java惊爆首个0day

日前,Java又爆了一个新的0day,可能让攻击者获取计算机管理权限,Java 7 Update 10或更早的版本中存在该漏洞,该漏洞可以允许未经身份验证的远程...

21160
来自专栏木宛城主

SharePoint 2013 Designer工作流——Parallel Block的应用

参考目录 安装和配置SharePoint 2013 Workflow SharePoint 2013 实现多级审批工作流 在自定义Workflow...

284100
来自专栏张善友的专栏

Entity Framework Code First 支持存储过程

存储过程(Stored Procedure)不仅仅是将多得简直荒唐的业务逻辑塞入数据库的一种方式;它还是避免将多得简直荒唐的存储逻辑塞入应用程序层(applic...

21380
来自专栏MixLab科技+设计实验室

设计师编程指南之Sketch插件开发 4

为什么写这个系列的文章,一是因为网上相关的 sketch 插件开发教程太少,官方的文档写得不算太清楚,二是因为本公众号长期在研究智能设计相关的内容,基于 ske...

38080
来自专栏小文博客

良心压缩软件Bandizip——无广告超精简

10.4K50
来自专栏Python中文社区

怎样用Python实现地理编码

怎样用Python实现地理编码 专栏作者:时空Drei ❈ 时空Drei,德国德累斯顿工业大学在读博士生,个人的擅长领域为:利用Python进行空间数据(遥感G...

46370

扫码关注云+社区

领取腾讯云代金券