android重力感應開發

一、手機中常用的傳感器

在Android2.3 gingerbread系統中,google提供了11種傳感器供應用層使用,具體如下:(Sensor類)

#define SENSOR_TYPE_ACCELEROMETER 1 //加速度
#define SENSOR_TYPE_MAGNETIC_FIELD 2 //磁力
#define SENSOR_TYPE_ORIENTATION 3 //方向
#define SENSOR_TYPE_GYROSCOPE 4 //陀螺儀
#define SENSOR_TYPE_LIGHT 5 //光線感應
#define SENSOR_TYPE_PRESSURE 6 //壓力
#define SENSOR_TYPE_TEMPERATURE 7 //溫度
#define SENSOR_TYPE_PROXIMITY 8 //接近
#define SENSOR_TYPE_GRAVITY 9 //重力
#define SENSOR_TYPE_LINEAR_ACCELERATION 10//線性加速度
#define SENSOR_TYPE_ROTATION_VECTOR 11//旋轉矢量


1-1加速度傳感器

加速度傳感器又叫G-sensor,返回x、y、z三軸的加速度數值。
該數值包含地心引力的影響,單位是m/s^2。
將手機平放在桌面上,x軸默認爲0,y軸默認0,z軸默認9.81。
將手機朝下放在桌面上,z軸爲-9.81。
將手機向左傾斜,x軸爲正值。
將手機向右傾斜,x軸爲負值。
將手機向上傾斜,y軸爲負值。
將手機向下傾斜,y軸爲正值。
加速度傳感器可能是最爲成熟的一種mems產品,市場上的加速度傳感器種類很多。
手機中常用的加速度傳感器有BOSCH(博世)的BMA系列,AMK的897X系列,ST的LIS3X系列等。
這些傳感器一般提供±2G至±16G的加速度測量範圍,採用I2C或SPI接口和MCU相連,數據精度小於16bit。


Android開發之重力傳感器





1-2 磁力傳感器

磁力傳感器簡稱爲M-sensor,返回x、y、z三軸的環境磁場數據。
該數值的單位是微特斯拉(micro-Tesla),用uT表示。
單位也可以是高斯(Gauss),1Tesla=10000Gauss。
硬件上一般沒有獨立的磁力傳感器,磁力數據由電子羅盤傳感器提供(E-compass)。
電子羅盤傳感器同時提供下文的方向傳感器數據。

1-3 方向傳感器

方向傳感器簡稱爲O-sensor,返回三軸的角度數據,方向數據的單位是角度。
爲了得到精確的角度數據,E-compass需要獲取G-sensor的數據,
經過計算生產O-sensor數據,否則只能獲取水平方向的角度。
方向傳感器提供三個數據,分別爲azimuth、pitch和roll。
azimuth:方位,返回水平時磁北極和Y軸的夾角,範圍爲0°至360°。
0°=北,90°=東,180°=南,270°=西。
pitch:x軸和水平面的夾角,範圍爲-180°至180°。
當z軸向y軸轉動時,角度爲正值。
roll:y軸和水平面的夾角,由於歷史原因,範圍爲-90°至90°。
當x軸向z軸移動時,角度爲正值。
電子羅盤在獲取正確的數據前需要進行校準,通常可用8字校準法。
8字校準法要求用戶使用需要校準的設備在空中做8字晃動,
原則上儘量多的讓設備法線方向指向空間的所有8個象限。
手機中使用的電子羅盤芯片有AKM公司的897X系列,ST公司的LSM系列以及雅馬哈公司等等。
由於需要讀取G-sensor數據並計算出M-sensor和O-sensor數據,
因此廠商一般會提供一個後臺daemon來完成工作,電子羅盤算法一般是公司私有產權。

1-4 陀螺儀傳感器

陀螺儀傳感器叫做Gyro-sensor,返回x、y、z三軸的角加速度數據。
角加速度的單位是radians/second。
根據Nexus S手機實測:
水平逆時針旋轉,Z軸爲正。
水平逆時針旋轉,z軸爲負。
向左旋轉,y軸爲負。
向右旋轉,y軸爲正。
向上旋轉,x軸爲負。
向下旋轉,x軸爲正。
ST的L3G系列的陀螺儀傳感器比較流行,iphone4和google的nexus s中使用該種傳感器。

1-5 光線感應傳感器

光線感應傳感器檢測實時的光線強度,光強單位是lux,其物理意義是照射到單位面積上的光通量。
光線感應傳感器主要用於Android系統的LCD自動亮度功能。
可以根據採樣到的光強數值實時調整LCD的亮度。

