今天公司要求我进行传感器的开发,而且只给2天时间,反映下自己没做过这方面可能需要时间延长下,不管,就给你两天时间! 干不完就使劲加班...现在企业压榨劳动力太赤裸裸了,没办法,纵使心中万匹草泥马路过也得干活啊!
这里写上一些传感器开发的小知识,希望对以后能用上
加速度传感器,重力传感器是一个东西的两种叫法,他是测量直线运动的加速度值。陀螺仪是角速度传感器,是测量旋转角速度的传感器。
首先找资料,了解安卓传感器主要分为三种
动作传感器:加速传感器,重力传感器,陀螺仪传感器,旋转向量传感器
环境传感器,光线传感器,温度传感器(据说还有大气压传感器)
位置传感器:方向传感器,磁场传感器
其中这些传感器又分为硬件传感器和软件传感器!所谓硬件传感器就是纯粹基于手机硬件获取的数据
而软件传感器并不是真实存在,而是基于硬件传感器基于一系列算法产生的伪传感器,比如方向传感器就是基于距离传感器和磁场传感器经过这两个传感器一系列算法得出!
在安卓开发中,已经提供了传感器的API就是
1 SensorManager类,该类是用来注册,监听,销毁监听器的方法,以及获取传感器数量种类精度等方法
2 Sensor类是提供了传感器的信息比如传感器的类型,版本,制造商等等比如常见的SensorType类型
序号 |
传感器 |
Sensor类中定义的TYPE常量 |
1 |
加速度传感器 |
TYPE_ACCELEROMETER |
2 |
温度传感器 |
TYPE_AMBIENT_TEMPERATURE |
3 |
陀螺仪传感器 |
TYPE_GYROSCOPE |
4 |
光线传感器 |
TYPE_LIGHT |
5 |
磁场传感器 |
TYPE_MAGNETIC_FIELD |
6 |
压力传感器 |
TYPE_PRESSURE |
7 |
临近传感器 |
TYPE_PROXIMITY |
8 |
湿度传感器 |
TYPE_RELATIVE_HUMIDITY |
9 |
方向传感器 |
TYPE_ORIENTATION |
10 |
重力传感器 |
TYPE_GRAVITY |
11 |
线性加速传感器 |
TYPE_LINEAR_ACCELERATION |
12 |
旋转向量传感器 |
TYPE_ROTATION_VECTOR |
3 SensorEventListener接口,主要就是传感器开发的监听回调,传感器的数值发生变化时就会调用这个方法
4 SensorEvent类是回调监听的参数,主要封装了传感器的监听数值(以数组形式存在)
这个就是传感器开发会用到的主要API,话说查了不少资料...
待会后面的一些内容是我这次项目开发用不到的,但是为了考虑以后会遇上,我就一并记录在这里了,这样之后在进行传感器开发,我不用再去查资料了,直接看我这篇帖子就囊括了大部分的资料
然后是我们要确定传感器的开发流程
1创建传感器管理类,
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
2选择项目开发中会遇到的传感器(最好打印出列表看手机支持那些传感器,主要用来看手机支持那些传感器,实际开发不需要这行代码)
List sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);//主要用来看看手机支持哪些传感器,可以不写
3注册你要监听的传感器监听器,实现监听方法
我的项目经过我的测试实际用到的是方向传感器
//方向传感器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_UI);
这里要注意了,要为了用户负责,注册了就要反注册,否则传感器可是耗电大户,我们一般在onResume注册监听,在onPause进行解绑
mSensorManager.unregisterListener(this);
这里介绍下监听器的三个参数
registerListener(参数一,参数二,参数三)
参数一就是监听回调对象,实现这个接口,编译器会自动复写这两个方法,我们下面再介绍这两个方法
参数二你需要监听的传感器类型
参数三 传感器获取数值的模式,你可以理解成传感器监听周围变化块慢,这个参数是一个常量,一般有四种
SENSOR_DELAY_FASTEST 最快,耗电大户
,监听的越快耗电量越大,这种模式一般不建议使用,因为监听周围大量的数据,算法如果不好将会影响游戏逻辑以及UI性能
SENSOR_DELAY_GAME 一般用来开发游戏,用于实行性较高的游戏比如一些赛车游戏,游戏开发建议用这个模式
SENSOR_DELAY_NORMAL 默认的平率,对于一般的益智类游戏使用,比如根据重力来调整小球进洞的小游戏,如果这个模式应用在赛车游戏上,采样率太低会导致跳帧
SENSOR_DELAY_UI 根据传感器更新UI,我们一般根据传感器的值变化用来绘制我们相应的UI,延迟一点反而好不用平凡的绘制UI造成性能浪费
4 开始考虑传感器采集的数据以及算法逻辑了,以上三步全是模板代码,第四步才是传感器开发的核心!
首先要知道不同的传感器返回的采样数据是不同的,如下
4-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。
4-2 磁力传感器
磁力传感器简称为M-sensor,返回x、y、z三轴的环境磁场数据。
该数值的单位是微特斯拉(micro-Tesla),用uT表示。
单位也可以是高斯(Gauss),1Tesla=10000Gauss。
硬件上一般没有独立的磁力传感器,磁力数据由电子罗盘传感器提供(E-compass)。
电子罗盘传感器同时提供下文的方向传感器数据。
4-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来完成工作,电子罗盘算法一般是公司私有产权。
4-4 陀螺仪传感器
陀螺仪传感器叫做Gyro-sensor,返回x、y、z三轴的角加速度数据。
角加速度的单位是radians/second。
根据Nexus S手机实测:
水平逆时针旋转,Z轴为正。
水平逆时针旋转,z轴为负。
向左旋转,y轴为负。
向右旋转,y轴为正。
向上旋转,x轴为负。
向下旋转,x轴为正。
ST的L3G系列的陀螺仪传感器比较流行,iphone4和google的nexus s中使用该种传感器。
4-5 光线感应传感器
光线感应传感器检测实时的光线强度,光强单位是lux,其物理意义是照射到单位面积上的光通量。
光线感应传感器主要用于Android系统的LCD自动亮度功能。
可以根据采样到的光强数值实时调整LCD的亮度。
4-6 压力传感器
压力传感器返回当前的压强,单位是百帕斯卡hectopascal(hPa)。
4-7 温度传感器
温度传感器返回当前的温度。
4-8 接近传感器
接近传感器检测物体与手机的距离,单位是厘米。
一些接近传感器只能返回远和近两个状态,
因此,接近传感器将最大距离返回远状态,小于最大距离返回近状态。
接近传感器可用于接听电话时自动关闭LCD屏幕以节省电量。
一些芯片集成了接近传感器和光线传感器两者功能。
下面三个传感器是Android2新提出的传感器类型,目前还不太清楚有哪些应用程序使用。
4-9 重力传感器
重力传感器简称GV-sensor,输出重力数据。
在地球上,重力数值为9.8,单位是m/s^2。
坐标系统与加速度传感器相同。
当设备复位时,重力传感器的输出与加速度传感器相同。
4-10 线性加速度传感器
线性加速度传感器简称LA-sensor。
线性加速度传感器是加速度传感器减去重力影响获取的数据。
单位是m/s^2,坐标系统与加速度传感器相同。
加速度传感器、重力传感器和线性加速度传感器的计算公式如下:
加速度 = 重力 + 线性加速度
4-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经过算法计算后得出。
算法一般是传感器公司的私有产权。
看到了吧,不同的传感器,返回的数值单位不仅不一样,就连返回值的数量也不同,所以业务逻辑算法差距都是非常大的,既然说到了X,Y,Z的正负值,就不得不说手机的坐标系了
X Y Z分别对应values[0]到[2](监听回调返回的数组)
这里对传感器举下例子
加速度感应检测——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轴运动时是正值
说道XYZ,就不得不说手机的坐标系了,如下图
如图就是手机的坐标系
至此,就介绍完了关于传感器开发的大部分信息,掌握以上信息,基本就可以进行开发了,我要做的就是一个角度仪的开发,用到的是方向传感器,我会带领各位熟悉传感器开发流程
上面我提到了传感器设置监听,复写的方法,核心就是在这复写的方法中,设置传感器器监听复写的两个方法
onSensorChanged(final SensorEvent event)//传感器数据变化的回调(主要)
onAccuracyChanged(Sensor sensor, int accuracy)//传感器精度变化的回调(一般很少用到,可忽略)
说到方向传感器,要说下方向传感器的小知识点了,android获取方向是通过磁场感应器和加速度感应器共同获得的,至于具体的算法SDK已经封装好了。也就是说现在获取用户方向有两种方式,一是官方推荐的,通过SensorManager.getOrientation()来获取,这个方法表面看似容易(那是因为你还没看到他的参数。。一会再说),但实际上需要用到两个感应器共同完成工作,特点是更加的准确。第二种方法非常简单,就像前面介绍的方式,直接得到三个轴上的数据。
两种方式的api会导致角度的取值范围是不同的
values[0] X轴 第一种方式获得方向(磁场+加速度)得到的数据范围是(-180~180),也就是说,0表示正北,90表示正东,180/-180表示正南,-90表示正西。而第二种方式(直接通过方向感应器)数据范围是(0~360)360/0表示正北,90表示正东,180表示正南,270表示正西。
values[1] 表示Y轴的角度:俯仰角 即由静止状态开始,前后翻转
values[2] 表示Z轴的角度:翻转角 即由静止状态开始,左右翻转
这里我把传感器开发的资料,以及我写的应用(Demo版有注释)以及开发的坑和关键点都写在了这里,只要下载我的demo版app很容易就看懂的,所以不会一步一步去描述代码,最后会呈上app的git地址供下载研究!
这里要注意了,因为方向传感器获取的数据最后我要进行算法显示在UI上,但是UI不能频繁的进行绘制,会造成性能浪费体验很差,所以我原本是打算根据下次与上次获取的值相减的绝对值达到某个值,再去改变UI,以此来减少UI的绘制,但是在安卓高级编程中推荐用线程去做这件事
此外,我自定义一个简单的view去实现跟随角度的变化来呈现不同的角度,这里有坑了,Math方法的tan函数额参数是弧度不是角度,,,烦躁...郁闷..好坑!
另外,textview显示角度会随着手机的转动而转动,没有去自定义,我直接使用了动画,大家可以自己去看具体的实现!
两天时间搞完app加上些这篇博客,完美完成!
demo版的app,我在公司开发公司没有UI,没有产品,没有接口文档,什么都没有,需求这种东西嘴巴告诉你,然后剩下的就靠你自己了,所以UI略丑大家不要介意
git地址 https://github.com/Itxupengfei/anglegaugeDemo
我参考的资料如下,有些资料里面部分的介绍是错误的,请注意甄别
参考资料 :http://blog.csdn.net/mad1989/article/details/20848181
http://blog.csdn.net/octobershiner/article/details/6639040
http://blog.csdn.net/octobershiner/article/details/6640451
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1009/424.html
http://blog.csdn.net/smartbetter/article/details/53161452
http://bbs.51cto.com/thread-1127671-1.html
http://www.2cto.com/kf/201111/110233.html
http://blog.sina.com.cn/s/blog_48d4913001010zsu.html
http://www.cnblogs.com/mengdd/archive/2013/05/19/3086781.html
http://www.2cto.com/kf/201412/359292.html
http://www.jb51.net/article/56989.htm