前言
作為一名程序員,鍵盤在手,天下我有啊,不整把高大上的鍵盤怎么提升B格。之前一直想買個(gè)機(jī)械鍵盤,聽說(shuō)機(jī)械鍵盤敲代碼和玩游戲都特別爽,也是裝B神器。同時(shí)也覺得普通的鍵盤打字打久了手腕會(huì)有點(diǎn)酸酸的,因?yàn)榍面I盤時(shí)都是要彎著手腕的,一點(diǎn)也不符合人體工程學(xué)。于是乎就想買一個(gè)分體的機(jī)械鍵盤,結(jié)果找了半天都沒有比較中意的,找到幾個(gè)人體工程學(xué)鍵盤,都是薄膜的,而且價(jià)格高得離譜,不就多個(gè)人體工程學(xué)光環(huán)嘛。。。身為程序員中的屌絲,豈能被金錢這種東西降低自身B格呢
普通機(jī)械鍵盤

帶 * “人體工程學(xué)光環(huán)” * 鍵盤

為了不要這么糾結(jié),就自己diy一個(gè)咯,正好有臺(tái)3D打印機(jī)(又一個(gè)裝B神器,你值得擁有,O(∩_∩)O哈哈~),全部外殼自己打印,控制板用Arduino Leonardo,原生支持鍵盤鼠標(biāo)驅(qū)動(dòng),軸體考慮到成本,先買了80顆國(guó)產(chǎn)黑軸做實(shí)驗(yàn),鍵帽也簡(jiǎn)單打印一下,說(shuō)干就干
3D打印的分體黑軸機(jī)械鍵盤
符合人體工程學(xué)的分體式設(shè)計(jì),全鍵無(wú)沖,可任意自定義快捷鍵,甚至可任性滴修改鍵位布局哦(重新設(shè)計(jì)外殼即可)

準(zhǔn)備
- 工具
- 3D打印機(jī) (打印外殼)
- 電烙鐵
- 熱熔膠 (固定按鍵用)
- 萬(wàn)用表
- 硬件
- Arduino Leonardo板 (驅(qū)動(dòng)板)
- 黑軸軸體
- 二極管+電阻+杜邦線+萬(wàn)能板
- 小螺絲 (外殼裝配)
- 軟件
- SolidWorks (3D建模,設(shè)計(jì)外殼,可用任何3D建模軟件代替哦)
- Arduino IDE (寫鍵盤驅(qū)動(dòng)程序)
是時(shí)候上點(diǎn)圖了。。。
自己組裝的三角洲式3D打印機(jī)

淘寶買的工具

步驟
先設(shè)計(jì)鍵位排布,使用 ** SolidWorks ** (任何3D建模軟件都o(jì)k的,只是我比較熟系SolidWorks哦)畫出簡(jiǎn)單的按鍵布局,先從左手開始,先完整的搞定左手能使用了,再做右手。設(shè)計(jì)好布局后制作支撐軸體的面板,然后設(shè)計(jì)電路,用飛線焊接,寫代碼測(cè)試按鍵是否都正常。電路正常后設(shè)計(jì)整個(gè)外殼,然后整體組裝。這就完工啦
- 鍵位設(shè)計(jì)
右手之所以外形扭曲,是因?yàn)?D打印機(jī)打印面積有限

- 電路設(shè)計(jì)
由于Arduino板io口有限,必須使用矩陣掃描來(lái)實(shí)現(xiàn)按鍵。掃描方式就是:定義n個(gè)io口為掃描口,m個(gè)接收口,組成一個(gè)n*m的矩陣。掃描口默認(rèn)全部都是低電壓,然后依次將每個(gè)掃描口單獨(dú)置為高電壓(即掃描動(dòng)作),當(dāng)這個(gè)高電壓的掃描口上連接的某個(gè)按鍵有按下時(shí),對(duì)應(yīng)的接收口電壓就也是高電壓,這時(shí)就可以定位到是哪個(gè)按鈕按下了,矩陣如圖所示:
Arduino有6個(gè)模擬口,14個(gè)數(shù)字口。我要做的鍵盤不超過(guò)80個(gè)鍵,所以使用8個(gè)數(shù)字口進(jìn)行脈沖掃描,6個(gè)模擬口加4個(gè)數(shù)字口用來(lái)接收脈沖來(lái)定位按鍵,這樣就實(shí)現(xiàn)了8*10的矩陣,支持80個(gè)鍵。還有2個(gè)數(shù)字鍵是空閑的,可以用于特殊按鍵定制。
- 按鍵沖突處理
如果按上圖簡(jiǎn)單實(shí)現(xiàn)會(huì)存在沖突問(wèn)題,當(dāng)接收口上有多個(gè)按鍵被按下時(shí),會(huì)存在回路,高電壓的掃描口和低電壓的掃描口發(fā)生短路,就不知道是哪個(gè)按鍵被按下了。一般鍵盤都是5鍵左右不沖突,也就是這個(gè)鍵盤有5個(gè)接收口,只要保證在同一個(gè)接收口上的按鍵不會(huì)同時(shí)按下就不會(huì)有沖突。
使用矩陣掃描方式就會(huì)有按鍵沖突問(wèn)題,我使用二極管來(lái)處理沖突,保證不會(huì)出現(xiàn)回路問(wèn)題,如圖(R是掃描口,C是接收口):

