2014年7月7日 星期一

使用樹莓派取得 eZ430-Chronos 運動手錶三軸加速度數值與按鈕狀態


這一篇文章主要是 "eZ430 運動手錶控制樹莓派小車 ( 開迴路控制 )" 網頁關於 eZ430-Chronos-915 ( eZ430) 運動手錶的通訊建立說明。
eZ430-Chronos Watch with Raspberry Pi

在下面的網頁中,我們將會說明如何使用樹莓派 ( Raspberry Pi ) 抓取 eZ430 運動手錶的資料,包括:三軸加速度和手錶上的按鈕 ( 左上、左下和右上 );以及如何安裝 eZ430 Chronos Control Center (eZ430 控制中心) 在樹莓派上。
eZ430 Chronos Control Center 在樹莓派的顯示畫面
eZ430 Chronos Control Center 在樹莓派的顯示畫面
eZ430 運動手錶的盒子裡,有一個 ( CC1111 ) USB RF Access Point (簡稱 USB RF AP ),用它來做為手錶與作業系統的橋接器,Linux 作業系統已內建其驅動程式,故不需再額外安裝,只要在使用時知道它在系統的裝置名稱就可以了。

eZ430 控制中心是一個 GUI 程式,可以使用這個介面做很多事,像是可在 windows 控制 Power Point 簡報的撥放、圖表化 eZ430 運動手錶上的三軸加速度資訊、控制滑鼠、無線更新、時間同步、以及心律模擬器等,幾乎現有 eZ430 運動手錶裡的功能都可以直接使用 GUI 做呈現,所以在撰寫程式或是有任何問題時,其實都可以透過這 GUI 來做為驗證或是對照。所以這軟體必須安裝在樹莓派上。

但在開始之前,請準備下面幾樣東西,大部分都是軟體。


準備:
  • eZ430-Chronos 運動手錶 ( 購買資料 )
  • TI 的網站裡面有三種型號 ( 433, 866, 915 ) 可以購買,但哪一種都沒關係,都可以使用在這。

  • Raspberry Pi 主機
  • 網頁中的主機使用 Model B ( 512MB) 的主機,其他型號應該也同樣適用!

  • eZ430 Chronos Control Center software for Linux ( TI 通用下載連結 )
  • 軟體一樣可以在上面提供的購買資料連結上找到,網頁撰寫時最新版本:Rev. C, 15 Oct 2013。

    下載的軟體無法直接在樹莓派中做安裝,因此下載之後先儲存到 Linux 作業系統中。

  • Linux 作業系統 ( 建議使用 Ubuntu )
  • Linux 作業系統是要用來處理 eZ430-Chronos 控制中心軟體的,這裡是直接使用 Ubuntu 來完成這動作的,其他的 Linux 發行版本應該也可以


下載與安裝 eZ430 Chronos Control Center:

eZ430 Chronos Control Center 的 Linux 版本安裝程式,因為要考慮到 X86 的架構,所以是 Binary ( 二進制 ) 的檔案格式,不能直接在樹莓派中安裝,因此必須重新封裝才能使用。

封裝的動作很簡單,就是先將檔案在 Ubuntu 安裝,再將安裝目錄整個封裝成一個檔案,傳送至樹莓派後再解封裝,安裝幾個支援 TI script 檔的軟體,就可以直接使用目錄中的檔案了。

在這一個部分,操作方式盡量以圖面表示,相關指令會列在圖片上面,跟著做就好了!


首先,開啟 Linux 作業系統 ( 假設使用 Ubuntu ) 的瀏覽器,並輸入以下網址下載安裝檔

http://www.ti.com/lit/zip/slac388
eZ430-Chronos 軟體安裝過程 - 1

選擇下載並開啟壓縮檔管理員,按下 "OK" 開始下載
eZ430-Chronos 軟體安裝過程 - 2

