鍵盤手焊還不夠,裏面跑Python更過癮

誰要本身作個鍵盤呢?仍是要手焊的鍵盤~python

若是,你平常寫的是軟件,最接近硬件制板的一次是大學時焊接收音機,那你跟我同樣,固然能夠試試作個鍵盤;或者,你平時設計的是硬件,手焊個鍵盤固然不在話下,寫個Python讓鍵盤跑起來也許會讓你興奮;亦或,你剛學完朋友圈裏Python課程,正準備大展身手,你的第一個Python項目,能夠是個鍵盤,感覺把Python握在手裏的感受……git

焊接本文中的鍵盤,筆者從早到晚花了一成天,而初版讓鍵盤跑起來的Python程序僅用了2小時,因而就有一個支持USB和藍牙的鍵盤,再給鍵盤裝上斑斕的色彩!github

若是你只關心跑在鍵盤裏的Python長什麼模樣,能夠直接跳到文章的倒數第100行,代碼放了在最後~app

涉及硬件,準備材料少不了。async

準備材料

  1. 黃銅線5米+(直徑0.8mm),也能夠用普通導線,但黃銅更酷一些
  2. 定位板,選了60%的,由於選擇多,鍵還少~ (好比睫毛外設的鋁合金衛星軸定位板)
  3. 衛星軸,由於不用PCB,只能選定位板類型的
  4. 軸61個,爲了辦公室炫耀(捱打),固然選清脆(擾人)的青軸啦
  5. 二極管61個,這是防多按鍵衝突(Anti-ghost),若是不多用3及以上鍵同時按的組合鍵(好比 ctrl + shift + c),這個能夠省掉(立創商城購買挺方便)
  6. 還須要個帶藍牙和USB的主控Pitaya Go,後面Python就跑在這個開發板裏面

鍵盤材料ide

固然還須要一些工具:工具

  1. 烙鐵、焊錫
  2. 鉗子,用來剪黃銅線
  3. 鑷子,萬一沒有,剪刀也能夠
  4. 萬用表,若是眼力足夠好,這也能夠省掉~

開始動手

  1. 安裝衛星軸

把衛星軸安裝在定位板上,能夠用潤滑脂把潤滑一下,能夠減小按鍵的噪聲,潤滑脂是半固體狀的,不是潤滑油哦ui

2. 安裝機械鍵盤軸spa

3. 焊接矩陣鍵盤插件

矩陣鍵盤分行、列,先把用二極管把軸的一個腳跟行線鏈接,並焊接好,二極管的方向能夠行到列,也能夠是列到行,但整個矩陣要保持二極管的方向一致。

把焊好一條行線後,能夠用萬用表測一下二極管的方向是否都是一致的,或者是否有虛焊。這裏用的是黑色貼片二極管,由於小,肉眼分辨方向至關考驗眼力,特別是焊接以後還有焊跡。也能夠選用插件的二極管,焊接更簡單一些,也買回了,不過,貼片的看起來更整潔一些,爲了顏值,仍是挑戰了難度係數更高的貼片的二極管。

而後再焊接列線,能夠在行上面用額外的黃銅線墊一下,再焊接,讓列線架空,避免行跟列短接了。

列隊完畢,等待集結~

4. 將行、列線鏈接到主控Pitaya Go的IO口

這裏矩陣鍵盤有5行、14列,Pitaya Go有20個可用的IO,剩下的1個IO還能夠接個燈。矩陣鍵盤和主控焊接完成後,最好用萬用表檢測一下各行各列是否短接,至少目測一下。

以上硬件算搭好了,Python要登場了。

用鍵盤跑Python——實現USB+藍牙鍵盤

電腦端Python一般是跑在CPython解釋器裏面,而嵌入式MCU中的Python起源7年前,Damien George開始寫的輕量級Python解釋器——MicroPython,咱們今天要用到是基於MicroPython的CircuitPython。

Adafruit爲CircuitPython開發了很是多硬件相關的庫,基於這些庫,咱們能夠快速實現一個鍵盤,這裏用到adafruit_bleadafruit_hid這兩個庫。實現一個USB+藍牙鍵盤100行就行,Talk is cheap,看代碼:

import time
from board import *
import digitalio
import usb_hid

import adafruit_ble
from adafruit_ble.advertising import Advertisement
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.standard.hid import HIDService
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode as _

ROWS = (P27, P13, P30, P20, P3)
COLS = (P26, P31, P29, P28, P5, P4, P24, P25, P23, P22, P14, P15, P16, P17)

