使用 Mini D1 ESP32 製作 藍牙HID鍵盤

上次使用 Arduino Pro Micro 模擬 鍵盤按鍵操作,但 iOS 無法簡單地透過 USB連接 鍵盤及電腦
需要透過藍牙裝置才能將鍵盤按鍵的效果傳送給 iOS ,因此在下又要測試新零件

Mini D1 ESP32

外觀
見下文
Mini D1 ESP32 正面

見下文
Mini D1 ESP32 使用 ESP-WROOM-32 晶片
是一種具備 WiFi Bluetooth Low Energy (BLE) 的混合型微控制器模組

見下文
CH9102X 是一種 能將電子訊號轉換成 USB訊號 的晶片

見下文
Mini D1 ESP32 背面,印有引腳功能
(由於不需要用盡所有引腳,因此在下只焊接需要使用的引腳)

見下文
Mini D1 ESP32 使用 Micro USB Type-B 插口

見下文
Micro USB Type-B 插口 旁邊有重新啟動按鈕

引腳
Mini D1 ESP32 共有 40支引腳,其中38支引腳是由 ESP32-WROOM-32 轉接的引腳
但經 Mini D1 ESP32 轉接的引腳並非傳統的 雙列直插封裝 (Dual Inline Package (DIP))
無法簡單地安裝到麵包板上(除非不焊接其中一排引腳)
另外由於 Mini D1 ESP32 的引腳文字印刷到底部,但使用時通常是正面向上,因此無法看到文字
因此在下以正面的方式將排列列出,方便查看引腳用途

Micro USB Type-B (正面)
1202140
2192239
3182338
4172437
5162536
6152635
7142734
8132833
9122932
10113031

印刷的引腳名稱比較難明白用途,因此在下使用官方說明文件的用途來命名
編號引腳方向功能
1S6特殊GP6引腳,韌體SPI整合SCK引腳,不能獨立使用
2S8特殊GP8引腳,韌體SPI整合MISO引腳,不能獨立使用
3IO2輸入/輸出GP2數碼引腳,提供接觸訊號,電路板LED
4IO0輸入/輸出GP0數碼引腳,提供接觸訊號
5IO4輸入/輸出GP4數碼引腳,提供接觸訊號
6IO12輸入/輸出GP12數碼引腳,提供接觸訊號
7IO32輸入/輸出GP33數碼引腳,提供接觸訊號
8IO25輸入/輸出GP25數碼引腳
9IO27輸入/輸出GP27數碼引腳,提供接觸訊號
10GND接地
11U1特殊GP1引腳,UART整合TXD引腳,不能獨立使用
12U3特殊GP3引腳,UART整合RXD引腳,不能獨立使用
13IO22輸入/輸出GP22數碼引腳,硬件SPI的WP引腳,硬件I 2 C的SCL引腳
14IO21輸入/輸出GP21數碼引腳,硬件SPI的HOLD引腳,硬件I 2 C的SDA引腳
15IO17輸入/輸出GP17數碼引腳
16IO16輸入/輸出GP16數碼引腳
17GND接地
185V輸出 5V 電壓
19IO15輸入/輸出GP15數碼引腳,提供接觸訊號
20S7特殊GP7引腳,韌體SPI整合MOSI引腳,不能獨立使用
21S10特殊GP10引腳,韌體SPI整合WP引腳,不能獨立使用
22IO13輸入/輸出GP13數碼引腳,提供接觸訊號
233V3輸出 3.3V 電壓
24IO5輸入/輸出GP5數碼引腳,硬件SPI的SS引腳
25IO23輸入/輸出GP23數碼引腳,硬件SPI的MOSI引腳
26IO19輸入/輸出GP18數碼引腳,硬件SPI的MISO引腳
27IO18輸入/輸出GP18數碼引腳,硬件SPI的SCK引腳
28IO26輸入/輸出GP26數碼引腳
29I36輸入GP36引腳,只接受數碼輸入用途
30RST
31GND接地
32NC無效引腳
33I39輸入GP39引腳,只接受數碼輸入用途
34I35輸入GP35引腳,只接受數碼輸入用途
35IO33輸入/輸出GP33數碼引腳,提供接觸訊號
36I34輸入GP34引腳,只接受數碼輸入用途
37IO14輸入/輸出GP14數碼引腳,提供接觸訊號
38NC無效引腳
39S9特殊GP9引腳,韌體SPI整合HOLD引腳,不能獨立使用
40S11特殊GP11引腳,韌體SPI整合SS引腳,不能獨立使用

