腦鍵盤是現代科技中不可或缺的一部分。它是我們和計算機溝通的主要工具,通過鍵盤上的按鍵我們可以輸入文字、命令等信息。然而你是否曾想過,這個看似簡單的設備是如何設計出來的?又是如何制造出我們常用的每一個鍵?
一個標準的英文鍵盤通常有108個鍵,包括26個字母鍵、10個數字鍵以及一些功能鍵如Shift、Ctrl、Alt等。這些鍵分布在兩個部分:主鍵盤區和副鍵盤區。
設計一款好的電腦鍵盤需要考慮很多因素。例如,布局要合理,使得用戶在打字時能夠快速準確地找到每個鍵位。此外,按鍵的手感也非常重要,既要保證按下后能產生足夠的反饋力以確保用戶的操作被正確識別,又要避免過度的力度導致手指疲勞。
對于按鍵的制作工藝來說,常見的主要有注塑成型和沖壓成型兩種方法。其中,注塑成型是指將塑料材料加熱至熔融狀態,然后注入模具內冷卻固化形成形狀的過程。這種方法的優點是可以生產出復雜且立體的產品形狀,而且可以一次性完成多個產品的一致性制造。
另一種則是沖壓成型,它是利用壓力使金屬或非金屬材料變形成為所需的形狀和尺寸的技術。沖壓成型適用于大批量生產,具有成本低、效率高的優點。
無論是哪種方式,都需要對原材料進行嚴格的篩選,并在后續的加工過程中進行精細的質量控制,以確保每一批次的產品都能達到較高的質量要求。
除了基本的按鍵外,還有一些特殊的功能鍵如F1-F12、Delete、Insert等等。這些鍵的位置通常是固定的,為了方便用戶記憶,一般都會在鍵帽上印制相應的符號或者名稱。
電腦鍵盤的設計與按鍵制作工藝是一項涉及到多學科知識和技術的工作。從設計理念到實際制作,每一個環節都離不開精密的計算和精心的操作。只有這樣,才能打造出既美觀又實用的電腦鍵盤,為用戶提供更好的使用體驗。
嘍寶寶們,今天教大家做這個超解壓的鍵盤,來聽聽聲,連聲音都和真的鍵盤一模一樣。做法超簡單,共三張圖紙,快跟著我的節奏一起做。
·圖紙站在右卡紙上,把白剪掉,這樣子大便折疊,再從中間剪,沿線折疊一張紙,向后,不要拆錯普了,跟著我的方法一起拆。
·在這個位置深貝,它求占起來,全部都這樣子做好。
·按照字母的順序,一個一個剪將半占上去。
·這個上下鍵盤沿線剪開,全部樂占完了。
真的超解壓,超好玩,光聽著聲音,你也來做一個吧。
感謝點贊關注哦。
生命不止,折騰不息。”對工程師來說,沒有任何一件電子產品可以稱作廢品。
功能不夠豐富?自己焊一塊板子。使用不夠方便?自己加一個物理外掛。有線鍵盤太麻煩?自己改裝成無線的。EEwolrd論壇的工程師們就自己動手,把小小一塊鍵盤改裝得五花八門。
鍵盤俠終結者之自動反擊鍵盤
作者:彭丙浩 原帖地址:http://www.eeworld.com.cn/avLy9WD
我比較喜歡上網,網絡世界是個沒有硝煙的江湖,行走江湖,必須有件趁手的兵器,傳統的機械鍵盤火力已經無法滿足時代需要,于是我造了這個自動反擊鍵盤,MCU+繼電器+鍵盤電路板 ;當然最節約成本的方案是搞個ST帶USB接口的MCU芯片,直接輸入字符,我對USB協議不太熟,于是就弄個成品鍵盤直接拿來用。當前這個姥爺方案簡單易用,效果還不錯。
機器視覺打造全自動老板鍵智能鍵盤
作者:eew_dy9f48 原帖地址:http://www.eeworld.com.cn/afXzvHO
一、作品簡介
自帶鍵盤的樹莓派Pi400,其實可以看作一塊強大的智能鍵盤,作為電腦的輔助;按照項目內容層層遞進,首先,先配置樹莓派p400,讓它作為一塊普通電腦鍵盤;接下來,我想嘗試結合一些人工智能實現鍵盤命令的自動執行,比如全自動老板鍵,通過ESP32-CAM作為樹莓派的網絡攝像頭,這樣可以脫離連線限制,可以部署在任何地方。然后一旦識別到老板人臉,就自動發送Alt+Tab等老板鍵,瞬間切換至工作界面。除此之外,由于在上述任務中我們已經實現了樹莓派HID鍵盤的配置,因此我們還可以使用它來作為游戲助手,實現鍵盤宏,按一個按鍵打出一整套combo。由于宏是內建在鍵盤中的,在pc端并沒有任何相關進程,所以不會被游戲判定為使用輔助工具。這就可以實現很多功能上的延申,大家可以自行玩耍。
二、系統框圖
功能模塊一共三部分:
三、各部分功能說明
首先,先介紹下項目中包含的硬件設計。
這個項目包括了無線網絡攝像頭的制作。雖然網上有現成的ESP32CAM模塊售賣,且價格非常便宜。但是由于做工良莠不齊,導致經常翻車。而且,ESP32性能較弱,且不支持USB,如果未來想做一些其他的開發也可能會力不從心。因此,趁這個項目的機會,我打算直接制作一塊ESP32S2 CAM開發板出來。
這個攝像頭開發板其實我后面還重新繪制了第二個版本,增加了tf卡槽,同時修復了飛線的問題,并由于板子面積有限將所有封裝換成了0402。但由于新版的板子打樣回來焊接難度有點大,還一直遲遲沒有動手,因此先使用老版本的板子完成項目。
接下來說說軟件方面,我們具體介紹一下每一個功能模塊的實現方法。
1. Pi400 HID 鍵盤功能的實現。
在github上有一個zero_hid的庫,可以實現使用樹莓派zero模擬hid鍵盤。但這個庫有一些問題,直接使用在組合鍵上會出很多的問題,因此我參考這個項目,重寫了一下這個庫。
首先科普一下HID協議,HID鍵盤協議是一種基于報文的協議,通過在USB總線上進行通信。當用戶按下鍵盤上的按鍵時,鍵盤將生成一個HID報文,并將其發送到計算機。計算機收到報文后,根據報文的內容來模擬相應的鍵盤操作,例如在文本編輯器中輸入字符或執行特定的功能。
HID鍵盤報文包含多個字段,其中最重要的是按鍵碼(Keycode)。按鍵碼表示按下的鍵的唯一標識符,例如“A”鍵的按鍵碼是0x04。除了按鍵碼外,報文還可以包含其他信息,如修飾鍵(如Shift、Ctrl和Alt鍵)的狀態和組合鍵的狀態。
因此,在合成報文前,我們先要知道我們想輸入的按鍵哪些是修飾鍵,而哪些是按鍵,他們要分開進行處理。
在進入代碼部分前,我們需要先安裝一下驅動。首先先新建一個文件,命名為isticktoit_usb,添加可執行權限,并填入以下內容:
···
#!/bin/bash
cd /sys/kernel/config/usb_gadget/
mkdir -p isticktoit
cd isticktoit
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "fedcba9876543210" > strings/0x409/serialnumber
echo "Tobias Girstmair" > strings/0x409/manufacturer
echo "iSticktoit.net USB Device" > strings/0x409/product
mkdir -p configs/c.1/strings/0x409
echo "Config 1: ECM network" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower
# Add functions here
mkdir -p functions/hid.usb0
echo 1 > functions/hid.usb0/protocol
echo 1 > functions/hid.usb0/subclass
echo 8 > functions/hid.usb0/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc
ln -s functions/hid.usb0 configs/c.1/
# End functions
ls /sys/class/udc > UDC
···
接著運行以下命令,完成驅動配置:
···
#!/bin/bash
echo "" | sudo tee -a /boot/config.txt
echo "# BEGIN HID Keyboard Simulation" | sudo tee -a /boot/config.txt
echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt
echo "# END HID Keyboard Simulation" | sudo tee -a /boot/config.txt
echo "" | sudo tee -a /etc/modules
echo "# BEGIN HID Keyboard Simulation" | sudo tee -a /etc/modules
echo "dwc2" | sudo tee -a /etc/modules
echo "libcomposite" | sudo tee -a /etc/modules
echo "# END HID Keyboard Simulation" | sudo tee -a /etc/modules
# Move to before exit 0
echo "" | sudo tee -a /etc/rc.local
echo "# BEGIN HID Keyboard Simulation" | sudo tee -a /etc/rc.local
echo "sudo ./isticktoit_usb" | sudo tee -a /etc/rc.local
echo "# END HID Keyboard Simulation" | sudo tee -a /etc/rc.local
···
完成后,以后每次重啟完成,只需要運行一下isticktoit_usb即可。
處理報文部分的代碼如下:
···
from typing import List
from .hid import hidwrite
from .hid.keycodes import KeyCodes
from time import sleep
import json
import pkgutil
import os
import pathlib
class Keyboard:
def __init__(self, dev='/dev/hidg0') -> None:
self.dev=dev
self.set_layout()
self.control_pressed=[]
self.key_pressed=[]
def list_layout(self):
keymaps_dir=pathlib.Path(__file__).parent.absolute() / 'keymaps'
keymaps=os.listdir(keymaps_dir)
files=[f for f in keymaps if f.endswith('.json')]
for count, fname in enumerate(files, 1):
with open(keymaps_dir / fname , encoding='UTF-8') as f:
content=json.load(f)
name, desc=content['Name'], content['Description']
print(f'{count}. {name}: {desc}')
def set_layout(self, language='US'):
self.layout=json.loads( pkgutil.get_data(__name__, f"keymaps/{language}.json").decode() )
def gen_list(self, keys=[]):
_control_pressed=[]
_key_pressed=[]
for key in keys:
if key[:3]=="MOD":
_control_pressed.append(KeyCodes[key])
else:
_key_pressed.append(KeyCodes[key])
return _control_pressed, _key_pressed
def gen_buf(self):
self.buf=[sum(self.control_pressed),0] + self.key_pressed
self.buf +=[0] * (8 - len(self.buf)) # fill to lenth 8
##########################################################################
# For user
def press(self, keys=[], additive=False, hold=False):
_control_pressed, _key_pressed=self.gen_list(keys)
if not additive:
self.control_pressed=[]
self.key_pressed=[]
self.control_pressed.extend(_control_pressed)
self.control_pressed=list(set(self.control_pressed)) # remove repeated items
self.key_pressed.extend(_key_pressed)
self.key_pressed=list(set(self.key_pressed))[:6] # remove repeated items and cut until 6 items
self.gen_buf()
hidwrite.write_to_hid_interface(self.dev, self.buf)
if not hold:
self.release(keys)
def release(self, keys=[]):
_control_pressed, _key_pressed=self.gen_list(keys)
try:
self.control_pressed=list(set(self.control_pressed) - set(_control_pressed))
except:
pass
try:
self.key_pressed=list(set(self.key_pressed) - set(_key_pressed))
except:
pass
self.gen_buf()
hidwrite.write_to_hid_interface(self.dev, self.buf)
def release_all(self):
self.control_pressed=[]
self.key_pressed=[]
self.gen_buf()
hidwrite.write_to_hid_interface(self.dev, self.buf)
def text(self, string, delay=0):
for c in string:
key_map=self.layout['Mapping'][c]
key_map=key_map[0]
mods=key_map['Modifiers']
keys=key_map['Keys']
self.press(mods + keys)
sleep(delay)
···
上面這段代碼把想要輸出的按鍵分為control(修飾按鍵)和key(普通按鍵)兩塊,再組合形成報文列表。使用的邏輯是輸入當前想要按下的按鍵狀態,然后程序發送對應的報文。
測試一下:
···
import os
import zero_hid
if os.geteuid() !=0:
raise ImportError('You must be root to use this library on linux.')
k=zero_hid.Keyboard()
k.press(["KEY_H"], additive=False, hold=False)
k.press(["KEY_E"], additive=False, hold=False)
k.press(["KEY_L"], additive=False, hold=False)
k.press(["KEY_L"], additive=False, hold=False)
k.press(["KEY_O"], additive=False, hold=False)
···
press方法中填入的是一個list,表示當前按下的所有按鍵。具體的鍵值列表在zero_hid/keymaps/US.json中。
如果電腦成功打印,表示功能正常。
2. Pi400 鍵盤動作的捕捉與獨占。
一般在python中捕獲鍵盤動作,大家使用的都是keyboard庫,簡單好用。但keyboard庫有個致命的問題,就是無法獨占鍵盤。這在我們當前的應用中是無法接受的。試想一下,當我們想發送ctrl+alt+del時,一旦按下,樹莓派和電腦都進入了安全模式。你無法預期在鍵盤上的操作會在樹莓派系統中整出什么幺蛾子。因此,我們需要在捕捉鍵盤動作的同時,對鍵盤資源進行獨占,以此避免按鍵被其他的進程捕獲。在這里我們使用evdev庫來實現。
···
import os
import evdev
if os.geteuid() !=0:
raise ImportError('You must be root to use this library on linux.')
dev=evdev.InputDevice('/dev/input/event0')
dev.grab() # grab 是為了獨占,保證此設備不會被別的進程捕獲
for event in dev.read_loop():
key=evdev.categorize(event)
if isinstance(key, evdev.KeyEvent) and key.keystate !=2:
print(key.keycode)
···
按下按鍵,我們就可以看到對應的鍵值被打印在終端里。
接下來只需要把抓取到的鍵值組合成列表,發送到我們上一步實現的hid中即可。
細心的同學可能會意識到,evdev抓取到的的鍵值如果和hid的鍵值不匹配怎么辦?這里我們就需要人工進行匹配,創建一個文件,將他們一一對應起來。
在項目文件夾下創建一個codemap.csv文件,寫入以下對應:
···
KEY_LEFTCTRL,MOD_LEFT_CONTROL
KEY_RIGHTCTRL,MOD_RIGHT_CONTROL
KEY_LEFTALT,MOD_LEFT_ALT
KEY_RIGHTALT,MOD_RIGHT_ALT
KEY_LEFTSHIFT,MOD_LEFT_SHIFT
KEY_RIGHTSHIFT,MOD_RIGHT_SHIFT
,
KEY_LEFTMETA,MOD_LEFT_GUI
,
,
KEY_ESC,KEY_ESC
KEY_TAB,KEY_TAB
KEY_CAPSLOCK,KEY_CAPSLOCK
,
KEY_NUMLOCK,KEY_NUMLOCK
KEY_SYSRQ,KEY_SYSRQ
KEY_DELETE,KEY_DELETE
KEY_INSERT,KEY_INSERT
KEY_BACKSPACE,KEY_BACKSPACE
KEY_ENTER,KEY_ENTER
,
KEY_SPACE,KEY_SPACE
,
KEY_UP,KEY_UP
KEY_DOWN,KEY_DOWN
KEY_LEFT,KEY_LEFT
KEY_RIGHT,KEY_RIGHT
,
KEY_PAGEUP,KEY_PAGEUP
KEY_PAGEDOWN,KEY_PAGEDOWN
KEY_HOME,KEY_HOME
KEY_END,KEY_END
,
KEY_F1,KEY_F1
KEY_F2,KEY_F2
KEY_F3,KEY_F3
KEY_F4,KEY_F4
KEY_F5,KEY_F5
KEY_F6,KEY_F6
KEY_F7,KEY_F7
KEY_F8,KEY_F8
KEY_F9,KEY_F9
KEY_F10,KEY_F10
KEY_F11,KEY_F11
KEY_F12,KEY_F12
,
KEY_GRAVE,KEY_GRAVE
KEY_1,KEY_1
KEY_2,KEY_2
KEY_3,KEY_3
KEY_4,KEY_4
KEY_5,KEY_5
KEY_6,KEY_6
KEY_7,KEY_7
KEY_8,KEY_8
KEY_9,KEY_9
KEY_0,KEY_0
KEY_MINUS,KEY_MINUS
KEY_EQUAL,KEY_EQUAL
,
KEY_Q,KEY_Q
KEY_W,KEY_W
KEY_E,KEY_E
KEY_R,KEY_R
KEY_T,KEY_T
KEY_Y,KEY_Y
KEY_U,KEY_U
KEY_I,KEY_I
KEY_O,KEY_O
KEY_P,KEY_P
KEY_A,KEY_A
KEY_S,KEY_S
KEY_D,KEY_D
KEY_F,KEY_F
KEY_G,KEY_G
KEY_H,KEY_H
KEY_J,KEY_J
KEY_K,KEY_K
KEY_L,KEY_L
KEY_Z,KEY_Z
KEY_X,KEY_X
KEY_C,KEY_C
KEY_V,KEY_V
KEY_B,KEY_B
KEY_N,KEY_N
KEY_M,KEY_M
,
KEY_LEFTBRACE,KEY_LEFTBRACE
KEY_RIGHTBRACE,KEY_RIGHTBRACE
KEY_BACKSLASH,KEY_BACKSLASH
KEY_SEMICOLON,KEY_SEMICOLON
KEY_APOSTROPHE,KEY_APOSTROPHE
KEY_COMMA,KEY_COMMA
KEY_DOT,KEY_DOT
KEY_SLASH,KEY_SLASH
,
KEY_KP0,KEY_KP0
KEY_KP1,KEY_KP1
KEY_KP2,KEY_KP2
KEY_KP3,KEY_KP3
KEY_KP4,KEY_KP4
KEY_KP5,KEY_KP5
KEY_KP6,KEY_KP6
KEY_KP7,KEY_KP7
KEY_KP8,KEY_KP8
KEY_KP9,KEY_KP9
KEY_KPASTERISK,KEY_KPASTERISK
KEY_KPMINUS,KEY_KPMINUS
KEY_KPPLUS,KEY_KPPLUS
KEY_KPDOT,KEY_KPDOT
KEY_KPSLASH,KEY_KPSLASH
···
接著在代碼中,我們只需要打開該文件,轉換為字典,刪除空白項,即可制作好對應的字典。每次捕捉到按鍵后,利用字典翻譯一下即可。
···
with open('./codemap.csv', 'r') as file:
reader=csv.reader(file)
codemap={rows[0]:rows[1] for rows in reader}
del codemap[""]
···
3. 人臉識別在Pi400上的實現。
實現人臉識別我們使用的工具是ultralytics。Ultralytics安裝非常簡單,只需要pip install ultralytics即可。唯一需要注意的是我們需要更換一下pytorch的版本,否則會出現Segmentation fault
···
pip uninstall torch torchvision
pip install torch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2
···
完成安裝后,我們要使用stream的方法,從網絡推流中獲取到視頻流。視頻流來源是我們一開始制作的ESP32 S2 CAM開發板。開發板上燒錄的是arduino ide上的官方CameraWebServer例程。除了常規的選擇對應開發板并修改wifi信息外,我們還需要自定義一下開發板引腳。假設我們這里選擇#define CAMERA_MODEL_ESP32S2_CAM_BOARD,那么我們要把camera_pins.h中的對應部分改成:
···
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 2
#define SIOD_GPIO_NUM 42
#define SIOC_GPIO_NUM 41
#define Y9_GPIO_NUM 1
#define Y8_GPIO_NUM 3
#define Y7_GPIO_NUM 4
#define Y6_GPIO_NUM 6
#define Y5_GPIO_NUM 8
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 9
#define Y2_GPIO_NUM 7
#define VSYNC_GPIO_NUM 16
#define HREF_GPIO_NUM 15
#define PCLK_GPIO_NUM 5
#define LED_GPIO_NUM 45
···
按照下圖所示配置進行燒錄即可。
Pi400這邊的代碼比較簡單,ultralytics已經被設計的非常易于使用。
···
from ultralytics import YOLO
import requests
import time
url="http://192.168.8.171"
model=YOLO("yolov8n.pt")
requests.get(url+"/control?var=framesize&val=" + str(8))
results=model.predict(url+":81/stream", stream=True, show=True, conf=0.5)
for result in results:
for box in result.boxes:
class_id=result.names[box.cls[0].item()]
cords=box.xyxy[0].tolist()
cords=[round(x) for x in cords]
conf=round(box.conf[0].item(), 2)
print("Object type:", class_id)
print("Coordinates:", cords)
print("Probability:", conf)
print("---")
···
如果所安裝的樹莓派系統是桌面版本,我們在桌面版本上運行以上程序,就可以看到畫面。如果是僅有terminal的系統,terminal中也會有相應信息打印。
最后我們只需要整合上述功能,就可以實現帶有全自動老板鍵的智能鍵盤。
完整主程序代碼如下:
···
import zero_hid
import evdev
import csv
import signal
import os
import threading
if os.geteuid() !=0:
raise ImportError('You must be root to use this library on linux.')
k=zero_hid.Keyboard()
# dev=evdev.InputDevice('/dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd')
dev=evdev.InputDevice('/dev/input/event0')
dev.grab() # grab 是為了獨占,保證此設備不會被別的進程捕獲
with open('./codemap.csv', 'r') as file:
reader=csv.reader(file)
codemap={rows[0]:rows[1] for rows in reader}
del codemap[""]
curr_pressed=[]
def key_input(key):
global curr_pressed
if isinstance(key, evdev.KeyEvent) and key.keystate !=2:
if key.keystate==1:
curr_pressed.append(key.keycode)
if key.keystate==0:
curr_pressed.remove(key.keycode)
print("\r" + "CODE: " + key.keycode + " ;STAT: " + str(key.keystate) + " "*40, end="")
keys=[codemap[i] for i in curr_pressed]
k.press(keys, additive=False, hold=True)
def handler(signal, frame):
k.release_all()
dev.ungrab()
dev.close()
exit()
signal.signal(signal.SIGTSTP, handler) # Ctrl+Z
signal.signal(signal.SIGINT, handler) # Ctrl+C
def thread1():
for event in dev.read_loop():
try:
key_input(evdev.categorize(event))
except Exception as error:
print(error)
t1=threading.Thread(target=thread1, daemon=True)
t1.start()
from ultralytics import YOLO
import requests
url="http://192.168.8.171"
model=YOLO("yolov8n.pt")
requests.get(url+"/control?var=framesize&val=" + str(8))
results=model.predict(url+":81/stream", stream=True, show=True, conf=0.5)
delay=1
count=0
mode=0
pre_mode=0
for result in results:
try:
for box in result.boxes:
class_id=result.names[box.cls[0].item()]
cords=box.xyxy[0].tolist()
cords=[round(x) for x in cords]
conf=round(box.conf[0].item(), 2)
print("Object type:", class_id)
print("Coordinates:", cords)
print("Probability:", conf)
print("---")
if class_id=="person":
mode=1
count=0
if mode !=pre_mode:
pre_mode=mode
k.press(["MOD_LEFT_ALT","KEY_TAB"], additive=False, hold=False)
print("triggered!!!")
count +=1
if count > delay:
mode=0
pre_mode=mode
except Exception as error:
print(error)
···
羅技K260鍵盤套裝改鋰電池供電及加工作指示
作者:dcexpert 原帖地址:http://www.eeworld.com.cn/a0Guf54
看到手邊的羅技K260無線鍵盤,就想改造一下。
K260使用了兩個AAA電池供電,雖說K260省電已經做的很不錯,但是為了環保,以及避免電池沒電時找不到電池更換,還有電池漏液造成的腐蝕,就想改成鋰電池供電。
鍵盤很容易拆開,取下反面的十多顆螺絲,用撬棒稍微用力把外殼的卡扣松開,就可以輕松把后蓋取下
拆開后可以看到按鍵部分分三層,一層是按鍵部分,另外兩層分別是按鍵的行列電路。這也是薄膜鍵盤的標準結構。
主控芯片使用了 nordic 的 nrf31504,這是nordic公司的一顆集成增強8051內核的2.4G無線收發器,帶有16K ROM和512字節RAM。在nordic的網站上已經搜索不到這個芯片,估計已經停產了。
比較有趣的是天線部分,居然把長度標上去了。
系統原來使用2節AAA電池供電,電壓范圍是2-3.2V,而主芯片 nrf31504的電源范圍是 1.9-3.6V。使用鋰電池供電(電壓范圍是3.3-4.2V),最簡單方式就是加一個二極管,將電源降低0.6V,這樣電源范圍就是2.7-3.6V,可以滿足電壓要求。但是這樣改造感覺缺少了一點趣味性,就想能不能換一種方式,增加一個LED根據電流指示工作狀態,既能反映出工作狀態,看起來也更有科技感。用萬用表實測鍵盤的待機電流約35uA,發射時電流約5mA。電流可以通過電流傳感器(如TI的INA180)轉換為電壓,但是春節期間無法打樣,PCB打樣焊接周期也較長,又不想繼續等待,就想還有沒有其它方式。考慮到鍵盤的功耗很低,如果把LED串聯到電源中,也是可以滿足功耗要求,但是電壓就不夠了,這時就需要提高供電的電壓才行。一顆紅色LED導通壓降約1.5V,黃色和普通綠色LED約1.8V,藍色白色LED的壓降較高,約2.3-2.7V。這樣算下來,使用5V左右供電在串聯一個黃色LED正合適,這樣的話使用移動電源或TWS耳機充電盒的主板,就可以實現充電管理和升壓兩個功能,既簡單又能滿足要求。
雖然鍵盤看起來很大,但是內部空間其實比較小。經過翻箱倒柜找了一圈,終于在箱底找出幾個合適的元件。
電池,用了兩種電池,并聯以提高容量。一個140mAH,另一個200mAH。
這個圓柱形電池不知道大家認識不
拆開后是這樣的。
移動電源主板,這個還是幾年前社區網友老楊提供的。把USB座拆掉后,正好可以放在鍵盤的空隙中。
主要元件的布局
因為鍵盤是不透明的,為了讓指示燈露出來,用電動螺絲刀和鉆頭,在適當的位置鉆孔。充電指示燈處用1.8mm鉆頭,工作指示燈用3mm的LED,使用2.8mm的鉆頭。充電指示燈的空用熱熔膠堵住,防止進灰進水,同時也能透光。
插入LED,并用膠水固定。
再焊接各部分導線
用透明膠帶固定電源板和導線
最后測試一下充電和鍵盤功能,沒有問題就可以將后蓋裝回去。下面是改裝后的效果:
充電指示燈效果。
待機時指示燈狀態,每秒喚醒10次左右。
按下鍵盤,指示燈狀態,可以看到按鍵后不會立即休眠。
作者:IC爬蟲 原帖地址:http://www.eeworld.com.cn/a00SefD
CIY64 這款客制化鍵盤我有兩把,使用快兩年了,幾個月就要換電池,這些廢棄的電池沒地方回收真是有點污染環境,而且有時碰到沒有備用電池的情況非常抓狂,兩節南孚7號電池也要6塊錢,所以早就有把鍵盤改成充電的想法。本來想使用無線充電的方案,但是這把鍵盤的腳撐是不可調節的,而且高低有限,充電時不好放在無線充電器上。又不想給這把鍵盤的外殼開孔,所以做個能在7號電池倉放下的充電板,1000mah的鋰電池估計可以用非常的久,需要用的時候拉出來充其實也沒啥問題。
方案:使用ME4054作為充電IC,這款IC最大可以800ma的電流給鋰電池充電,但是發熱比較大,我不需要快速給鋰電池充電,而且避免電路板過熱,可以使用這顆芯片的外部配置電阻就充電電流限制在300mA,這個時候芯片溫度還可以接受。這款鍵盤使用的是兩節7號電池供電,為了避免鋰電池的電壓過高損壞鍵盤的原有的電路,加了一顆PAM2305AABADJ DC-DC降壓芯片,將共給鍵盤控制板的電壓限制到2.6V左右。
電路:
安裝:
充電電流,這張圖是我將充電配置為100ma,有點慢,后面改成了300MA,給1000mah的電池充電,從3.7v充滿,耗時一個半小時:
作者:pomin 原帖地址:http://www.eeworld.com.cn/a5WjDaT
結合USB-HOST和藍牙HID鍵盤的例程制作了一個有線鍵盤轉藍牙鍵盤的設備,代碼如下:
/******************************************************************************/
/* 頭文件包含 */
#include "CONFIG.h"
#include "HAL.h"
#include "hiddev.h"
#include "hidkbd.h"
/*********************************************************************
* GLOBAL TYPEDEFS
*/
__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
__attribute__((aligned(4))) uint8_t RxBuffer[MAX_PACKET_SIZE]; // IN, must even address
__attribute__((aligned(4))) uint8_t TxBuffer[MAX_PACKET_SIZE]; // OUT, must even address
extern uint8_t need_send;
#if(defined(BLE_MAC)) && (BLE_MAC==TRUE)
const uint8_t MacAddr[6]={0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
#endif
/*********************************************************************
* @fn Main_Circulation
*
* [url=home.php?mod=space&uid=159083]@brief[/url] 主循環
*
* [url=home.php?mod=space&uid=784970]@return[/url] none
*/
__HIGH_CODE
void Main_Circulation()
{
TMOS_SystemProcess();
}
/*********************************************************************
* @fn main
*
* @brief 主函數
*
* @return none
*/
int main(void)
{
uint8_t i, s, k, len, endp;
uint16_t loc;
#if(defined(DCDC_ENABLE)) && (DCDC_ENABLE==TRUE)
PWR_DCDCCfg(ENABLE);
#endif
SetSysClock(CLK_SOURCE_PLL_60MHz);
#if(defined(HAL_SLEEP)) && (HAL_SLEEP==TRUE)
GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
#endif
/* 開啟電壓監控 */
PowerMonitor(ENABLE, HALevel_2V1);
#ifdef DEBUG
GPIOA_SetBits(bTXD1);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
UART1_DefInit();
#endif
PRINT("%s\n", VER_LIB);
CH58X_BLEInit();
HAL_Init();
GAPRole_PeripheralInit();
HidDev_Init();
HidEmu_Init();
PRINT("Start @ChipID=%02X\n", R8_CHIP_ID);
pU2HOST_RX_RAM_Addr=RxBuffer;
pU2HOST_TX_RAM_Addr=TxBuffer;
USB2_HostInit();
PRINT("Wait Device In\n");
while(1)
{
Main_Circulation();
s=ERR_SUCCESS;
if(R8_USB2_INT_FG & RB_UIF_DETECT)
{ // 如果有USB主機檢測中斷則處理
R8_USB2_INT_FG=RB_UIF_DETECT;
s=AnalyzeRootU2Hub();
if(s==ERR_USB_CONNECT)
FoundNewU2Dev=1;
}
if(FoundNewU2Dev || s==ERR_USB_CONNECT)
{ // 有新的USB設備插入
FoundNewU2Dev=0;
mDelaymS(200); // 由于USB設備剛插入尚未穩定,故等待USB設備數百毫秒,消除插拔抖動
s=InitRootU2Device(); // 初始化USB設備
if(s !=ERR_SUCCESS)
{
PRINT("EnumAllRootDev err=%02X\n", (uint16_t)s);
}
}
/* 如果下端連接的是HUB,則先枚舉HUB */
s=EnumAllU2HubPort(); // 枚舉所有ROOT-HUB端口下外部HUB后的二級USB設備
if(s !=ERR_SUCCESS)
{ // 可能是HUB斷開了
PRINT("EnumAllHubPort err=%02X\n", (uint16_t)s);
}
/* 如果設備是鍵盤 */
loc=U2SearchTypeDevice(DEV_TYPE_KEYBOARD); // 在ROOT-HUB以及外部HUB各端口上搜索指定類型的設備所在的端口號
if(loc !=0xFFFF)
{ // 找到了,如果有兩個KeyBoard如何處理?
i=(uint8_t)(loc >> 8);
len=(uint8_t)loc;
SelectU2HubPort(len); // 選擇操作指定的ROOT-HUB端口,設置當前USB速度以及被操作設備的USB地址
endp=len ? DevOnU2HubPort[len - 1].GpVar[0] : ThisUsb2Dev.GpVar[0]; // 中斷端點的地址,位7用于同步標志位
if(endp & USB_ENDP_ADDR_MASK)
{ // 端點有效
s=USB2HostTransact(USB_PID_IN << 4 | endp & 0x7F, endp & 0x80 ? RB_UH_R_TOG | RB_UH_T_TOG : 0, 0); // 傳輸事務,獲取數據,NAK不重試
if(s==ERR_SUCCESS)
{
endp ^=0x80; // 同步標志翻轉
if(len)
DevOnU2HubPort[len - 1].GpVar[0]=endp; // 保存同步標志位
else
ThisUsb2Dev.GpVar[0]=endp;
len=R8_USB2_RX_LEN; // 接收到的數據長度
if(len)
{
U2SETorOFFNumLock(RxBuffer);
PRINT("keyboard data: ");
for(i=0; i < len; i++)
{
PRINT("x%02X ", (uint16_t)(RxBuffer[i]));
}
PRINT("\n");
need_send=1;
}
}
else if(s !=(USB_PID_NAK | ERR_USB_TRANSFER))
{
PRINT("keyboard error %02x\n", (uint16_t)s); // 可能是斷開了
}
}
else
{
PRINT("keyboard no interrupt endpoint\n");
}
SetUsb2Speed(1); // 默認為全速
}
}
}
/******************************** endfile @ main ******************************/
設置need_send全局變量作為標志位,對于藍牙HID線程修改如下:
if(events & START_REPORT_EVT)
{
if (need_send) {
HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT,
HID_KEYBOARD_IN_RPT_LEN, RxBuffer);
need_send=0;
}
tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 1);
return (events ^ START_REPORT_EVT);
}
將HID線程的周期改為1ms來提高藍牙鍵盤的速度。
實物:
(工程文件可至原帖內下載)
作者:cruelfox 原帖地址:http://www.eeworld.com.cn/aWvjfbD
這個DIY項目的想法已經有很久了,如今終于達到了的設計的初衷。要體現“任性”的特點,先介紹背景吧。
在看這個帖子的諸位一定都在用計算機鍵盤吧。鍵盤上的數字鍵是1到9從左至右排列,或者是右小鍵盤區那樣三個一排有序排列,反正規律很明顯。但是字母鍵卻不是A,B,C...到Z這么按字母序有規律地排下來的。我剛接觸電腦(其實還是學習機)的時候,沒在意這個問題,覺得是要盲打嘛,反正對兩手的手指頭來說,按字母序排列并沒有什么好處。于是用多了這些排列也就記住了,從來不管它為什么要這樣。其實,PC的鍵盤鍵位排布上是延用了打字機的鍵盤,這是設備演變過程中很自然的一個延續。打字機的歷史就要早很多了,我沒有親見過打字機長什么樣,而且,咱們漢字是鉛字打上去的,和英文打字機方式完全不同。
上面這個照片(來自wikipedia),是"Sholes and Glidden Type-Writer.",第一個獲得成功的商用打字機(1873)。請注意它的鍵盤字母鍵排列。
為什么得到這樣一個字母排列?在當時的確經過了多次的優化改進,因為打字機是機械的動作,要盡量避免連續的擊鍵引起沖突。結果是因為商業上的成功,QWERTY這個布局也跟著被越來越多的制造商吸收采用。在非英語語言的鍵盤上,個別鍵位可能不同,屬大同小異了。最早的IBM PC鍵盤:
其實在電傳動打字機問世之后,打字鍵盤的鍵位布局就可以自由了。但是QWERTY的流行沒有被改變——習慣的力量是強大的。雖然是大眾所接受,QWERTY也有被人詬病的地方,比如說左右手分配不平衡,在英語里面單獨用左手能打出來的單詞遠比單獨用右手的多。那么,除了QWERTY還能用啥?在ANSI標準里面還有另外一個鍵盤布局,叫做DVORAK.
Dvorak(德沃夏克)布局,是以其發明人之一: August Dvorak 的姓命名的。在20世紀30年代,Dvorak 和 Dealey 在他們多年的研究工作基礎上發明了Dvorak布局,目標是減少打字出錯幾率、提高速度和減少手的疲勞。最初發明的布局是這個樣子:
Dvorak布局的最明顯特征是讓使用頻率最高的鍵安排在中間的一排(Home row),這樣手指不用移動就觸得到。當然還有左右手均衡的設計等等。盡管不是所有人都同意Dvorak布局能夠比QWERTY布局提高鍵盤輸入的效率,最快打字速度的記錄的確是在Dvorak鍵盤上創造的。
我是經常要寫代碼的人,對鍵盤要求比較高,一定要順手。從1998年擁有電腦開始,第一塊鍵盤用了5年,實在是塑料結構磨損嚴重了才換了。第二塊鍵盤用了大概也有5年,第三塊是淘寶買到的和第二塊同樣的。除了手感,我對鍵盤還有個挑剔是要大回車鍵(老鍵盤慣出來的)。到了用上筆記本電腦,鍵盤問題只能忍忍了。我最后買的一塊Benq的”輕指飛揚"絕版鍵盤因為是USB,作為筆記本鍵盤替補一直保留到現在。
到2012年下半年,我在淘寶發現了有“機械鍵盤”這東東,認識了Cherry MX軸。然后到2013年農歷年后,我花一百多一點買了一塊老舊的國產青軸機械鍵盤,雖然很陳舊狀態也差了,敲了一會兒我就發現:這就是我要的手感啊,一比起來用了多年的薄膜鍵盤簡直太委屈手指了。我后來花了更多的錢買了新的軸(就是機械鍵盤的開關)來更換修復,使之成為上班工作用。
機械鍵盤用著爽,后來我發現手指別扭的地方了,跟QWERTY鍵盤布局有關系。了解了Dvorak布局之后,我下定決心,換用Dvorak. 這個過程很漫長,大約是一年以后才拋開了QWERTY根深蒂固的影響。到如今兩年多,我也沒有肯定我的輸入速度是否達到自己曾經QWERTY時候最快的水平,不過可以肯定的是換了Dvorak,手指頭是舒服了。借個圖說明兩種布局的差別:
從QWERTY換到Dvorak,除了決心以及過程中的痛苦外,還有額外的成本。一是操作系統的支持,雖然DOS, Windows, Linux都支持Dvorak,但需要加載keymap,或者設置鍵盤布局,且每臺機器,每個用的系統都要改。在Windows上,Dvorak和默認的En-US是平級的,但中文輸入法只能用En-US也就是壓根兒沒考慮Dvorak. 于是我將en_us.dll直接替換掉了,但也不是完美的解決,比如Sogou拼音會從更底層調用讀鍵盤,還是沒法用(于是我一直用智能ABC咯)。二是用別人電腦的時候,比如同事要請幫忙,又不能SSH過去,我就只好盯著鍵盤來“一指禪”了;以及電腦安裝系統的時候,應急啟動時候,類似的困難。三是我的電腦夫人也就沒法用,同樣的道理。四是雖然內部變成Dvorak,鍵盤上印的還是QWERTY那樣的,必須盲打,必須雙手干活,不能一只手拿著食物啦。這時候我多希望它還是QWERTY,可以用用一指禪。
綜上,在操作系統軟件層次上修改鍵盤布局來使用Dvorak,問題還是多多。那么我在鍵盤上面改,硬件直接搞定好了。附帶的好處是可以隨時切換鍵盤布局,鍵盤也可以共享給夫人用。國產老機械鍵盤里面主控是8049 MCU,雖然不能對它編程,我換掉它還是可以的。于是就有了這次的“任性"DIY。
先是改造的對象,主角: 這已經是拆解出機械鍵盤中的PCB板+鋼板,并且拆掉了全部的鍵軸之后的樣子。這塊鍵盤買來時的成色相當差,很臟,惟有鍵帽還不錯,但原本的軸已進灰,狀態差。
軸全部拆下來之后才能將鋼板和PCB分離,不然是被卡住的。原來鍵盤里面的灰比照片上還多得多。注意到這塊DIP40的芯片,就是鍵盤的主控。
特寫,80C49
LED部分,使用了一片D觸發器鎖存指示燈狀態。
暴力破壞,將80C49拆掉。
拆掉原來的鍵盤主控,我用什么頂替呢?沒有引腳全兼容的單片機了,而且我要制作USB鍵盤,所以……STM32F072,做塊一樣大小的PCB. 因為主要是使用原有的鍵盤掃描矩陣,有些引腳是不需要連的。
焊好元件后的板子,準備替換80C49。
用剪下的電阻腿作連接吧,對好位把引腳都焊上。STM32F0的SWD接口務必要留出來下載程序的。
這是在軟件開發當中調試的場景。USB線需要飛線,因為原來的鍵盤PCB上就沒有USB。
開始安裝鋼板,主鍵區焊上全新的Cherry MX茶軸(2.5 RMB一顆)。F區暫且空著,因為使用頻率不高,換新軸就顯得浪費了,等下再把部分舊軸清洗一下裝回去。
我設計的MCU PCB要在鍵盤PCB和鋼板之間。除了SWD的引腳,把UART飛線出來供調試的不時之需。
主鍵區鍵帽就位。
編輯鍵區也安裝好,確認這里替換后不會有沖突。調試用的線和針腳以后是要拆掉的。
最后的組裝,USB線,以及切換鍵盤布局的附加按鈕。部分鍵軸還沒有裝,低優先級的。
DIY過程直播完了,下面說硬件的設計。80C49是塊MCU,貌似也就在PS/2鍵盤上面用。搜到其datasheet對引腳的定義:
其實最關心的還是鍵盤矩陣怎么接的,這個我就靠人肉了,在的PCB背面尋著每條掃描行或列線找,記錄在草稿紙上。最終整理出來的結果是這樣的:(最上邊和最右邊鉛筆寫的數字是引腳編號)
掃描矩陣是8x14的,最多可以支持112個按鍵,實際上只有101個鍵,空出了一些。對照上面那個引腳定義,可以把用到的I/O口確定了。除了電源引腳,剩下還有幾個引腳使用到:PS/2的CLK和DATA占用2個,狀態指示LED的電路占用1個,AT/XT開關使用了一個。我用STM32F072C8,有48個引腳剛好是夠的,富余的I/O就飛線引出了。
這是我設計的電路圖:
PCB Layout:
不從80C49引腳上走的信號包括: SWD接口,USB D+/D-,USART TX/RX,額外兩個可用I/O。
軟件上的工作比硬件多得多。因為想改造成USB鍵盤,不得不把USB HID的實現稍微看懂一下。PS/2模式硬件上也是保留的,暫時我還沒去寫軟件。
總結一下,USB HID鍵盤需要使用兩種HID報告:一是從設備到主機的,按鍵狀態的報告,8字節;二是主機到設備的,指示燈狀態的報告,1字節。第一個報告我使用EP1(Endpoint 1, 端點1)來發送,中斷傳輸;第二個報告就使用默認的EP0,控制傳輸。USB的描述符,可以從現有的USB鍵盤上修改而來。(完整代碼和工程文件見原帖)