KEYMAP = (
    _.ESCAPE, _.ONE, _.TWO, _.THREE, _.FOUR, _.FIVE, _.SIX, _.SEVEN, _.EIGHT, _.NINE, _.ZERO, _.MINUS, _.EQUALS, _.BACKSPACE,
    _.TAB, _.Q, _.W, _.E, _.R, _.T, _.Y, _.U, _.I, _.O, _.P, _.LEFT_BRACKET, _.RIGHT_BRACKET, _.BACKSLASH,
    _.CAPS_LOCK, _.A, _.S, _.D, _.F, _.G, _.H, _.J, _.K, _.L, _.SEMICOLON, _.QUOTE, None, _.ENTER,
    _.LEFT_SHIFT, _.Z, _.X, _.C, _.V, _.B, _.N, _.M, _.COMMA, _.PERIOD, _.FORWARD_SLASH, None, _.RIGHT_SHIFT, None,
    _.LEFT_CONTROL, _.LEFT_ALT, _.LEFT_GUI, None, None, _.SPACE, None, None, _.RIGHT_ALT, _.RIGHT_GUI, _.APPLICATION, _.RIGHT_CONTROL, None, None)

class Matrix:
    def __init__(self, rows=ROWS, cols=COLS):
        self.rows = []
        for pin in rows:
            io = digitalio.DigitalInOut(pin)
            io.direction = digitalio.Direction.OUTPUT
            io.drive_mode = digitalio.DriveMode.PUSH_PULL
            io.value = 0
            self.rows.append(io)
        self.cols = []
        for pin in cols:
            io = digitalio.DigitalInOut(pin)
            io.direction = digitalio.Direction.INPUT
            io.pull = digitalio.Pull.DOWN
            self.cols.append(io)
        self.pressed_keys = []

    def scan(self):
        new_keys = []
        pressed_keys = []
        released_keys = self.pressed_keys
        for r in range(len(self.rows)):
            self.rows[r].value = 1
            for c in range(len(self.cols)):
                if self.cols[c].value:
                    key = r * len(self.cols) + c
                    pressed_keys.append(key)
                    if key in released_keys:
                        released_keys.remove(key)
                    else:
                        new_keys.append(key)
            self.rows[r].value = 0
        self.pressed_keys = pressed_keys
        return pressed_keys, released_keys, new_keys

def main():
    hid = HIDService()
    advertisement = ProvideServicesAdvertisement(hid)
    advertisement.appearance = 961
    ble = adafruit_ble.BLERadio()
    if ble.connected:
        for c in ble.connections:
            c.disconnect()
    ble.start_advertising(advertisement)
    advertising = True
    ble_keyboard = Keyboard(hid.devices)

    matrix = Matrix()
    usb_keyboard = Keyboard(usb_hid.devices)

    while True:
        pressed_keys, released_keys, new_keys = matrix.scan()
        if released_keys:
            released_keycodes = list(map(lambda i: KEYMAP[i], released_keys))
            print('released keys {}'.format(released_keycodes))

            usb_keyboard.release(*released_keycodes)
            if ble.connected:
                advertising = False
                ble_keyboard.release(*released_keycodes)
        if new_keys:
            new_keycodes = list(map(lambda i: KEYMAP[i], new_keys))
            print('new keys {}'.format(new_keycodes))
            usb_keyboard.press(*new_keycodes)
            if ble.connected:
                advertising = False
                ble_keyboard.press(*new_keycodes)

        if not ble.connected and not advertising:
            ble.start_advertising(advertisement)
            advertising = True

        time.sleep(0.001)

if __name__ == '__main__':
    main()

這個是一個最簡單的Python版本鍵盤,咱們還能夠跟進一步

讓鍵盤更具生產力

這是一個 60% 鍵盤,缺乏了包括 F1~F十二、 方向鍵、小鍵盤等鍵位。

但經過引入 TMK 中的層級切換和組合按鍵功能,並融入 Toward a more useful keyboard 中把手指儘可能停留在 A、S、D、F  J、K、L、; 等起始鍵位的理念,咱們可讓這個小鍵盤更具生產力。

這裏引入 Tap-key 功能,即按某個按鍵不放激活另外的功能。

好比把 d 用做 Tap-key,即短按 d 輸出 d, 按住 d 不放則激活移動光標功能,H、J、K、L被映射爲方向鍵,而 U  N 則爲 PgUp 和 PgDn。

以上功能的實現見:

相關文章
相關標籤/搜索