Arduino IDE

Mini D1 ESP32 可以透過 Arduino IDE 上載 Sketch
但需要先安裝及設定一些資料

見下文
到 Arduino IDE 的 File > Preferences

見下文
Additional Boards Managers URLs 輸入
https://dl.espressif.com/dl/package_esp32_index.json

然後按 OK

見下文
Tools > Board: > Boards Manager...

見下文
在搜尋欄位尋找 esp32
找到由 Espressif Systems 提供的 ESP32

見下文
見下文
Install 並等待下載及安裝

見下文
安裝支援 ESP32 後,到 Tools > Board: > ESP32 Arduino > WEMOS D1 MINI ESP32

見下文
Tools > Upload Speed: > 115200
其實不一定使用 115200 ,只是 115200 是比較見用的鮑率
使用最高速度的 921600 同樣能夠上載 Sketch

見下文
在下編寫一個讓 Mini D1 ESP32 的 LED 閃動的 Sketch
void setup() {
        pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
        delay(500);
}

但編譯 Sketch 出現
exec: "python": executable file not found in $PATH
Error compiling for board WEMOS D1 MINI ESP32.


見下文
在 Terminal 輪入
sudo apt install python-is-python3

或按此下載 python-is-python3

見下文
安裝 python-is-python3 雖然修正 PATH 的錯誤,但出現另一個錯誤
Traceback (most recent call last):
    File "${HOME}/.arduino15/packages/esp32/tools/esptool_py/3.0.0/esptool.py", line 38, in <module>
        import serial
moduleNotFoundError: No module named 'serial'
exit status 1
Error compiling for board WEMOS D1 MINI ESP32.

見下文
既然顯示 esptool 找不到 serial ,因此在下在 Terminal 輪入
pip install esptool

嘗試讓 pip 自動安裝需要使用的 python 套件
但原來在下一直都未安裝 pip

見下文
見下文
因此先在 Terminal 輸入
sudo apt install python3-pip
或按此下載 python3-pip

見下文
安裝 pip 後,再次輸入
pip install esptool

便可以下載及安裝 esptool 及相關套件
(注意:不需要使用 sudo 來執行 pip)

見下文
編譯沒有出現錯誤

見下文
將 Sketch 上載到 Mini D1 ESP32

見下文
電路板上的LED 每500毫秒 閃動

BLE Keyboard

BLE Keyboard 函式庫提供與 Keyboard.h 相似的語法及供能,更加容易編寫模擬藍牙鍵盤的功能
但 BLE Keyboard 沒有在 Arduino 函式庫列表上登記,因此需要自行下載及安裝
見下文
https://github.com/T-vK/ESP32-BLE-Keyboard

見下文
到 Releases 頁面,下載最新版本的 ESP32-BLE-Keyboard.zip
(如果擔心函式庫被移除,請自行保存)

見下文
開啟 Arduino IDE ,到 Include Library > Add .ZIP Library...

見下文
選擇需要匯入的 函式庫zip檔案

見下文
編寫 BLE Keyboard 的 Sketch 並上載到 Mini D1 ESP32
#include <BleKeyboard.h>

BleKeyboard myKeyboard = BleKeyboard("My BLE Keyboard");
// Use any valid pin
const byte SIGNAL_PIN = 26;

void setup() {
        pinMode(SIGNAL_PIN, INPUT);
        pinMode(LED_BUILTIN, OUTPUT);
        digitalWrite(LED_BUILTIN, HIGH);
        myKeyboard.begin();
        digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
        if (myKeyboard.isConnected() && digitalRead(SIGNAL_PIN) == HIGH) {
                myKeyboard.write('1');
        }
}

見下文
當 Mini D1 ESP32 運作時,會發現其藍牙名稱

見下文
點選連接並配對

見下文
見下文
數秒後便可以使用

見下文
見下文
Android 連接時,不需要確認配對

