作者:周秉誼 / 臺灣大學計算機及資訊網路中心作業管理組碩士後研究人員
利用Wiimote自製大型的電子白板及觸控螢幕,是新奇又低成本的解決方案。Wiimote上的加速度及光學感測器可以收集使用者的動作資訊,經過程式分析整理後,就能用來操作遊戲和應用程式。目前已經有許多Wiimote的函式庫,程式設計人員可以快速地開發出有趣的應用。
前言
行動裝置 (mobile device) 是目前電子產品最熱門的領域,不但提供了各種通信及娛樂,也是將雲端運算融入生活環境中最重要的一環。為了提供使用者方便且直觀的操作經驗,近來觸控式螢幕 (touchscreen) 已經成為各種行動裝置最流行的使用者操作介面 (user interface)。從任天堂DS到Apple iPhone等智慧型手機,都充分利用了觸控式螢幕帶給使用者新奇的操作經驗。然而,受限於硬體及成本,想要在一般家庭體驗大型的觸控式螢幕,不是那麼容易,因此就有人想到可以利用任天堂公司的Wii搖控器 (Wii Remote, 簡稱Wiimote) 來自製多點觸控及電子白板等應用。
自製電子白板的原理,是以Wiimote上的紅外線感測功能來追蹤紅外線光筆的軌跡,Windows程式可以參考Johnny Chung Lee的網站[1],實際運用在教學上的環境架設在草屯國小林家賢組長的網站[2]有很仔細的介紹。而Wiimote上還有其他許多感測器及使用者互動的元件,都是很好的應用方向。
Wiimote是任天堂公司Wii遊戲機的主要控制器 (搖捍),以內建的各種感應器為Wii平台的遊戲帶來各種新穎的互動及操作方式,如直接揮動Wiimote進行各種球類遊戲等。因此就有人想到可以把Wiimote當成一個新的電腦操作工具,最簡單的例子就是把Wiimote當成簡報時取代滑鼠來控制遊標和換頁。WiiLi.org為了想在Wii上面運行Linux,曾進行很多Wiimote軟硬體控制的研究,現在可以在WiiBrew、Wii-linux及DarwinRemote等專案得到Wiimote的軟硬體介紹及第三方 (third-party) 的應用。
Wiimote感應器
Wiimote上的感應器分為加速度感測器 (accelerometers) 及光學感測器 (optical sensor) 兩種。
加速度感測器用來觀測操作者的動作,使用ADXL330晶片,可以觀測三個軸方向的加速度,感測範圍是±3g (gravity)。當Wiimote處在自由落體的情況下,加速度感測器會回報零加速度,所以當Wiimote靜止不動的時候,會得到與地球引力相反方向的1g加速度。因此可以利用三個軸方向測得的合力方向,得知Wiimote的傾斜情況,就可以知道Wiimote目前的擺放方式。
光學感測器可以利用外部的紅外線光源,定出Wiimote目前指向的位置。紅外線感測器是一個單色的感應器,透過Wiimote外殼上的紅外線濾片,可以接收外部紅外線光源。內建的影像處理器會將接收到的光源追踪 (track) 成四個光點,傳送到主機的資料就只是這些光點的位置。在一般的Wii遊戲環境中,外部紅光線光源是由感應棒 (sensor bar) 提供,感應棒的內部是兩個紅外線LED叢集 (IR LED cluster),Wii遊戲就可以使用接收到的紅外線光點的位置,來判斷Wiimote的指向。在使用Wiimote的紅外線感測器進行其他應用時,可以設計各種不同的紅外線光源,如紅外線光筆等,也可用簡單的電路及紅外線LED自製不同外型的感應棒。
Wiimote上還有幾個按鈕、一塊小記憶空間及一些回饋 (feeback) 功能的元件。記憶體是一塊16k bytes的電子抹除式可複寫唯讀記憶體 (EEPROM),有些遊戲會利用來儲存使用者的資料。回饋功能元件包括LED燈、振動器、及擴音器,程式可以控制這些元件進行不同的動作,如播放聲音、振動等。還可以接上不同的擴充元件,如強化的加速度感測器或Nunchuk。
Wiimote連線方式
Wiimote上各個感應器的數值及回饋元件的控制,都是透過藍芽無線通訊協定的人機介面規範 (Bluetooth Human Interface Device Profile, Bluetooth HID) 來傳輸。Bluetooth HID延用USB HID協定,用來提供鍵盤、滑鼠及搖桿等使用者輸入裝置與作業系統之間溝通的介面。在Linux上可以使用BlueZ這個包含在Linux kernel裡的基本藍芽堆疊 (Bluetooth stack) 和藍芽裝置溝通,BlueZ套件也提供了一些小程式,可以進行藍芽裝置及服務查詢。使用hcitool程式可以掃描周圍的藍芽裝置並顯示裝置的名稱及藍芽位址 (Bluetooth address) 等資訊,在藍芽接收器 (Bluetooth adapter) 和Wiimote連接時,就可以利用hcitool得到Wiimote的藍芽位址,在以其他程式處理Wiimote時就可以使用。使用sdptool程式進行藍芽的服務搜尋協定 (service discovery protocol),可以得到Wiimote的裝置名稱為Nintendo RVL-CNT-01,及Wiimote支援的L2CAP和HID協定等資訊。而Wiimote上各種感應器的資料,就是利用HID介面上定義的各個報告描述元 (report descriptor) 回報給主機,主機也可以透過這個介面控制Wiimote。想要利用Wiimote進行不同的應用,就需要有一個函式庫 (library) 來處理和傳送HID介面上的報告資料流。
CWiid函式庫
CWiid [3]是一個基於GPL授權,運行在使用者空間 (user space) 下的驅動程式 (driver),它提供了一個抽象化的程式介面 (API, application programming interface) 把複雜的藍芽連線的細節隱藏起來。除了API,CWiid也提供了幾個小程式可以閱讀這些程式的原始碼 (source code),來了解CWiid這個函式庫的工作流程及各個函式的使用方式。lswm程式呼叫CWiid內的cwiid_get_bdinfo_array() 函式列出所有可以連線的Wiimote。wmgui是一個以GTK+ (GIMP toolkit) 寫成的視窗程式,它可以把所有Wiimote的資訊顯示出來;如圖二,中間是加速度感測器的資訊,右邊的黑點是光學感測器追蹤到的紅外線光源。wminput是Wiimote的事件驅動程式 (event driver),配合uinput這個linux核心模組處理wminput發出的事件,就可以使用Wiimote取代滑鼠了。
CWiid的使用流程,一開始要先呼叫cwiid_open(bdaddr) 函式,傳入值bdaddr是利用str2ba() 函式處理過的藍芽裝置的位址,而cwiid_open() 函式會回傳一個型態為cwiid_wiimote_t的控制代碼 (handle),這個控制代碼將會在程式中用來存取Wiimote。cwiid_open() 函式會建立藍芽的連線將socket資訊寫在控制代碼中、設定Wiimote的旗標 (flag),並產生兩個POSIX執行緒 (POSIX threads, pthread) 的副程序在背景執行。router_thread() 會不斷監聽藍芽連線傳回來的封包,再用封包內的report ID將不同的封包內容交由不同的函式處理。status_thread() 會不斷將router_thread()取得的Wiimote目前的狀態記錄到cwiid_wiimote_t的資料結構裡,並且設定Wiimote會送出的回報資訊,Wiimote會依這個設定送出不同report ID的封包及資訊。主要的執行緒可以使用cwiid_set_rpt_mode() 函式設定想要接收的感應器、使用cwiid_get_state() 函式取得目前感應器的資訊,或使用cwiid_set_mesg_callback() 函式產生一個背景執行的mesg_callback_thread() 函式執行緒,這個執行緒會利用自行定義的callback function自動回報及處理感應器的資訊。這些執行緒之間需要透過數個pthread_mutex_t進行同步,以免不同執行緒同時存取同一塊記憶體空間,稍微增加了閱讀程式的複雜度。
結語
Wiimote不只改變了遊戲的操作方式,也產生了許多充滿創意的應用。因此有許多人寫了不同的C/Java函式庫提供不同應用使用,連著名的自動控制及模擬軟體LabVIEW,都有Wiimote的驅動函式庫可以使用,或許也能夠作為軌跡追蹤及動作偵測的實驗器材。使用Wiimote進行簡報是最基本的應用,做為電子白板等教學輔助器材也有實際的教學經驗可供參考。未來可能還會有更天馬行空的應用方式,也是很讓人期待的。
參考資料
1. http://johnnylee.net/projects/wii/
2. http://media.ttes.ntct.edu.tw/blog/?p=947
3. http://abstrakraft.org/cwiid/