完成下載之後會開啟壓縮檔管理員,點擊上方的 "解開" 按鈕,將檔案直接解壓縮到家目錄下,完成解壓縮之後按下 "關閉(C)" 按鈕並點擊左上角的 "X" 關閉壓縮檔管理員
eZ430-Chronos 軟體安裝過程 - 3
eZ430-Chronos 軟體安裝過程 - 4
eZ430-Chronos 軟體安裝過程 - 5

在終端機中可以看到下載的檔案為 Chronos-Setup,這是一個二進制安裝執行檔
eZ430-Chronos 軟體安裝過程 - 6

為了得到 eZ430 控制中心的安裝目錄,要先將他在 Ubuntu 系統做安裝。直接輸入下面指令安裝

$ ./Chronos-Setup
eZ430-Chronos 軟體安裝過程 - 7

安裝的過程就像在 Windows 下安裝軟體一樣。一直按 "Next" 就可以完成安裝
eZ430-Chronos 軟體安裝過程 - 8
eZ430-Chronos 軟體安裝過程 - 9
eZ430-Chronos 軟體安裝過程 - 10

完成安裝之後,就會在家目錄下產生一個 Texas Instruments 的目錄,這就是接下來要封裝給樹莓派用的目錄。繼續輸入下面指令對 Texas Instruments 目錄作封裝

$ tar zcvf eZ430-Chronos-RasPi.tar.gz Texas\ Instruments/
eZ430-Chronos 軟體安裝過程 - 11

將安裝之後的檔案 ( 也就是 eZ430-Chronos-RasPi.tar.gz ) 傳到樹莓派的家目錄中 ( 假設使用 pi 登入,/home/pi/ ),但在繼續下面指令之前,請先確認您的樹莓派的 SSH 功能已開啟並知道 IP 位址 ( 假設樹莓派 IP 位址是 192.168.11.12 ),最後輸入下面指令將封裝檔傳送過去

$ scp eZ430-Chronos-RasPi.tar.gz pi@192.168.11.12:/home/pi/
eZ430-Chronos 軟體安裝過程 - 12

Note: 請先插上 USB RF AP 再將樹莓派開機,以下至這一節結束可以直接在樹莓派做也可以使用 MobaXterm 來做,都可以開啟 eZ430 控制中心。

開啟 SSH 軟體連線到樹莓派 ( 或直接在樹莓派中操作都可以 ),確認一下檔案傳輸的結果
eZ430-Chronos 軟體安裝過程 - 13

我們要直接在 /home/pi/ 下解開封裝的檔案,完成之後就會在產生一個相同的 Texas Instruments 目錄

$ tar zxvf eZ430-Chronos-RasPi.tar.gz
eZ430-Chronos 軟體安裝過程 - 14
eZ430-Chronos 軟體安裝過程 - 15

完成上面步驟,就把 eZ430 控制中心的軟體裝好了。但要執行 TI 的 GUI 軟體,樹莓派必須額外安裝執行 TCL Script 檔所需要的軟體 (  其他系統也一樣 )。在開啟的終端機視窗中輸入下面指令
pi@raspberrypi ~ $ sduo apt-get update && sudo apt-get tcl8.5 tk8.5 xdotool

如果之後要使用 Python 寫程式,那上面的指令就要改成
pi@raspberrypi ~ $ sduo apt-get update && sudo apt-get python-serial tcl8.5 tk8.5 xdotool


執行 eZ430 控制中心軟體:

eZ430 控制中心在樹莓派開啟的畫面在網頁最上頭的那一張畫面就是,而現在我們要直接在遠端連線的終端機下開啟它。輸入下面指令,並將 eZ430 運動手錶先設定在 ACC 模式下 ( 按手錶左下按鈕作選擇 )

$ cd Texas\ Instruments/eZ430-Chronos/Control\ Center/Chronos\ Control\ Center/
$ ./eZ430-Chronos\ CC\ 1_2.tcl
使用 SSH 連線至樹莓派開啟 eZ430 控制中心