1-6 壓力傳感器

壓力傳感器返回當前的壓強,單位是百帕斯卡hectopascal(hPa)。

1-7 溫度傳感器

溫度傳感器返回當前的溫度。

1-8 接近傳感器

接近傳感器檢測物體與手機的距離,單位是釐米。
一些接近傳感器只能返回遠和近兩個狀態,
因此,接近傳感器將最大距離返回遠狀態,小於最大距離返回近狀態。
接近傳感器可用於接聽電話時自動關閉LCD屏幕以節省電量。
一些芯片集成了接近傳感器和光線傳感器兩者功能。
下面三個傳感器是Android2新提出的傳感器類型,目前還不太清楚有哪些應用程序使用。

1-9 重力傳感器

重力傳感器簡稱GV-sensor,輸出重力數據。
在地球上,重力數值爲9.8,單位是m/s^2。
座標系統與加速度傳感器相同。
當設備復位時,重力傳感器的輸出與加速度傳感器相同。

1-10 線性加速度傳感器

線性加速度傳感器簡稱LA-sensor。
線性加速度傳感器是加速度傳感器減去重力影響獲取的數據。
單位是m/s^2,座標系統與加速度傳感器相同。
加速度傳感器、重力傳感器和線性加速度傳感器的計算公式如下:
加速度 = 重力 + 線性加速度

1-11 旋轉矢量傳感器

旋轉矢量傳感器簡稱RV-sensor。
旋轉矢量代表設備的方向,是一個將座標軸和角度混合計算得到的數據。
RV-sensor輸出三個數據:
x*sin(theta/2)
y*sin(theta/2)
z*sin(theta/2)
sin(theta/2)是RV的數量級。
RV的方向與軸旋轉的方向相同。
RV的三個數值,與cos(theta/2)組成一個四元組。
RV的數據沒有單位,使用的座標系與加速度相同。
舉例:
sensors_event_t.data[0] = x*sin(theta/2)
sensors_event_t.data[1] = y*sin(theta/2)
sensors_event_t.data[2] = z*sin(theta/2)
sensors_event_t.data[3] = cos(theta/2)
GV、LA和RV的數值沒有物理傳感器可以直接給出,
需要G-sensor、O-sensor和Gyro-sensor經過算法計算後得出。
算法一般是傳感器公司的私有產權。





二、Android感應檢測管理---SensorManager

1、取得SensorManager


使用感應檢測Sensor首要先獲取感應設備的檢測信號,你可以調用Context.getSysteService(SENSER_SERVICE)方法來取得感應檢測的服務

2、實現取得感應檢測Sensor狀態的監聽功能


實現以下兩個SensorEventListener方法來監聽,並取得感應檢測Sensor狀態:

//在感應檢測到Sensor的精密度有變化時被調用到。   
public void onAccuracyChanged(Senso sensor,int accuracy);  
//在感應檢測到Sensor的值有變化時會被調用到。   
public void onSensorChanged(SensorEvent event);  




3、實現取得感應檢測Sensor目標各類的值

實現下列getSensorList()方法來取得感應檢測Sensor的值;
        List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_TEMPERATURE);  


4、註冊SensorListener

sm.regesterListener(SensorEventListener listener, Sensor sensor, int rate);  

        第一個參數:監聽Sensor事件,第二個參數是Sensor目標種類的值,第三個參數是延遲時間的精度密度。延遲時間的精密度參數如下:

參數

延遲時間

SensorManager.SENSOR_DELAY_FASTEST

0ms

SensorManager.SENSOR_DELAY_GAME

20ms

SensorManager.SENSOR_DELAY_UI

60ms

SensorManager.SENSOR_DELAY_NORMAL

200ms



因爲感應檢測Sensor的服務是否頻繁和快慢都與電池參量的消耗有關,同時也會影響處理的效率,所以兼顧到消耗電池和處理效率的平衡,設置感應檢測Sensor的延遲時間是一門重要的學問,需要根據應用系統的需求來做適當的設置。
感應檢測Sensor的硬件檢測組件受不同的廠商提供。你可以採用Sensor的getVendor(),Sensor()的getName()和Sensor的getVeesrion()方法來取得 廠商的名稱、產品和版本。

5、取消註冊

sm.unregisterListener(SensorEventListener listener)  


6、感應檢測

加速度感應檢測——Accelerometer

Accelerometer Sensor測量的是所有施加在設備上的力所產生的加速度的負值(包括重力加速度)。加速度所使用的單位是m/sec^2,數值是加速度的負值。

