DIY黨的福利!鵝廠程序員教你200元以內製作專屬分體鍵盤

歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~

本文由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 送你一份技術課程大禮包!

海量技術實踐經驗,盡在雲加社區

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章