標籤:
一、手機中常用的感應器
在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。
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軸運動時是正值
三、舉例之-Gsensor1,圖示三軸方向
Android重力感應系統的座標系以螢幕的左下方為原點(【注意】2d編程的時候,是以螢幕左上方為原點的),箭頭指向的方向為正。從-10到10,以浮點數為等級單位,想象一下以下情形:
手機螢幕向上(z軸朝天)水平放置的時侯,(x,y,z)的值分別為(0,0,10);
手機螢幕向下(z軸朝地)水平放置的時侯,(x,y,z)的值分別為(0,0,-10);
手機螢幕向左側放(x軸朝天)的時候,(x,y,z)的值分別為(10,0,0);
手機豎直(y軸朝天)向上的時候,(x,y,z)的值分別為(0,10,0);
其他的如此類推,規律就是:朝天的就是正數,朝地的就是負數。利用x,y,z三個值求三角函數,就可以精確檢測手機的運動狀態了。
2,通過監測Gsensor判斷手機處於靜止/移動狀態
public class MainActivity extends Activity implements SensorEventListener { private static final String TAG = MainActivity.class.getSimpleName(); private SensorManager mSensorManager; private Sensor mSensor; private TextView textviewX; private TextView textviewY; private TextView textviewZ; private TextView textviewF; private int mX, mY, mZ; private long lasttimestamp = 0; Calendar mCalendar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textviewX = (TextView) findViewById(R.id.textView1); textviewY = (TextView) findViewById(R.id.textView3); textviewZ = (TextView) findViewById(R.id.textView4); textviewF = (TextView) findViewById(R.id.textView2); mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);// TYPE_GRAVITY if (null == mSensorManager) { Log.d(TAG, "deveice not support SensorManager"); } // 參數三,檢測的精準度 mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);// SENSOR_DELAY_GAME } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor == null) { return; } if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { int x = (int) event.values[0]; int y = (int) event.values[1]; int z = (int) event.values[2]; mCalendar = Calendar.getInstance(); long stamp = mCalendar.getTimeInMillis() / 1000l;// 1393844912 textviewX.setText(String.valueOf(x)); textviewY.setText(String.valueOf(y)); textviewZ.setText(String.valueOf(z)); int second = mCalendar.get(Calendar.SECOND);// 53 int px = Math.abs(mX - x); int py = Math.abs(mY - y); int pz = Math.abs(mZ - z); Log.d(TAG, "pX:" + px + " pY:" + py + " pZ:" + pz + " stamp:" + stamp + " second:" + second); int maxvalue = getMaxValue(px, py, pz); if (maxvalue > 2 && (stamp - lasttimestamp) > 30) { lasttimestamp = stamp; Log.d(TAG, " sensor isMoveorchanged...."); textviewF.setText("檢測手機在移動.."); } mX = x; mY = y; mZ = z; } } /** * 擷取一個最大值 * * @param px * @param py * @param pz * @return */ public int getMaxValue(int px, int py, int pz) { int max = 0; if (px > py && px > pz) { max = px; } else if (py > px && py > pz) { max = py; } else if (pz > px && pz > py) { max = pz; } return max; }}
原理就是通過每次得到的x,y,z三軸的值,和下一次的值作比較,它們每個差值中絕對值最大的如果超過某一個閥值(自己定義),並且這種狀態持續了x秒,我們就視為手機處於(顛簸)移動狀態,當然這種判斷肯定是不科學的,有時候也會產生誤判,比較理想的情境就是:攜帶手機坐在公交上或是開車。
其它可供參考資料:
http://blog.csdn.net/zhandoushi1982/article/details/8591878
http://blog.csdn.net/ZhengZhiRen/article/details/5930451
http://blog.csdn.net/a345017062/article/details/6459643
android 三軸加速度感應器【轉】