eZ430 控制中心的視窗出現之後,先按下左上方的 "Start Access Point" 按鈕,開始等待與手錶作連線,這時再按下手錶的右下按鈕,雙方就會開始通訊。若此時手錶開始上下左右亂動,畫面上的 X、Y 和 Z 的直線就會開始根據手錶的動作做擺動,你 ( 妳 ) 現在可以試試!

eZ430 控制中心上有好幾個頁面,每個頁面都有著不同的功能可以與手錶互動!試試從 SimpliciTi Sync 頁面去設定手錶的日期與時間,會比用手慢慢調整快上很多。其他功能就自己再試試吧!


撰寫連線程式與測試:

要由樹莓派取得 eZ430 運動手錶的三軸加速度與按鈕資料,由上面的操作之後就可以知道是經由 USB RF AP 作為中介。而 USB RF AP 一但接上樹莓派主機之後,是否可被系統偵測到唯一有效的 USB 裝置,可輸入 lsusb 指令看輸出 ( 如最下面一行,有被偵測到 )
pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 2047:0340 Texas Instruments

接著看系統核心是否正確的辨識以及使否已載入正確的 module ( cdc_adm, 黃色文字 );最重要的是裝置的名稱叫什麼 ? 由下面文字來看,可以知道應該是 /dev/ttyAMA0 ( 綠色字 )
pi@raspberrypi ~ $ dmesg | tail -20
[    3.514710] usb 1-1.2: SerialNumber: F2BF934607002300
[    3.970021] udevd[156]: starting version 175
[    4.853761] bcm2708_i2c_init_pinmode(0,0)
[    5.005499] bcm2708_i2c_init_pinmode(0,1)
[    5.012758] bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at 0x20205000 (irq 79) (baudrate 100k)
[    5.320814] bcm2708_i2c_init_pinmode(1,2)
[    5.421478] bcm2708_i2c_init_pinmode(1,3)
[    5.516687] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79) (baudrate 100k)
[    5.540112] cdc_acm 1-1.2:1.0: This device cannot do calls on its own. It is not a modem.
[    5.763537] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device
[    5.991529] usbcore: registered new interface driver cdc_acm
[    6.217772] bcm2708-i2s bcm2708-i2s.0: Failed to create debugfs directory
[    6.245499] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[   10.687618] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
[   11.133319] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
[   11.954177] i2c /dev entries driver
[   16.922450] FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
[   19.909123] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
[   21.473810] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0x4DE1
[   26.777505] Adding 102396k swap on /var/swap.  Priority:-1 extents:1 across:102396k SSFS


因為上面的軟體可以正常執行,所以上面說的是廢話 !!! 當然被辨識出 ! 但是重點一定要知道 USB RF AP 在系統的裝置名稱 ( /dev/ttyAMA0 ),測試的時候會用到 !

** 通訊格式說明:

USB AF AP 插上系統之後就可將其視為一個 UART 裝置,因此可以使用 serial 通訊方式與其連結。一旦雙方建立起連結之後,eZ430 運動手錶若啟動在 ACC 通訊模式,就會開始等待遠方送來需求碼,待接收到需求碼後,就會將三軸加速度資料以及按鈕狀態以固定的格式 ( 七個位元 ) 送出,然後一直處在等待需求碼的狀態直到雙方取消連結。

完整的通訊流程請參照下面的流程圖。

eZ430 運動手錶的通訊流程
eZ430 運動手錶的通訊流程

** 測試原始碼:

測試之前請先下載測試程式碼,或是點擊所提供的連結下載。
pi@raspberrypi ~/Codes $ wget -O - goo.gl/P9Vvgp | tar zxvf -
.... << 過程省略 >> ....
pi@raspberrypi ~/Codes $ cd eZ430-getaccel/
pi@raspberrypi ~/Codes/eZ430-getaccel $ ls -l
總計 16
-rwxr-xr-x 1 pi pi 8157  2月 25 18:52 eZ430_getaccel
-rw-r--r-- 1 pi pi 4738  2月 25 15:16 eZ430_getaccel.c
pi@raspberrypi ~/Codes/tmp/eZ430-getaccel $