SensorEvent.values[0]:加速度在X軸的負值
SensorEvent.values[1]:加速度在Y軸的負值
SensorEvent.values[2]:加速度在Z軸的負值

例如:

當手機Z軸朝上平放在桌面上,並且從左到右推動手機,此時X軸上的加速度是正數。

當手機Z軸朝上靜止放在桌面上,此時Z軸的加速度是+9.81m/sec^2。

當手機從空中自由落體,此時加速度是0

當手機向上以Am/sec^2的加速度向空中拋出,此時加速度是A+9.81m/sec^2

重力加速度感應檢測——Gravity

重力加速度,其單位是m/sec^2,其座標系與Accelerometer使用的一致。當手機靜止時,gravity的值和Accelerometer的值是一致的。

線性加速度感應檢測——Linear-Acceleration

Accelerometer、Gravity和Linear-Acceleration三者的關係如下公式:

accelerometer = gravity + linear-acceleration

地磁場感應檢測——Magnetic-field

地磁場的單位是micro-Tesla(uT),檢測的是X、Y、Z軸上的絕對地磁場。

陀螺儀感應檢測——Gyroscope

陀螺儀的單位是弧度/秒,測量的是物體分別圍繞X,Y,Z軸旋轉的角速度。它的座標系與加速度傳感器的座標系相同。逆時針方向旋轉的角度正的。也就是說,如果設備逆時針旋轉,觀察者向X,Y,Z軸的正方向看去,就報告設備是正轉的。請注意,這是標準的正旋轉的數學定義。

光線感應檢測——Light

values[0]:表示環境光照的水平,單位是SI lux。

位置逼近感應檢測——Proximity

values[0]:逼近的距離,單位是釐米(cm)。有一些傳感器只能支持近和遠兩種狀態,這種情況下,傳感器必須報告它在遠狀態下的maximum_range值和在近狀態下的小值。

旋轉矢量感應檢測——Rotation Vector

旋轉向量是用來表示設備的方向,它是由角度和軸組成,就是設備圍繞x,y,z軸之一旋轉θ角度。旋轉向量的三個要素是,這樣旋轉向量的大小等於sin(θ/2),旋轉向量的方向等於旋轉軸的方向。

values[0]: x*sin(θ/2) 
values[1]: y*sin(θ/2) 
values[2]: z*sin(θ/2) 
values[3]: cos(θ/2) (optional: only if value.length = 4)

方向感應檢測——Orientation

其單位是角度

values[0]: Azimuth(方位),地磁北方向與y軸的角度,圍繞z軸旋轉(0到359)。0=North, 90=East, 180=South, 270=West 
values[1]: Pitch(俯仰),圍繞X軸旋轉(-180 to 180), 當Z軸向Y軸運動時是正值
values[2]: Roll(滾),圍繞Y軸旋轉(-90 to 90),當X軸向Z軸運動時是正值 


實例:

/*
*當手機正面朝上的時候,z的值爲q,反面朝上的時候,z的值爲-g
當手機右側面朝上的時候,x的值爲g,右側面朝上的時候,x的值爲-g
當手機上側面朝上的時候,y的值爲g,右側面朝上的時候,y的值爲-g
*
*/

public class MainActivity extends ActionBarActivity {
    /**
     * 創建一個傳感器管理器和一個傳感器監聽器,管理器用來管理傳感器以及創建各種各樣的傳感器,
     * 監聽器用來監視傳感器的變化並且進行相應的操作
     **/
    private SensorManager mSensorManager;
    private Sensor mSensor;

    TextView textView;

    float x,y;

    private static final String TAG = MainActivity.class.getSimpleName();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);

        //獲得重力感應硬件控制器
        mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        if (null == mSensorManager) {
            Log.d(TAG, "deveice not support SensorManager");
        }

        //添加重力感應監聽,並實現其方法
        SensorEventListener sensorEventListener = new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {

                if (event.sensor == null) {
                    return;
                }

                if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                x = event.values[SensorManager.DATA_X];
                y = event.values[SensorManager.DATA_Y];
<span style="white-space:pre">		</span>//z = .....
                textView.setText("x="+(int)x+"y="+(int)y);
                }
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {

            }
        };

        //註冊Listener,SENSOR_DELAY_GAME爲檢測的精確度,
        mSensorManager.registerListener(sensorEventListener, mSensor,SensorManager.SENSOR_DELAY_GAME);

    }
}

轉載自:http://blog.csdn.net/mad1989/article/details/20848181


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章