摘要:Android 是麵向智能手機和其他便攜式設備的最受歡迎的操作係統(OS)之一。它為多種傳感器提供了標準的API 接口,包括加速度計。加速度計的標準API 定義了原始加速度數據的坐標係統。用戶必須將從傳感器中讀取的原始數據轉換為標準單位,並使其符合係統定義的坐標方向。本文介紹了Android 中的坐標係統是如何定義的,以及如何在Android 係統的驅動代碼中對3 軸加速度計數據的方向和坐標進行轉換。本文討論的示例代碼基於飛思卡爾的Android 2.2 和2.3 驅動程序,加速度計則以飛思卡爾的MMA8452Q 加速度傳感器為例。
Sensor.TYPE_ACCELEROMETER 所有數值都采用SI 標準單位(m/s2),測量手機的加速度值,並減去重力加速度分量。 values[0]:x 軸上的加速度值減去Gx values[1]:y 軸上的加速度值減去Gy values[2]:z 軸上的加速度值減去Gz 例如,當設備平放在桌上並推著其左側向右移動時,x 軸加速度值為正。當設備平放在桌上時,加速度值為+9.81,這是用設備的加速度值 (0 m/s2) 減去重力加速度值 (-9.81 m/s2)得到的。 當設備平放在桌上放,並以加速度A m/s2 朝天空的方向推動時,加速度值等於A+9.81,這是用設備加速度值(+A m/s2)減去重力加速度值(-9.81 m/s2)得到的。 表 1 列出了與設備的各個位置相對應的傳感器的加速度值讀數。用戶可以用下表檢查加速度計的方向與係統坐標是否一致。 表 1. 不同位置上各軸的加速度值
判斷是否需要改變方向或交換X-Y 軸的方法如下所述: 1. 將設備放置在朝上(UP)的位置,如表1 中所示。 2. 從傳感器中讀取3 軸的數據。如果Y 軸上的數據為 ±1 g (±9.81m/s2),其他兩個軸上的數據大約為0,則不需要交換X-Y 軸。否則,需要交換X 和Y 軸,請轉至步驟3。 2.1. 在該位置上,如果Y 軸上讀取的數據為+1 g (+9.81m/s2),則Y 軸的方向不需要改變,如果數據為負,則Y 軸的方向需要改變。 2.2. 將設備放置在朝左(LEFT)的位置,如表1 中所示。X 軸上讀取的數據應為±1g (±9.81m/s2),其他兩個軸上的數據應大約為0。如果X 軸上的數據為正,則其方向不需要改變;否則X 軸的方向需要改變。然後,執行第4 步判斷Z 軸的方向。 3. 設備仍然放置在朝上(UP)的位置,並從傳感器中讀取3 個軸的數據。此時X 軸上的數據應為 ±1 g (±9.81m/s2),其他兩個軸上的數據大約為0,需要X-Y 交換。 3.1. 在該位置上,如果X 軸的數據讀取為+1 g (+9.81m/s2),則X 軸的方向不需要改變;否則需要改變。 3.2. 將設備放置在向左(LEFT)位置上,如表1 中所示。Y 軸上讀取的數據應為±1g (±9.81m/s2),其他兩個軸上的數據應大約為0。如果Y 軸上的數據為正,則其方向不需要改變;否則需要改變。然後執行第4 步判斷Z 軸的方向。 4. 將設備放置在正麵朝上(FRONT-UP)的位置,並從傳感器中讀取3 軸數據。如果 Z軸上的數據為+1 g (+9.81m/s2),其他兩個軸上的數據大約為0,則Z 軸方向無需改變;如果Z 軸數據為-1 g (-9.81m/s2),則Z 軸方向需要改變。 在 Android 係統中,傳感器數據由內核空間中的Linux 驅動讀取,然後由HAL 層驅動發送至API。分層結構如圖3 所示。因此,傳感器數據可以在Linux 驅動層或在HAL 層上進行轉換。
在 HAL 文件中,會有一組宏定義,用於把從傳感器中讀取的加速度數據轉換為標準單位(m/s2)。如以下代碼: // conversion of acceleration data to SI units (m/s^2) #define CONVERT_A (GRAVITY_EARTH / LSG) #define CONVERT_A_X (-CONVERT_A) #define CONVERT_A_Y (CONVERT_A) #define CONVERT_A_Z (CONVERT_A) 在這個宏定義中,常量GRAVITY_EARTH 是一個標準重力加速度值,即9.81m/s2,LSG為一個重力加速度值的最小有效計數值,例如,MMA8452 在正常模式下的讀數為1024。因此,CONVERT_A 用於把從加速度傳感器中讀取的數據,從數字讀數轉換為標準重力加速度單位。 通過分別修改CONVERT_A_X、CONVERT_A_Y 和CONVERT_A_Z,我們可以輕鬆地改變X、Y 和Z 軸的方向。如果該軸的方向與係統定義相反,可以使用(-CONVERT_A)來改變其方向。如果方向一致,就使用(CONVERT_A),則保持方向不變。 這個宏定義位於FSL Android 9 (Android 2.2)驅動程序的HAL文件sensor.c 中。對於FSLAndroid 10 (Android 2.3),您可以在’libsensors’文件夾的HAL 文件Sensor.h 中找到它。 在 Android 2.2 HAL 文件中交換X 軸和Y 軸 在某些情況下,X 和Y 軸必須進行交換,以便使傳感器數據的坐標與係統坐標保持一致。 對於 FSL Android 9 (Android 2.2)驅動程序來說,X 軸和Y 軸的交換非常簡單。首先,在HAL 文件sensor.c 中,在函數sensor_poll() 中找到以下代碼: switch (event.code) { case ABS_X: sSensors.acceleration.x = event.value * CONVERT_A_X; break; case ABS_Y: sSensors.acceleration.y = event.value * CONVERT_A_Y; break; case ABS_Z: sSensors.acceleration.z = event.value * CONVERT_A_Z; break; } 然後,根據如下所示修改代碼: switch (event.code) { case ABS_X: sSensors.acceleration.y = event.value * CONVERT_A_Y; break; case ABS_Y: sSensors.acceleration.x = event.value * CONVERT_A_X; break; case ABS_Z: sSensors.acceleration.z = event.value * CONVERT_A_Z; break; } 在 Android 2.3 的HAL 文件中交換X 軸和Y 軸 在 Android 2.3 的HAL 文件中交換X 軸和Y 軸會更加複雜些,因為它具有更複雜的HAL文件結構。所有HAL 文件都位於文件夾‘libsensors’中。文件AccelSensor.cpp 中的兩個函數需要修改。 首先,修改函數AccelSensor()的代碼,如下所示: if (accel_is_sensor_enabled(SENSOR_TYPE_ACCELEROMETER)) { mEnabled |= 1 mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) { mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) { mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z; } } 然後,修改函數processEvent()的代碼,如下所示: void AccelSensor::processEvent(int code, int value) { switch (code) { case EVENT_TYPE_ACCEL_X: mPendingMask |= 1 break; case EVENT_TYPE_ACCEL_Y: mPendingMask |= 1 break; case EVENT_TYPE_ACCEL_Z: mPendingMask |= 1 break; } } 完成後,X 軸和Y 軸的數據就互相交換了。 在 Kernel 驅動文件中交換X 軸和Y 軸 X 軸和Y 軸的數據交換可以在底層的Linux 驅動中,在剛開始讀取傳感器數據時實施。通過這種方法,無論傳感器芯片以何種方式安裝在PCB 中,或者使用各種不同類型的傳感器,HAL 文件都可以保持一致。 對於 Android 2.2 和2.3 來說,執行該操作的最便捷的方式是修改函數report_abs()中的代碼。在該函數中,傳感器數據通過調用函數mma8452_read_data()讀取,如下所示(當使用的傳感器為MMA8452Q 時): if (mma8452_read_data(&x,&y,&z) != 0) { //DBG("mma8452 data read failed/n"); return; } X 軸和Y 軸可以通過以下方式輕鬆交換: if (mma8452_read_data(&y,&x,&z) != 0) { //DBG("mma8452 data read failed/n"); return; } 對於 Android 2.2,MMA8452 的Kernel 驅動文件為mma8452.c;對於Android 2.3,驅動文件是‘hwmon’文件夾中的mxc_mma8452.c。 在 Kernel 驅動文件中改變 X、Y 和Z 軸的方向 傳感器數據的方向也可以在Kernel 驅動文件中更改。以下帶有注釋的語句可以添加到函數report_abs()中,從而改變數據方向: if (mma8452_read_data(&y,&x,&z) != 0) { //DBG("mma8452 data read failed/n"); return; } x *= -1; //Reverse X direction y *= -1; //Reverse Y direction z *= -1; //Reverse Z direction input_report_abs(mma8452_idev->input, ABS_X, x); input_report_abs(mma8452_idev->input, ABS_Y, y); input_report_abs(mma8452_idev->input, ABS_Z, z); input_sync(mma8452_idev->input); 總結 Android 係統已經為加速度計定義了坐標係統,因此用戶必須轉換從實際傳感器中讀取的數據,從而與其保持一致。無論是否需要轉換,都應檢查X、Y 和Z 軸的方向以及X-Y軸坐標。我們可以更改HAL 文件或Kernel 驅動文件來改變軸的方向,或交換X 和Y 軸,但是不要同時修改HAL 文件和Kernel 驅動。 參考資料 1. Android Coordinate System http://developer./reference/android/hardware/SensorEvent.html 2. Reference Code and User’s Guide on ‘Android MMA8452.tar.gz’. 3. Reference Code and User’s Guide on ‘mma8452_imx51_android10_v100.tar.gz’. 4. Datasheet ‘MMA8452Q.pdf’.(end)
|
|
来自: dwlinux_gs > 《重力感应专题》