此為系列文,目前已完成的文章列表:
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (0)
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (1) 製作左手
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (2) 設定 BLE
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (3) Debounce
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (4) 定義 keyboardMgr class
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (5) 製作右手
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (6) 基礎鍵盤
- 從 0 開始,手打一把專屬的藍牙雙模人體工學鍵盤 (7) 軌跡球
今天的部分主要也都會在程式的修改上,份量會比較少,因為下一篇將會帶大家一口氣把右手的鍵盤部分都做完。在右手的 keyboard matrix 加入混戰之前,我們要先把現在的程式做一次清理,讓他變得比較有系統。
面對這樣的問題,我的切入點是: 我要把鍵盤看做一個 object,Arduino 的 main 程式中,僅會去初始化這個 object,然後在每一次的 loop 中都去呼叫這個 keyboard object 一次,命令他做一輪工作,也就是說 Arduino 的 main 程式的 pseucode 最後只會長得像這樣:
keyboardMgr: 管理鍵盤的 objectvoid setup() {
keyboardMgr.begin(); // 初始化該管理鍵盤的物件
}void loop () {
keyboardMgr.exec(); // 執行掃描 keyboard matrix,跟左手溝通...
}
這樣整個 Arduino 的 main 程式意圖就會變得非常明確,而未來發生 bug 的時候,如果是邏輯上面的 bug,我們可以很容易照著每個部分去做 debug。
其實上面的那個半 pseucode 就已經非常接近於最終的程式長相,大家可以先偷看 4_define_keyboard_manager/define_keyboard_manager 裡面的 .ino 主程式,你會發現真的就跟上面的 pseudocode 幾乎是一模一樣。
那麼在 keyboardMgr 到底在現階段要負責什麼事情呢? 他要負責的是定時去 polling 看看接收左手的 buffer 有沒有東西,有的話就做處理。那接下來的這個處理其實就包含了更高階層的鍵位判斷,有沒有要 toggle layer 等等。
有了這樣的概念以後,我們就可以來撰寫 KeyboardMgr 的內部,大家也可以邊看文章邊和最終完成的 KeyboardMgr.h 和 KeyboardMgr.cpp 對照著看。首先在程式剛宣告一個 KeyboardMgr 的時候,我們就有一些事情可以做了:
- 宣告 SoftwareSerial
- 初始並給予每個按鍵按下後代表的按鍵
這些東西是寫在 KeyboardMgr 的 constructor 裡面的,我曾經犯蠢過,把一些程式要在 Arduino 主程式中的 void begin 裡面的東西寫到 constructor 裡面去,然後 Arduino 就死掉了 XD。救回來的方法也是靠重燒 bootloader 進去。
接下來 keyboardMgr 在 void begin() 裡面還要再做一次初始化,也就是 keyboardMgr.begin()。這時我們要處理的事情則是一些要等 Arduino 過電開始跑之後才能初始化的事情,例如 SoftwareSerial 的 begin,Keyboard 的 begin 等等。在我們把 MCP23018 接上去以後,I2C 的初始化也要在 Arduino 過電開始後才能進行,我們會再下一篇文章中解釋 MCP23018 跟簡單介紹 I2C。 P.S. 我就是犯蠢把 I2C 的初始化寫在 constructor 裡面,然後每次燒進去 Arduino 就掛了 Orz。
最後要處理的部分就是 keyboardMgr.exec 的部分。目前 keyboardMgr.exec 裡面要做的事情就是前一篇文章最後右手範例中的 loop 在做的事情,只不過我們稍微做了一點修改,這是為了要配合之後把右手及 trackball 加入的事件,所以我們加入了 read_from_left 的 member function,把讀取左邊這件事情再抽出來,讓程式更加好懂。
至此我們就把右手程式的鋼骨蓋好了,之後我們就可以在 KeyboardMgr 裡面加入讀取右邊的 keyboard matrix 和 軌跡球的事件,最後也可以在裡面設定要把key event 送給 usb 還是送給 bluetooth HID 模組。