Score
0
Watch 6 Star 31 Fork 3

makerdiary / python-keyboardPythonMIT

Join us
Explore and code with more than 5 million developers,Free private repositories !:)
Sign up
手焊的、跑 Python 的 USB + 蓝牙双模键盘 spread retract

Clone or download
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
README.md

Python Keyboard

中文 English

这是一个手焊的 USB 和蓝牙双模键盘,还是一个里面跑 Python 的键盘

自己动手造键盘

  1. 手焊键盘

  2. 参考 Pitaya Go 下载教程 更新 CircuitPython 固件,固件更新之后,Pitaya Go 会在电脑端模拟出一个名为 CIRCUITPY 的 U 盘和一个串口

  3. 下载两个 CircuitPython 库 - adafruit-ble & adafruit-hid,然后它们放在 CIRCUITPY U 盘的 lib 目录,U 盘内容结构,如下:

    CIRCUITPY
    ├───code.py
    └───lib
        ├───adafruit_ble
        └───adafruit_hid
  4. 把以下 Python 代码拷贝到 code.py,保存之后 code.py 会被重新加载运行,这时你就得到了一个 USB + 蓝牙的双模键盘

    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()

    如果你的键盘矩阵连接到 Pitaya Go 的 IO 有所不同, 你需要要更改代码中 ROWSCOLS

更进一步——让键盘更具生产力

这是一个 60% 键盘,缺少了包括 F1~F12、 方向键、小键盘等键位。

但通过引入 TMK 中的层级切换和组合按键功能,并融入 Toward a more useful keyboard 中把手指尽量停留在 ASDFJKL; 等起始键位的理念,我们可以让这个小键盘更具生产力。

这里引入 Tap-key 功能,即按某个按键不放激活另外的功能。

比如把 d 用作 Tap-key,即短按 d 输出 d, 按住 d 不放则激活移动光标功能,HJKL被映射为方向键,而 UN 则为 PgUp 和 PgDn

  • d + h
  • d + j
  • d + k
  • d + l
  • d + uPgUp
  • d + nPgDn

要实现这个功能,把 keyboard.pyaction_code.py 复制到 CIRCUITPY U 盘中,然后将 code.py 修改为:

# code.py

from keyboard import main

main()

另外,这个 Python 键盘还支持了同时按下两个按键 (间隔不超过25ms) 激活特殊功能,也计划支持长按 ; 用作 Ctrl,用 ; + c 替代 Ctrl + c,在 VS Code 中使用很方便。

Todo

  • 长按 ; 用作 Ctrl
  • 宏功能
  • 优化速度

Comments ( 7 )

Sign in for post a comment

Python
1
https://gitee.com/makerdiary/python-keyboard.git
git@gitee.com:makerdiary/python-keyboard.git
makerdiary
python-keyboard
python-keyboard
zh-cn

Help Search