測試程式碼下載 ( http://goo.gl/P9Vvgp )

下載之後會有兩個檔案其中一個是已編譯完成的執行檔;另一個是原始檔,若有做修改要做編譯的話,請輸入下面指令重新譯議成執行檔


$ sudo gcc eZ430_getaccel.c -l wiringPi -o eZ430_getaccel


下載檔案中的執行檔權限有事先修改可直接執行,但之後若有重新編譯就必須在前面加 sudo 才能執行,如下所示
pi@raspberrypi ~/Codes/tmp/eZ430-getaccel $ ./eZ430_getaccel /dev/ttyACM0
Waiting for accelerometer
[0]=255[1]=  6[2]=  7[3]=  1[4]=195[5]=200[6]= 62

程式執行時會將回傳的 7 個字元轉換成數字格式輸出到螢幕上,其中 [3] 所輸出的是手錶按按鈕按下時相對應的數字輸出; [4]、[5] 和 [6] 相對於 X、Y 和 X 軸的加速度值。只要手錶有任何變化或是動作時都會即時反應到螢幕上。若要結束就按下 "Ctrl + C"。

這程式所得到的加速度數值的範圍列在流程圖的左下那一堆文字上面,不同的轉動所得到的數值範圍會介在 0 - 60 或是 255 - 190 之間,其他的數值看不到;這些數值沒有經過運算,是直接由手錶傳送出來的原生資料,就算是 eZ430 控制中心也是接收到這些資料!

眼尖的你 ( 妳 ) 或許會發現上一段最後一句話好像有語病,eZ430 控制中心裡面看到的資料數據與程式所呈現出來的數值不一樣怎麼會是接收到一樣的資料呢 ? 解釋一下就會清楚了:

eZ430 運動手錶所傳送過來的加速度原生資料為無符號字元 ( unsigned char ),這是程式在執行時所得到的數據,不過沒經過任何處理。而且不難發現,在手錶有動作時,數據就會發生變化,反應的速度很快!但相對於 eZ430 控制中心上的數據變化,就比較平順一點。詳細比較一下應該可以感覺出來吧!

但兩者數據還是不同呀!

應該這樣說,加速度原生資料是屬於高頻訊號容易產生雜訊,如果不經過一些處理,雜訊就會對系統產生干擾,為了讓這些干擾的影響降低,就必須將這些高頻雜訊消除掉。一般所使用的方法就是加入軟體低通濾波器 ( Low-Pass Filter ),簡單!而且對系統負荷很小,對於小型微處理器很好用。

另外就是常用在 MPU6050 結合加速度計與陀螺儀的 "互補濾波器 ( Complementary-Filter ) "。同樣都是加入了低通濾波器,但 "互補濾波器" 不只如此,主要是用來結合兩種訊號 ( 加速度計與陀螺儀 ) 的濾波器 ( 這有時間在寫 MPU6050 的資料時再講好了 ),現在將重點放在下面的圖形。

下圖中有三條線:綠色線先不要管它,因為它是 X 軸陀螺儀的數據;紅色曲線是 X 軸加速度原生資料,不難看出曲線上有很多峰值,而且有些值會在短暫時間內上下突然變化 ( 就像車子馬上加速又減速一樣,坐起來很不舒服 ),若直接將這些數據用在控制馬達轉動上,可料想到會出現什麼情形!因此必須將這些突然的數據變化影響減至最小,也就是濾波。將高頻訊號濾掉,而濾掉這些高頻訊號之後所得到的曲線就是綠色那條線。可看到綠色線是一條平順的曲線,而這種曲線的數據才是能夠直接給微處理器用的資料,用這些資料才容易做分析與判斷接下來要輸出的動作,不會讓突然出現的雜訊 ( 大增或大減的訊號 ) 造成錯誤的判斷!
MPU6050 濾波與為濾波訊號之差異

回到正題!

eZ430 運動手錶會根據擺動的方式輸出不同的加速度數值,這些數值是屬於無符號字元 ( unsigned char, 0 - 255 ),但因為加速度是個向量 ( 有大小、有方向 ),所以取得的這些無符號字元必須先使用 "二的補數 ( 2's complement )" 轉換成有符號字元 ( signed char, -128 - 127 ) ( 對於在控制小車馬達轉動時,可方便得知要前進還是要後退 ),然後再使用低通濾波器做處理,最後得到的加速度值就會跟 eZ430 控制中心所得到的一樣。

如果要詳細知道這些處理的過程,打開 eZ430-Chronos CC 1_2.tcl 這個 Script 檔案 ( line: 859 - 895),就會發現剛剛說二的補數與低通濾波器的程式碼,直接將這些程式碼做移植,就能將加速度數值轉換成 eZ430 控制中心相同的範圍。
pi@raspberrypi ~ $ cd Texas\ Instruments/eZ430-Chronos/Control\ Center/Chronos\ Control\ Center/
pi@raspberrypi ~/Texas Instruments/eZ430-Chronos/Control Center/Chronos Control Center $ ls -l
總計 124
-rwxr-xr-x 1 pi pi 86866 10月 14 15:17 eZ430-Chronos CC 1_2.tcl
-rwxr-xr-x 1 pi pi   233  3月 25  2010 eZ430-Chronos-CC.ini
-rwxr-xr-x 1 pi pi  8208  3月 15  2010 eZ430-Chronos_driver.tcl
-rwxr-xr-x 1 pi pi   252  3月 22  2010 iTunes Control.ini
-rwxr-xr-x 1 pi pi   229  3月 22  2010 Media Player Control.ini
-rwxr-xr-x 1 pi pi  8620  2月 19  2010 ram_based_updater.txt
pi@raspberrypi ~/Texas Instruments/eZ430-Chronos/Control Center/Chronos Control Center $

若還是不夠的話,就去找 eZ430 運動手錶的韌體程式,看如何將加速度數值轉換到 ± 1g;另外,也可以計算一下手錶轉動的角度 pitch-yaw-roll ( 用在控制 eZ430 小車的前進、後退與轉向控制上 ),有興趣的再深入去研究!


** 程式碼說明:

Note:程式碼與流程圖是一致的,建議一起使用

eZ430-getaccel.c 程式碼有兩個主要的部份:一個是程式一開始與 eZ430 手錶雙方連線確認,確認連線之後為另一個索取加速度資料的部分。這兩個部分都是無窮迴圈,直到 ( 前者 ) 條件成立跳出或是由使用者中斷 ( 後者 )。

程式一開始 ( main ),就是開啟與 USB RF AP 通訊的串列埠,而串列埠的名稱,剛剛在前頭已經知道是 /dev/ttyACM0,直接把它當作是程式執行的參數就行了。開啟串列埠之後,設定串列埠的傳輸速度與參數之後就可以開始傳送跟接收了!
if(argc != 2) {
    printf("usage: %s [serial port - usually /dev/ttyACM0]\n",argv[0]);
    return 0;
  }

  f = open(argv[1],O_RDWR);
  if(f == -1) {
    printf("Unable to open '%s'\n",argv[1]);
    return 0;
  }

  if(tcgetattr(f, &cf) == -1) {
    printf("Unable to get termios details\n");
    return 0;
  }

  if(cfsetispeed(&cf, B115200) == -1 || cfsetospeed(&cf, B115200) == -1) {
    printf("Unable to set speed\n");
    return 0;
  }

  /* Make it a raw stream and turn off software flow control */
  cfmakeraw(&cf);
  cf.c_iflag &= ~(IXON | IXOFF | IXANY);

  if(tcsetattr(f, TCSANOW, &cf) == -1) {
    printf("Unable to set termios details\n");
    return 0;
  }

串列埠可以使用之後,就進入第一個無窮迴圈:與 eZ430 運動手錶連線。串列埠會一直送出 0xFF, 0x07, 0x03 這三個字元,直到接收到 eZ430 運動手錶回傳 0xFF, 0x06, 0x03 才會跳出這個無窮迴圈,而這也表示已建立兩者之間的連線。
// hello_str 宣告在程式前頭
// static unsigned char hello_str[3] = { 0xFF, 0x07, 0x03 };
//-----------------------------------------------------------
for(;;)
  {
    unsigned char hello_response[3];
    int i;

    usleep(250000);

    if(write(f,hello_str,sizeof(hello_str)) != sizeof(hello_str)) {
      printf("Unable to say hello\n");
      return 0;
    }

    i = read(f,hello_response,sizeof(hello_response));
    if(i < 0) {
      printf("Unable to read response\n");
      return 0;
    }

    if(i != sizeof(hello_response))
      continue;

    if(hello_response[0] == 0xFF && hello_response[1] == 0x6 && hello_response[2] == 0x3)
      break;
  }

建立連線之後,進入第二個無窮迴圈,開始請求資料回傳給樹莓派 (資料的取得,呼叫 read_accel 副程式 )。
( 到現在為止,都還是在 main 中 )
  for(;;)
  {
    ACC = read_accel(f);
    //printf("ACC, x = %d, y = %d, z = %d\n");

    fflush(stdout);
    usleep(100000);
  }

下面是第二個迴圈一直呼叫的副程式的程式碼。程式會一直依序傳送 req_data 陣列裡的 7 個字元給 eZ430 運動手錶,並確認它的回傳碼 ( 前三個字元:0xFF, 0x06, 0x07 ) 是否正確,再決定是否繼續提出剩下的字元將其顯示在螢幕上。
static unsigned char req_data[7] = {0xFF, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00};

typedef struct accdata {
    int x;
    int y;
    int z;
} ACCDATA;


static ACCDATA read_accel(int fd)
{
    char buffer[7];
    int i;
    ACCDATA acc;
    
    for(;;)
    {
        if(write(fd, req_data, sizeof(req_data)) != sizeof(req_data))
        {
            printf("Send request data to eZ430 error !\n");
            break;
        }
        
        if(read(fd, buffer, sizeof(buffer)) == -1)
        {
            printf("Reveice data from eZ430 error !\n");
            break;
        }
        
        if( buffer[0] == (char)0xff && buffer[1] == 0x06 && buffer[2] == 0x07 )
        {
            
            ///* 測試用,不用時將前面 // 取消掉
            for(i = 0;i < 7;i++)
            {
                printf("[%d]=%3d", i, buffer[i]);
            }
            printf("\r");
            //*/
            return acc;
        }
    }
}


總結:

終於,又將這部分寫完了!

賣場沒出售 eZ430 運動手錶,寫這網頁主要是為了 "eZ430 運動手錶控制樹莓派小車 ( 開迴路控制 )" 這篇,把這個當作前導再直接應用到小車的控制上,就不會塞太多東西在同一篇網頁裡,也能快速上架一些篇幅,彌補之前好長一段時間很少更新賣場部落格。

如果對加速度計、陀螺儀有興趣的話,延伸閱讀這一篇:

Accelerometer & Gyro Tutorial (這一篇有中文版翻譯,上網找一下就有)


希望這篇網頁,可以對同時擁有樹莓派與 eZ430 運動手錶的人有所助益!

能夠看到這邊的客倌,感謝您的支持,支持這篇落落長的文章!


<< eZ430-Chronos-Watch 部落格系列文章 >>

沒有留言:

張貼留言

留言屬名為"Unknown"或"不明"的用戶,大多這樣的留言都會直接被刪除掉,不會得到任何回覆!

發問問題,請描述清楚你(妳)的問題,別人回答前不會想去 "猜" 問題是什麼?

不知道怎麼發問,請看 [公告] 部落格提問須知 - 如何問問題 !