見下文
見下文
見下文
iOS需要 藍牙4.0或以上 及 具備BLE功能 才能辨認及連接

見下文
測試按鍵效果
(閣下應該會發現在下只按一次按鈕,熒幕卻出現多次按鍵效果
是因為在真實環境下,當金屬接觸時,有機會有微少分離並再次接觸的情況,這個情況還會在極短時間內連續發生
這個情況稱為 接觸彈跳(Contact Bouncing)
人不會感覺到這些微少彈跳,但電子裝置卻能夠偵測這些微少彈跳,因此按一次卻出現多次按鍵效果
移除彈跳 (Debouncing) 是非常複雜的操作,因此在下不在此仔細說明
在下使用 下拉電阻 (Pull-Down Resistor) 來處理,但種做法並非最佳方法
如果只是製作測試、實驗性的電子工具,並非精密儀器,這種方法仍然可以解決大部分彈跳的問題

見下文
測試起動、等待配對、已連接效果

在下將之前 Arduino Pro Micro 的程式改為適合 Mini D1 ESP32 使用
在下增加:
  • 起動狀態(Booting)(訊號燈亮著)
  • 等待配對狀態(Waiting for Pairing)(訊號燈每500毫秒閃動)
  • 已配對狀態(Paired)(訊號燈熄滅)
方便辨認 Mini D1 ESP32 的狀態

製作轉接器

由於之前在下曾製作匹配 Arduino Pro Micro 引腳的鍵盤電路板
但不相容 Mini D1 ESP32 的引腳,但重新製作鍵盤電路板,又有點浪費
因此使用萬用電路板,手動方法焊接線路
製作適合 Mini D1 ESP32 至 Arduino Pro Micro 的轉接器

線路原型
見下文
在下使用 Fritzing 並自製 Mini D1 ESP32 元件,方便設計線路

實際線路
見下文
由於實際情況元件能夠向上堆疊,因此可以將萬用電路板剪裁至最小但適合的使用範圍

見下文
見下文
見下文
轉接器的正面

見下文
轉接器的後面

由設計至動手焊接,在下大約使用2小時

見下文
見下文
見下文
見下文
將 Mini D1 ESP32 安裝到 轉接器

見下文
將 轉接器 安裝到 Arduino Pro Micro 鍵盤

見下文
由於在下的朋友使用 iPhone ,因此設計的功能主要是以 iOS 的 VoiceOver 為主要功能:
  • 項目選擇
  • 捲動
  • 轉輪
  • 執行
  • 返回
  • 桌面
  • 切換器
  • 通知中心
  • 控制中心
  • 熒幕開關效果

重新設計

由於之前設計的鍵盤佈局只是為了用盡 Arduino Pro Micro 所有數碼引腳
並沒有考慮按鈕之間空位很少,沒有佈局區分,反而無法達到方便、易用的效果
最後還是要重新設計另一塊電路板,將功能相關的按鈕編排成一個群組,方便記憶及操作

見下文
電路板原型設計圖
綠色線路為正面,紅色線路為背面
按鈕右邊焊墊為列(Row),按鈕左邊焊墊為欄(Column)

見下文
電路板製成器
電路板 正面
其實與之前設計的 8x8按鈕電路板 相同,只是按鈕位置稍微調整及分類
及改用 Mini D1 ESP32 的引腳佈局

見下文
電路板 背面

見下文
在下的名稱 及 Open Hardware 圖案

見下文
安裝 Mini D1 ESP32 (及 8粒 100KΩ 電阻) 的位置

見下文
焊接 64粒 按鈕 及 8粒 120KΩ電阻 及 連接Mini D1 ESP32 的引腳座
(恰巧在下沒有 100KΩ電阻 改用 120KΩ電阻 亦可行)

見下文
焊接 6mm按壓按鈕

見下文
焊接 電阻 及 引腳座
使用 引腳座 可以方便安裝及卸除 Mini D1 ESP32 ,但會比較佔用空間
直接將 Mini D1 ESP32 比較不佔用空間,亦比較美觀,但如果 Mini D1 ESP32 損壞,則很難替換
在下考慮維修或替換問題,因此使用 引腳座 方便事後處理

見下文
焊接後的背面,拿住使用時,非常刺手

見下文
將 Mini D1 ESP32 安裝到新設計的鍵盤電路板

見下文
安裝到鍵盤電路板的 Mini D1 ESP32 的正面

見下文
見下文
安裝到鍵盤電路板的 Mini D1 ESP32 的側面

見下文
安裝到鍵盤電路板的 Mini D1 ESP32 的 Micro USB Type-B 插口方向

欄列按鈕配對
雖然新設計的鍵盤電路板印上按鈕符號,但焊接後會覆蓋符號,因此製作圖表方便記憶按鈕對應程式碼

ABCDEFGH
1BackDktpAppSMuteCrtnNotfCtrlStts
2C⇤C↥C⇥Say1SayCSayS
3C↤C↧C↦123
4S⇤S↧S⇥456
5S↤S↧S↦789
6UndoRedoSA*0#
7CutCopyPasteDelRCallDelL
8DictSpCpScCp!SpTpRun

對應功能
符號鍵盤 1 手勢功能
BackESC2指畫Z返回上一層目錄
DktpVO + h按Home 或 1指由熒幕底部滑動至熒幕下半部回到桌面
AppSVO + h + h按2次Home 或 1指由熒幕底部滑動至熒幕上半部開啟應用程式切換器
MuteVO + s3指點擊2次開啟或關閉靜音
CrtnVO + F113指點擊3次開啟或關閉熒幕
NotfVO + PageUp在狀態列 3指向下滑動前往通知中心
CtrlVO + PageDown在狀態列 3指向上滑動前往控制中心
SttsVO + m前往狀態列
C⇤Cmd + 左箭咀游標移到最前
C↥上箭咀游標向上移動
C⇥Cmd + 右箭咀游標移到最後
Say1VO + b2指向上滑動由第一項目朗讀到最後
SayCVO + a2指向下滑動由當前項目朗讀到最後
SaySControl2指點擊1次停止朗讀
VO + Cmd + 上箭咀1指向上滑動轉輪項目數值增加
VO + Cmd + 下箭咀1指向下滑動轉輪項目數值減少
C↤左箭咀遊標向左移動
C↧下箭咀遊標向下移動
C↦右箭咀遊標向右移動
1數字1數字鍵盤1
2數字2數字鍵盤2
3數字3數字鍵盤3
VO + Cmd + 左箭咀1指在熒幕左邊向下滑動 另1指在熒幕右邊向上滑動轉輪向左移動
VO + Cmd + 右箭咀1指在熒幕左邊向上滑動 另1指在熒幕右邊向下滑動轉輪向右移動
S↤Cmd + Shift + 左箭咀選取文字至最前
S↧Shift + 上箭咀向上選取文字
S↦Cmd + Shift + 右箭咀選取文字至最後
4數字4數字鍵盤4
5數字5數字鍵盤5
6數字6數字鍵盤6
Option + 上箭咀3指向上滑動向上捲動
Option + 下箭咀3指向下滑動向下捲動
S↤Shift + 左箭咀向左取選文字
S↧Shift + 下箭咀向下取選文字
S↦Shift + 右箭咀向右取選文字
7數字7數字鍵盤7
8數字8數字鍵盤8
9數字9數字鍵盤9
Option + 左箭咀3指向左滑動向左捲動
Option + 右箭咀3指向右滑動向右捲動
UndoCmd + z回復上一步
RedoCmd + Shift + z重做下一步
SACmd + a選取所有文字
*星號數字鍵盤星號
0數字0數字鍵盤0
#井號數字鍵盤井號
Control + 上箭咀3指在熒幕上半部點擊1次選取最前項目
Control + 下箭咀3指在熒幕下半部點擊1次選取最後項目
CutCmd + x將選取的文字複製到剪貼簿,並刪除選取文字
CopyCmd + c將選取的文字複製到剪貼簿
PasteCmd + v將剪貼簿在遊標位置貼上
DelRShift + Delete刪除遊標右側文字
CallReturn電話撥號
DelLDelete刪除遊標左側文字
左箭咀1指向左滑動選取上一個項目
右箭咀1指向右滑動選取下一個項目
Dict文字編輯時2指點擊2次使用聽寫
SpCpVO + Shift + c3指點擊4次將朗讀的文字複製到剪貼簿
ScCpCmd + Shift + 3音量減 + Home 或 音量加 + 開關鍵擷取熒幕截圖
!Control + space切換輸入法
上箭咀1指向上滑動選擇已選取項目的上一個功能
下箭咀1指向下滑動選擇已選取項目的下一個功能
SpTpVO + -2指點擊2次使用精妙點擊
RunVO + space2指點擊1次執行已選取項目
1. 鍵盤 以 Mac鍵盤 為基礎
Mac鍵盤 的 Control 預設為 一般鍵盤 的 Ctrl
Mac鍵盤 的 Option 預設為 一般鍵盤 的 Alt
Mac鍵盤 的 Command 預設為 一般鍵盤 的 Win
VO 為 VoiceOver修飾鍵 預設為 Control + Option

見下文
測試:
  • 數字鍵盤
  • 刪除文字
  • 撥號效果
(在下電話因為只作測試用途,沒有安裝電話卡,因此沒有正式通話)

見下文
測試:
  • 複製朗讀文字
  • 遊標移動
  • 文字選取
  • 文字處理
  • 輸入法切換
  • 熒幕擷取

補充資料

見下文
除了 iOS 的 VoiceOver ,在下還測試 Android 的 TalkBack
TalkBack 都能夠支援類似的無障礙操,但功能比較少
而且主要是 Android 原生鍵盤功能或效果,而 TalkBack 的功能則比較少
不同牌子、型號的 Android 支援鍵盤操作的程度各有不同

由於 Apple 將大量手勢申請專利 (WO2011088134),導致其他公司在未經授權下不能使用特定手勢
因此 TalkBack 有部分手勢無法使用,亦沒有加入鍵盤功能
亦有部分原因是不同的 Android ,沒有整合手勢,導致無法使用鍵盤操作
例如某些 Android 的電話功能能夠使用數字鍵盤輸入,某些不能
某些 Android 可以使用 Page Up 或 Page Down 捲動頁面,某些不能
由於太多不同公司的 Android ,在下都無法全部測試

總結

要讓 iPhone 能使用文字輸入以外的鍵盤操作,需要啟動 全面鍵盤操控 (Full Keyboard Access) 功能
或啟動 VoiceOver 並配合 VoiceOver 專用的快捷鍵
由於一些特別原因,認識到一些有心人捐贈或以非常便宜的二手價轉讓電腦、電話、電子工具給在下
因此在下不同型號的 iPhone 可以測試這個專案

見下文
在下發現,當 主要語言 使用中文(或非英文?)時, VO + 字母 的 VoiceOver 操作有時會無法使用
要到 設定 > 一般 > 語言與地區 > 偏好的語言順序 英文 設定為主要語言,便能正常操作,不過 VoiceOver 便會朗讀英語
(切換語言時會中斷熒幕錄影,因此在下直接拍攝電話畫面)

而 Android 由於原生設計已經可以使用鍵盤操作,只需要透過 USB OTG (USB On-The-Go) 連接便可以使用
並非只能使用 藍牙HID鍵盤

製作這個鍵盤的主要原因是因為在下的朋友有視力障礙問題
由於現在的智能電話主要都是觸控熒幕,視力障礙人士容易有錯誤操作情況
但一般藍牙鍵盤的佈局都是傳統佈局,而且要記下大量組合鍵並不容易
因此設計這個鍵盤給朋友使用
而在下只是簡單說明按鈕佈局,朋友只需要5分鐘便熟習操作,至今亦有使用

在下將組合鍵操作設計成單鍵操作,可以方便使用者不需要記下大量組合鍵,甚至可以單手操作
如果懂得自改修改程式碼,可以將按鍵修改成自己需要的按鍵操作或組合鍵,如同 Macro Keyboard 一般使用

在下將資料分享到 https://bitbucket.org/hkgoldenmra/wemos-mini-d1-keyboard ,包括:
  • 相容 WeMos Mini D1 的 Arduino 的 ino 原始碼
  • SVG 及 PNG 電路原型設計預覽圖
  • Fritzing 電路原型設計圖
  • Gerber 印刷電路檔案
有興趣亦可以自行下載使用及修改

參考資料