電壓動(dòng)蕩處理
二極管解決了沖突問(wèn)題,但是不能解決電壓動(dòng)蕩,電壓不穩(wěn)定有兩方面,第一就是當(dāng)掃描口高電壓變?yōu)榈碗妷簳r(shí),接收口電壓不會(huì)立即變成低電壓,所以在接收口都需要加一個(gè)下拉電阻,讓電壓立馬降下來(lái)。第二就是按鍵按下時(shí)接觸片碰撞時(shí)導(dǎo)致的電壓不穩(wěn),這個(gè)最好是通過(guò)加電容(和按鍵并聯(lián))去過(guò)濾波動(dòng)電壓,買元件時(shí)忘了買電容了,這里就簡(jiǎn)單粗暴了-
最終電路設(shè)計(jì)
-
外殼設(shè)計(jì)(第一期簡(jiǎn)單點(diǎn),不把電路板放到外殼內(nèi))
-
左手
-
右手
-
側(cè)面
-
-
鍵帽設(shè)計(jì)
程序設(shè)計(jì)
#include "Keyboard.h"
#include "HID.h"
#define scanPin_len 8
int scanPin[] = {4,5,6,7,0,1,2,3}; // 掃描pin,(默認(rèn)低電平,逐個(gè)輸出高電平)
int scanPos = 0; // 當(dāng)前掃描位
#define btnPinA_len 6
#define btnPinD_len 4
int btnPinA[] = {5,4,3,2,1,0}; // 按鈕pin,模擬端口
int btnPinD[] = {8,9,10,11}; // 按鈕pin,數(shù)字端口
#define btn_len 10
byte btn[scanPin_len][btn_len]; // 按鈕狀態(tài)
byte btnTmp[btn_len]; // 臨時(shí)按鈕狀態(tài)
#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);
}
// 初始化按鈕狀態(tài)
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() {
// 輪詢?cè)O(shè)置scanPin
for(int i=0; i<scanPin_len; i++) {
if(i == scanPos) {
digitalWrite(scanPin[i], HIGH);
} else {
digitalWrite(scanPin[i], LOW);
}
}
delay(5);
// 讀取按鍵信息
readBtn();
// 處理狀態(tài)有改變的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; // 下一個(gè)
}
void readBtn() {
// 先讀模擬口,再讀數(shù)字口
// 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打印機(jī)精度還是有點(diǎn)欠缺,特別是處理弧線):
-
打印機(jī)底板想換成玻璃的,結(jié)果新買的毛玻璃打印時(shí)受熱不均,碎了。。。還是乖乖用回美紋紙吧
-
在打印中,加熱頭松動(dòng)掉落,還好機(jī)器有自動(dòng)保護(hù),沒有造成火災(zāi)。幸虧代碼不是我寫的,要不然肯定會(huì)火災(zāi)的,_
-
打印過(guò)程中底座脫落,都打成鳥窩了。。。一路坎坷啊
-
軸體安裝,再次簡(jiǎn)單粗暴的沒有使用衛(wèi)星軸
-
飛線,這是第一版沒加二極管的連線,沒有做pcb,直接飛線連,簡(jiǎn)單高效,適合屌絲程序員,O(∩_∩)O哈哈~
-
ArduinoLeonardo還沒到貨,拿uno測(cè)試按鍵
-
外殼組裝效果

-
第一版鍵帽(字母是用美紋紙貼上去的,就是這么簡(jiǎn)單粗暴)
-
Leonardo到貨,測(cè)試驅(qū)動(dòng)
-
右手組裝成功(黑色更有感覺?。?/p>
-
新版鍵帽(白色),美紋紙弱爆了,必須整高端點(diǎn),然后發(fā)現(xiàn)白色材料打印效果很贊,光滑度也高了不少,打印材料還是相當(dāng)重要的
-
電路板,裸露在鍵盤外還是挺有極客范的哦

-
最后效果,鍵盤在手,天下我有
總結(jié)
做完整個(gè)鍵盤感覺非常有成就感,也非常實(shí)用,截止目前已經(jīng)用了快半年時(shí)間了,已經(jīng)非常喜歡機(jī)械鍵盤的按鍵反饋,也非常習(xí)慣分體鍵盤的布局,手腕也不再?gòu)澲瑳]有酸過(guò)了。最后來(lái)大致匯總下花費(fèi)吧(屌絲程序員裝B有望啦。。。)
- 80顆國(guó)產(chǎn)黑軸 104元
- 元器件 24元(郵費(fèi)貴,還有很多二極管和萬(wàn)能板沒用到)
- Leonardo 30元
大概材料花費(fèi)在160元左右,比普通的機(jī)械鍵盤便宜多了,而且還是分體的,所有按鍵可隨意自定義(驅(qū)動(dòng)程序都自己寫的,還有啥不能改的,O(∩_∩)O哈哈~)
最后曬一下我在小黑屋的辦公桌(這鍵盤是不是B格最高的? O(∩_∩)O~~)




















