DIY党的福利!鹅厂程序员教你200元以内制作专属分体键盘

2023-10-29

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

本文由VellHe发表于云+社区专栏

前言

作为一名程序员,键盘在手,天下我有啊,不整把高大上的键盘怎么提升B格。之前一直想买个机械键盘,听说机械键盘敲代码和玩游戏都特别爽,也是装B神器。同时也觉得普通的键盘打字打久了手腕会有点酸酸的,因为敲键盘时都是要弯着手腕的,一点也不符合人体工程学。于是乎就想买一个分体的机械键盘,结果找了半天都没有比较中意的,找到几个人体工程学键盘,都是薄膜的,而且价格高得离谱,不就多个人体工程学光环嘛。。。身为程序员中的屌丝,岂能被金钱这种东西降低自身B格呢

普通机械键盘

img

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

img

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

3D打印的分体黑轴机械键盘

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

img


准备

* 工具

* 3D打印机 (打印外壳)

* 电烙铁

* 热熔胶 (固定按键用)

* 万用表

* 硬件

* Arduino Leonardo板 (驱动板)

* 黑轴轴体

* 二极管+电阻+杜邦线+万能板

* 小螺丝 (外壳装配)

* 软件

* SolidWorks (3D建模,设计外壳,可用任何3D建模软件代替哦)

* Arduino IDE (写键盘驱动程序)

是时候上点图了。。。

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

img

淘宝买的工具

img


步骤

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

* 键位设计

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

img

* 电路设计

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

img

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

* 按键冲突处理

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

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

img

* 电压动荡处理

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

* 最终电路设计

img

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

* 左手

img

* 右手

img

* 侧面

img

* 键帽设计

img

* 程序设计

#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打印机精度还是有点欠缺,特别是处理弧线):

img

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

img

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

img

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

img

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

img

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

img

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

img

* 外壳组装效果

img

img

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

img

* Leonardo到货,测试驱动

img

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

img

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

img

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

img

img

* 最后效果,键盘在手,天下我有

img

总结

做完整个键盘感觉非常有成就感,也非常实用,截止目前已经用了快半年时间了,已经非常喜欢机械键盘的按键反馈,也非常习惯分体键盘的布局,手腕也不再弯着,没有酸过了。最后来大致汇总下花费吧(屌丝程序员装B有望啦。。。)

* 80颗国产黑轴 104元

* 元器件 24元(邮费贵,还有很多二极管和万能板没用到)

* Leonardo 30元

大概材料花费在160元左右,比普通的机械键盘便宜多了,而且还是分体的,所有按键可随意自定义(驱动程序都自己写的,还有啥不能改的,O(∩_∩)O哈哈~)

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

img

问答
文字识别在格式上有什么要求?
相关阅读
超简单实现WEB页面顶部阅读进度条
FLV视频文件格式图示
基于日志分析的母机故障定位 ——机器学习应用
【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识

此文已由作者授权腾讯云+社区发布,更多原文请点击

搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!

海量技术实践经验,尽在云加社区

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DIY党的福利!鹅厂程序员教你200元以内制作专属分体键盘 的相关文章

  • 【Golang

    环境准备 GoLang go1 15 7 windows amd64 Docker 1 13 1 MySQL 8 0 28 一 利用容器部署mysql 1 首先通过docker pull mysql拉取mysql镜像 root k8s ma
  • Jetty篇一之初识Jetty

    前言 最近公司项目中用到了Jetty来作为项目的web容器 借此机会来分享一下我的学习心得 在学习Jetty之前 一定要了解一些Jetty的基本概念以及优缺点 这样才方便做更深入的学习 现在让我来慢慢揭开它的神秘面纱吧 基础 什么是Jett

