簡報筆的進化 (一)
去年剛加入 AppWorks 時,我為了解決在大場地辦活動時 2.4GHz 簡報遙控器不靈光的問題,用 433MHz 的 OOK 發射/超外差接收模組做了土砲的簡報遙控器。詳情記錄在簡報筆的故事這兩篇文章中。
雖然我用稍大的 RF 功率解決了射程的問題,但用這種遙控器的固定編碼 IC 加上學習型解碼 IC 做的簡報遙控器,有一個很困擾我們的問題: 它的反應有點慢。
以我上次做簡報筆用的發射編碼器 PT2264 來說,它有一個用電阻控制頻率的 RC 振盪器,做為編碼的時基。它每一個 bit 的時間是震盪器週期的 32 倍,資訊是載在波型的 duty cycle 上。每一個 word 有 12 個 bit 及一個長度為 4 bit 時間的同步記號,一個 frame 有 4 個 words。因此一個 frame 的長度就是 (12+4) * 4 = 64 bits。
我買到的發射器板子上都打了 3.3M ohm 的震盪電阻,震盪器頻率大概是 10KHz,週期是 0.1ms。64 個 bit 的時間就是:
0.1ms * 32 * 64 = 204.8ms
差不多是 0.2 秒。
也就是說,要完整傳送一個鍵的資料並讓接收器正確解碼,至少需要 0.2 秒。
雖然 0.2 秒聽起來不長,但站在臺上簡報的人本來就渡日如年,這個 “必需要按住按鍵達 0.2 秒之久才能換頁” 的特性常常讓他們以為簡報筆壞掉了,或是覺得簡報遙控器好像要按住兩秒才能換下一頁,相當令人困擾。
我有試著更換電組來修改振盪器的頻率,增快它編碼的速度,但大概當速度變成原來的 1.5 倍時,學習型解碼器就取樣不到了,因此這個速度太慢的問題沒辦法用改振盪器頻率的方法簡單解決。
於是我決定捲土重來,這次一定要徹底解決簡報筆的問題。
Packet Radio
要做到低延遲,又要可靠,我第一個想到的就是用 packet radio 的 IC 來做。
Packet radio 是以數位封包的方式在無線通道上傳送資料的技術,依據不同的頻帶、頻寬、調變技術和錯誤率,可以用數 Kbps 到 數 Mbps 不等的速度傳送資料。主流的 Bluetooth、Wi-Fi 等消費型無線通訊技術對通訊協定和應用有完整的定義,但 packet radio 只建立傳送資料的通道,至於要在通道上傳送什麼、做什麼應用,則由設計的人來決定。
由於半導體製程的進步,這些 packet radio 晶片的整合度都很高,從 RF 前端、PLL、ADC 到 modem 應有盡有,有的甚至還有 MAC。而且它們的 modem 常用 FSK 或 GFSK 這種 frequency domain 的調變方法,可靠度遠高於 ASK 或 OOK,有的上面還有 data link layer 幫你算 CRC、檢查資料的正確性,以及 network layer 處理定址的問題。
這裡面最常用的大概就是 Nordic 的 nRF2401L,它是一顆 2.4GHz 的 packet radio IC,用 GFSK 調變,頻道寬度 1MHz,速度最快可以到 1Mbps,整合度超高,只要加上 crystal 跟電源就可以工作 (當然還要天線的 matching network 啦)。nRF2401 很常用在物聯網的最後一段,用以連接裝置與 gateway。但很可惜的是它工作在非常吵雜的 2.4GHz band,我們說好不用 2.4GHz 的。出局。
我沒有堅持一定要用 430MHz 或 315MHz 的 RF 系統,但 GHz 以上的 RF 系統穿透力都相對弱,雖然波長短的系統天線會比較好設計,但在簡報筆這種應用上我還是偏好 sub-GHz 的系統。
Si4432
我想到 Silicon Labs 有一整個系列的 EZRadio 跟 EZRadioPRO 產品,都工作在 sub-GHZ band。我以前用過其中一顆 Si4432 設計無線的資料收集系統,對它還算熟,就決定用它了。
Si4432 也是一顆整合度很高的 packet radio SoC,它裡面有完整的 MAC、modem、頻率範圍超寬廣的 PLL、以及最大 20dBm 輸出的 PA。雖然 20dBm,也就是 100mW 聽起來好像不大,但它的接收感度高達 -121dBm,如果配上 FSK 或 GFSK 這種可靠度高的調變方法,再把 data rate 放慢,傳個幾百公尺一點都不是問題。
這是 Si4432 的 block diagram,是一個很典型的 RF transceiver。收到的訊號經過 LNA 放大後,與 local oscillator 產生的 I/Q 震盪訊號混合後降到中頻並分離 I/Q。分離後的 I/Q 訊號就直接送往 ADC 進入 digital domain 了。
根據 datasheet 上的說法,Si4432 的中頻是 crystal 頻率的 1/32,937.5KHz,在進入接收模式的時候 PLL 的頻率會自動往下偏移一個中頻的頻率,以確保混頻器的輸出含有正確的中頻頻率。
但其實 Si4432 支援的三種調變方法 OOK/FSK/GFSK 都不是 complex modulation,其實不一定要用 I/Q demodulation。在很多 FSK 或 GFSK 的接收晶片上也很常用 frequency detector 來處理。
而發射的部分就完全沒有 I/Q modulator 的影子,不管是 OOK 還是 FSK/GMSK 都可以直接控制 VCO 的輸出有無或頻率偏移來完成。
實戰
為了快速建立一個可以做實驗的系統,我去淘寶上買了 433MHz 的 Si4432 模組。Si4432 支援的頻率非常廣,從 240MHz 到 960MHz,工作在不同頻段時 antenna matching network 的設計需要跟著改變,因此買模組時要指定頻段。
市場上大部分的 RF 模組為了自動組裝方便,都會做成郵票孔的 SMD 模組,但我為了做實驗方便,特別去找了帶排針的模組。這個模組上除了 Si4432 跟 crystal 外,還有完整的 matching network 跟 antenna switch,只要焊上天線加上電源就可以動了。
這是 datasheet 中 Si4432 的參考線路。Si4432 的接收跟發射 port 是分開的,因此需要外加 antenna switch。而且它的接收 port 是 differential 的,因此跟 single-end 的 antenna switch 連接時還需要一個 balun 電路做平衡到不平衡的轉換。圖中的 C4、L4、C5 就是這個 discrete balun。
要怎麼控制它呢 ? Si4432 用 SPI 介面跟 MCU 溝通,除了標準的 4 隻 SPI 接腳外,Si4432 還提供了 interrupt 的輸出,讓 MCU 可以用 ISR 來處理各種通訊時的事件。當然你也可以用 polling SPI 暫存器的方法來做到同樣的事,只是程式會比較難寫。
站在巨人的肩膀上
Si4432 的功能非常強大,但控制起來也很複雜,它裡面足足有 128 個控制用的暫存器,如果要全部從頭自己寫程式來控制,會是非常大的工程。
做事情要懂得站在巨人的肩膀上。幾年前我用 Si4432 設計資料收集系統時,曾經用過一個叫做 RF22 的 library。這個 library 本來是設計給一個叫 RFM22 的 RF module,而 RFM22 上面那顆 RF 晶片剛好跟 Si4432 pin-to-pin、register-to-register 相容,不知道是誰抄誰。
當我再度造訪 RF22 的網站時,發現這個 library 已經停止開發,並且整併到一個叫 RadioHead 的 library 裡了。RadioHead 是一個包山包海的 packet radio library,除了 Si4432 外還支援一大堆其它的 RF 晶片,像 Nordic 的 nRF905、Semtech 的 SX1231 LoRa 晶片、和前面提過的 nRF2401L 等。
這個 library 是為 Arduino 開發的,但由於它並沒有用到什麼 Arduino 特有的功能,而且底層就只靠 SPI 跟 Si4432 溝通,因此可以輕易移植到其它處理器上執行。
不過我還是決定偷懶用 Arduino 做。
Si4432 只支援 3.3V,而我手上大部分的 Arduino 板子,不管是大片的 Uno 或是小片的 Pro Mini、Pro Micro 都是 5V 的版本。為了避免另外加 level shifter 的麻煩,我先用 ESP8266 來做實驗。
我拿了兩片 NodeMCU 跟 Si4432 模組,各接七條線把它們連起來,就可以開始做實驗了。
做通訊系統最麻煩的地方就是所有的東西都要做兩套。不管是做單工的的系統 (一端發射一端接收),或是雙工的系統 (兩端都能發射和接收),都要做兩套。
雖然簡報遙控器理論上用單工的系統就做得到,但為了讓這個系統更可靠,我決定要讓接收器在收到訊號後送一個 acknowledment 出來給發射器,並在發射器上透過某些使用者介面讓簡報的人收到一些回饋。Si4432 本身就是半雙工的發射、接受器,因此可以輕易做到這一點。
RadioHead 的 library 附了不少範例,包括了簡單的 client/server 通訊、可定址的 mesh network,以及更複雜的 routable network 等。但其實做簡報遙控器只需要用到 client/server 的範例,於是我就開了這兩個範例,照著 ESP8266 SPI 介面的規格修改了兩隻 I/O 腳的設定,就可以跑了。
RadioHead 的 library 在不同的處理器上執行時,需要修改兩隻腳的設定:SPI 的 CS 以及 IRQ 腳。
它的物件是這樣宣告的:
RH_RF22 object(CS, IRQ);
RadioHead 預設透過 Arduino 的標準 SPI library 使用 CPU 本身的硬體 SPI 介面,但如果硬體 SPI 有其它用途的話,它也有內建一個 bit-bang 的 SPI module,不過速度會比 native 的 SPI 慢很多。至於 SPI 的 CS 腳,本來就是軟體定義,因此可以指定到任何一隻腳。
比較特殊的是 IRQ 腳,對大部分 ATmega-based 的 Arduino 板子來說,能當 interrupt 輸入的接腳是有限制的,因此在設定 RadioHead 時,IRQ 腳就只能設定給可以接受中斷輸入的接腳。比如說在 Pro Micro 上,就只有 0、1、2、3、7 可以接受中斷輸入,如果把 IRQ 設定給這幾隻以外的接腳,RadioHead 就沒辦法正確動作。不過 ESP8266 的每一隻 I/O 腳都可以接受中斷輸入,因此做實驗時沒有甚麼限制。
總之,沒有什麼意外地,我成功地讓兩片 ESP8266 透過 Si4432 用 2.4Kbps 的速度互傳訊息了。接下來,就可以做板子了。
(未完待續)
Sorry I can not read Chinese.
Hi Bird, 看了你的Blog,覺得很有趣,想不到工作上的一身本領都可以應用在生活上.真是厲害. 想請教你一個問題,如果在工廠內收機台訊號,WIFI選用有4個選擇,433,868,900,920Mhz 頻段. 那一種可以在台灣使用?
臺灣目前真正明文開放的只有 922MHz。
433MHz 雖然汽機車遙控器、鐵捲門遙控器都在用,但其實有點游走法律邊緣。