CircuitPython
CircuitPython說是MicroPython的分支,支援更多晶片,有更多驅動,相對也更復雜。我用它主要是為了MicroPython上面沒有的HID,實現鍵鼠輸入。程式上和MicroPython有區別,尤其是GPIO的使用,這也影響了程式碼的複用。不過總歸是Python,移植也不難。標準庫的使用可以自行檢視官方文件,至於其他庫和驅動則要到處找,我也沒玩明白。
安裝庫
我使用的是源地的RP2040開發板,和我的這篇部落格中的相同也就是樹莓派PICO的晶片。安裝好CircuitPython後標準庫中自帶usb_hid
庫。
要實現打字的功能還要安裝adafruit_hid
庫,文件在這:Adafruit HID Library。
CircuitPython提供了包管理器cirup,確保你的開發板以隨身碟形式連線到電腦後,使用cirup install adafruit_hid
,即可自動檢測開發板型號並安裝庫。cirup使用期間可能需要掛梯子,也可以從adafruit_hid的倉庫clone下來用thonny直接丟進開發板目錄。
拼音輸入
我的拼音設定的是預設英文模式,按Shift切換漢語拼音。
import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kbd)
usrkey = digitalio.DigitalInOut(board.GP24)
usrkey.direction = digitalio.Direction.INPUT
usrkey.pull = digitalio.Pull.UP
def launch_notepad():
kbd.send(Keycode.WINDOWS, Keycode.R)
time.sleep(0.3)
layout.write('notepad\n')
time.sleep(0.5)
while True:
# 按下微控制器上的按鈕開始輸入
if not usrkey.value:
launch_notepad()
kbd.send(Keycode.SHIFT)
layout.write('meinvheguanzaixianfapai')
time.sleep(0.1)
layout.write('1\n')
time.sleep(0.2)
現象:
雖然成功輸入了漢字,但不同輸入法候選詞都有很大不同,就這個中英文切換的設定每個人都可能做自己的設定。這種方法無法保障在每臺電腦上正常輸入一樣的漢字。
Unicode輸入
確保輸入法在英文模式,不會開啟任何候選欄。
我希望有一種通用的輸入方式,最好是所有Unicode涵蓋的字元通用。bing了一下“windows輸入Unicode”,得到了一種方法。在notepad裡輸入16進位制的Unicode,緊跟著按Alt + x
即可轉為對應的文字。
今年是龍年,龘對應的Unicode是9f98,在notepad輸入
然後按Alt + x
先將準備好的大悲咒儲存在開發板目錄中
import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
import board
kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kbd)
usrkey = digitalio.DigitalInOut(board.GP24)
usrkey.direction = digitalio.Direction.INPUT
usrkey.pull = digitalio.Pull.UP
def launch_notepad():
kbd.send(Keycode.WINDOWS, Keycode.R)
time.sleep(0.3)
layout.write('notepad\n')
time.sleep(0.5)
def typing_unicode(line):
line = line.strip()
for char in line:
# 下面這一套函式看不懂可以自己一個個拆開試試
layout.write(hex(ord(char))[2:])
kbd.send(Keycode.ALT, Keycode.X)
kbd.send(Keycode.ENTER)
while True:
time.sleep(0.2)
if not usrkey.value:
launch_notepad()
with open("dbz.txt", "r") as f:
for line in f:
if not usrkey.value:
break
typing_unicode(line)
支援按鍵中止輸入
現在已經比較滿意了,但是在輸入較長的文章時,輸一半我不想繼續了,只能重新插拔。一般想法是把按鍵繫結中斷函式,按下改變輸入狀態,在輸入的時候同時輪詢輸入狀態。
結果一搜傻眼了,CircuitPython沒有提供MicroPython那種按鍵中斷,參考這篇文章,要用asyncio來管理按鍵中斷。這個asyncio也要如上文使用cirup安裝,不像MicroPython可以直接用。
import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
import asyncio
import board
import keypad
kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kbd)
def launch_notepad():
kbd.send(Keycode.WINDOWS, Keycode.R)
time.sleep(0.3)
layout.write('notepad\n')
time.sleep(0.5)
async def typing_unicode(line):
line = line.strip()
for char in line:
layout.write(hex(ord(char))[2:])
kbd.send(Keycode.ALT, Keycode.X)
await asyncio.sleep(0)
kbd.send(Keycode.ENTER)
async def usrkey_handler():
with keypad.Keys((board.GP24,), value_when_pressed=False) as keys:
is_typing = False
loop = asyncio.get_event_loop()
# 這裡cancel一次,這樣typing_task初始為done的狀態
typing_task = asyncio.create_task(typing_csb())
typing_task.cancel()
while True:
event = keys.events.get()
if event:
if event.released:
# 如果沒有初始化為done而是none,首次按鍵會拋異常
if not typing_task.done() and is_typing:
typing_task.cancel()
is_typing = False
else:
typing_task = asyncio.create_task(typing_csb())
is_typing = True
await asyncio.sleep(0)
async def typing_dbz():
launch_notepad()
with open("dbz.txt", "r") as f:
for line in f:
await typing_unicode(line)
asyncio.run(usrkey_handler())