随机推荐

  • 大数据模型案例库-涵盖多行业,超百个实战项目案例

    平台目前积累了大量的人工智能应用模型 不仅包括多年来人工智能企业服务方面的沉淀 还包括大量其他企业的真实项目应用模型 以及高校智能工作室成果模型 覆盖教育 医疗 交通 金融 科技 农业等18个行业 平台面向高校 企业 个人等广大用户群体 所
  • Candence原理图误删图页并保存退出后的恢复方法

    一早打开Candence准备工作 发现原理图少了几页 心里很慌 昨晚在画PCB的时候设置按了几次Delete键 没有反应 可能删了原理图 关闭的时候也没有看 直接保存退出了 看了之前拷贝备份的文件 时间有点久 那只能靠软件的自动备份功能了
  • C语言进阶(九)—— 函数指针和回调函数、预处理、动态库和静态库的使用、递归函数

    1 函数指针 1 1 函数类型 通过什么来区分两个不同的函数 一个函数在编译时被分配一个入口地址 这个地址就称为函数的指针 函数名代表函数的入口地址 函数三要素 名称 参数 返回值 C语言中的函数有自己特定的类型 c语言中通过typedef
  • 学习笔记-选择排序

    选择排序 将一个一维数组从小到大排序 思路 选择排序的思路是 首先认为数组的第一个数是最小的 保留它然后遍历它后面的数 跟它作比较 选择出最小的数和位置 遍历结束后 让这个最小的数和数组的第一位数交换 这样确定了第一个最小的数 之后重复这个
  • Unity AR阴影投射透明地面 仅渲染模型实时阴影 Shader实现

    亲测可用 上面就是实现的效果 仅仅渲染阴影 地面透明 也可以换成AR中的虚拟物体 AR中为的虚拟物体添加阴影 只用unity的光照投影是没办法实现的 或者需求是 角色需要投射阴影在墙上 但是墙不能显示 只渲染出阴影 相当于接受阴影的地面墙体
  • 吊打 CLIP 平均10个点,Meta 多模态通用模型 FLAVA真香啊

    厉害了 作者将单一模型运用于三个不同领域的不同任务 结构简单且训练直观 还能有着出色的表现 自Transformer横空出世 从NLP到CV 再到今天的多模态 无数基于Transformer的模型被应用于各类任务 似乎真的印证了当年文章的标
  • ldd not a dynamic executable

    在开发环境编译运行很ok的程序 到了客户的生产环境一直有问题 编译找不到库 类似这个样子 usr bin ld skipping incompatible lib libasound so when searching for lasoun
  • EXCEL-VBA:Workbooks.Open 参数 (打开文件)

    打开一个工作簿 语法 表达式 Open FileName UpdateLinks ReadOnly Format Password WriteResPassword IgnoreReadOnlyRecommended Origin Deli
  • UE5导入倾斜摄影

    前言 虚幻引擎是全球最先进的实时3D创作工具 可制作照片级逼真的视觉效果和沉浸式体验 2022年4月5号虚幻引擎发布了颠覆性的UE5 倾斜摄影是城市实景的基础 通过无人机采集实际照片再进行三维重建 常见的数据格式为osgb 本文主要介绍UE
  • JSP自定义标签的(生命周期与开发if,foreach,out)

    自定义标签定义 是用户定义的JSP语言元素 扩展名为tld的文件 tag标签的配置文件 通常放在WEB INF下面 自定义标签的开发及使用步骤 思路 1 1 创建一个标签助手类 继承BodyTagSupport 标签属性必须助手类的属性对应
  • 测试自动化平台

    https mp weixin qq com s WU5h8FW6BT5YZtlsSuCIcw 摘要 随着近几年国内IT行业高速发展 对测试工程师的要求也越来越高 其作用也越来越重要 但很多测试工程师也迎来了个人发展的瓶颈 下一步该向哪个方
  • clock的accuracy(tolerance)和jitter

    对于clock来说 有两个参数来衡量质量 分别是jitter和accuracy tolerance Jitter的单位是ps Tolerance的单位是ppm 百万分之 在晶振 RTC和Oscillator中也会找到类似参数 SOC和MCU
  • Hexo标签插件的使用

    tag 插件 Tag Plugin 是 Hexo 提供的一种快速生成特定内容的方式 例如 在标准 Markdown 语法中 我们无法指定图片的大小 这种情景 我们即可使用标签来解决 Hexo 内置来许多标签来帮助写作者可以更快的书写 完整的
  • docker运行nginx为什么要使用 nginx -g 'daemon off;'

    1 docker容器跑着为啥会挂掉 docker 容器默认会把容器内部第一个进程 也就是pid 1的程序作为docker容器是否正在运行的依据 如果docker 容器pid挂了 那么docker容器便会直接退出 2 docker run的时
  • 用Pandas做数据清洗的常用操作!

    大家好 我是小z 今天给大家分享一篇pandas数据清洗的干货 作为一名数据分析师 每天都在完成各种数据分析需求 其中数据清洗是必不可少的一个步骤 一般而言 当提及数据清洗时 其实是主要包括了缺失值处理 重复值处理和异常值处理三类操作 本文
  • DML语法整理笔记

    目录 1 什么是DML 2 两种INSERT方式 2 1 方式一 2 2 方式二 2 3 INSERT特点 2 4 两种方式对比 3 UPDATE 3 1 修改单标记录 3 2 修改多表记录 4 DELETE 4 1 方式一 可以删全表也可
  • 线性回归实战---Abalone鲍鱼年龄预测

    线性回归实现Abalone鲍鱼年龄预测 文章目录 线性回归实现Abalone鲍鱼年龄预测 一 环境准备 数据集简介 二 线性回归基础知识 什么是线性回归 最小二乘法 求解线性回归问题 三 Python代码 四 结果分析 前面我们使用手动编写
  • 2023年江苏省中职网络安全Web渗透测试解析(超详细)

    一 竞赛时间 180分钟 共计3小时 二 竞赛阶段 1 访问地址http 靶机IP web1 分析页面内容 获取flag值 Flag格式为flag xxx 2 访问地址http 靶机IP web2 分析页面内容 获取flag值 Flag格式
  • 什么是DNS欺骗和ARP欺骗?有何区别?

    欺骗攻击是黑客比较常用的一种攻击方式 也是一种隐蔽性较高的网络攻击方式 目前欺骗攻击的主要方式有 IP欺骗 ARP欺骗 DNS欺骗 Web欺骗 电子邮件欺骗等 那么DNS欺骗和ARP欺骗的区别是什么 具体请看下文 DNS欺骗 DNS欺骗是一
  • DIY党的福利!鹅厂程序员教你200元以内制作专属分体键盘

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由VellHe发表于云 社区专栏 前言 作为一名程序员 键盘在手 天下我有啊 不整把高大上的键盘怎么提升B格 之前一直想买个机械键盘 听说机械键盘敲代码和玩游戏都特别爽 也是装B