移动设备中的加速度计是一种MEMS传感器,用于测量三个轴上的线性加速度,以确定设备的方向和运动。根据Google Android Sensors Guide (2025),加速度计是移动应用中使用最多的传感器。MEMS技术可以将传感器放置在1毫米大小的芯片中,功耗低于1毫瓦。
要点
加速度计是一种微机电(MEMS)传感器,测量加速度在三个相互垂直轴上的投影:X(水平,向右)、Y(垂直,向上)和Z(垂直于屏幕平面)。在静止状态下,加速度计在Z轴上显示9.8 m/s²的值 — 这是指向地球中心的重力加速度。系统根据这个值确定设备的方向:如果Z轴值接近0,Y轴值接近-9.8 m/s²,则设备水平旋转。加速度计的测量范围通常为±2g、±4g、±8g或±16g,具体取决于芯片型号。
现代加速度计具有几个关键参数:灵敏度(从0.001 m/s²开始)、采样频率(高达1000 Hz)、测量范围和噪声水平。旗舰设备通常安装STMicroelectronics LSM6DSO或Bosch BMI270传感器,频率高达1600 Hz,主动模式下功耗低于0.5 mW。采样频率越高,应用收到的信号越详细 — 游戏需要200-400 Hz,计步则10-50 Hz就足够了。传感器噪声影响测量精度,通常在操作系统层面通过低通滤波器进行补偿。
MEMS加速度计内部是一个微小的硅结构:一个可移动的质量块(proof mass)悬挂在固定电极之间的弹性梁(cantilevers)上。在加速度作用下,质量块发生位移,改变可动与固定元件之间的电容 — 这种变化被测量并转换为电信号。闭环反馈电路(closed-loop)通过静电力将质量块保持在中心位置,确保整个测量范围内的线性度。在开环系统(open-loop)中,质量块自由移动,计算更简单,但精度较低。根据STMicroelectronics(2025)的数据,闭环加速度计的精度可达0.001g,温度漂移低于0.1 mg/°C。
三个轴对应于空间的三个维度:X(左右倾斜)、Y(上下)和Z(相对于屏幕的前后)。当设备平放在桌子上且屏幕朝上时,重力加速度矢量沿Z轴向下,值为9.8 m/s²。当设备倾斜时,重力的投影在轴之间重新分布 — 根据这些投影可以计算倾斜角度,精度高达0.1度。为了在不受重力影响的情况下确定运动,使用高通滤波器(high-pass filter)将加速度的动态分量(设备自身运动)与静态分量(重力)分离开来。
在Android上,通过SensorManager类和SensorEventListener接口访问加速度计。应用获取系统服务SENSOR_SERVICE,请求TYPE_ACCELEROMETER传感器,并注册监听器指定更新频率。系统每次新测量时调用onSensorChanged,传入一个值数组:values[0] = X, values[1] = Y, values[2] = Z。下面是一个用Kotlin读取加速度计数据的完整示例。
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
val sensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
// 计算倾斜角度
val pitch = Math.atan2(
x.toDouble(),
Math.sqrt(y.toDouble() * y + z.toDouble() * z)
)
// 用新角度更新界面
textViewAngle.text = "倾斜角:${Math.toDegrees(pitch)}°"
}
override fun onAccuracyChanged(
sensor: Sensor, accuracy: Int
) { }
}
sensorManager.registerListener(
sensorEventListener,
accelerometer,
SensorManager.SENSOR_DELAY_GAME
)
在示例中,SensorManager.SENSOR_DELAY_GAME设置约50 Hz的更新频率,适用于游戏和交互式应用。计步时使用SENSOR_DELAY_NORMAL(约5 Hz),精确测量使用SENSOR_DELAY_FASTEST(约200 Hz)。在onSensorChanged中,event.values数组包含传感器的当前读数。基于X、Y、Z值使用atan2计算倾斜角度(pitch) — 这是在不使用方向传感器的情况下确定设备方向的基本公式。别忘了在onPause中注销监听器以节省电量。
private val alpha = 0.8f
private val gravity = FloatArray(3)
private val linearAcceleration = FloatArray(3)
override fun onSensorChanged(event: SensorEvent) {
// 低通滤波器(LPF)用于分离重力
gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]
gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]
gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]
// 减去重力 — 得到线性加速度
linearAcceleration[0] = event.values[0] - gravity[0]
linearAcceleration[1] = event.values[1] - gravity[1]
linearAcceleration[2] = event.values[2] - gravity[2]
}
带有alpha系数的低通滤波器分离重力分量(静态矢量),减去它即可得到设备的纯加速度(线性加速度)。这对于在不考虑方向的情况下确定运动是必要的 — 例如检测步数、摇晃或撞击。Alpha值为0.8意味着滤波器允许约20%的新信号通过并保留80%的先前信号 — 足以平滑噪声而不会造成明显延迟。
在iOS上,通过Core Motion框架中的CMMotionManager类提供对加速度计的访问。应用创建管理器实例,并调用startAccelerometerUpdates指定队列和处理程序。数据以CMAccelerometerData的形式返回,包含CMAcceleration结构,带有x、y和z字段。下面是一个用Swift获取加速度计数据并过滤噪声的示例。
import CoreMotion
let motionManager = CMMotionManager()
motionManager.accelerometerUpdateInterval = 1.0 / 60.0
guard motionManager.isAccelerometerAvailable else { return }
motionManager.startAccelerometerUpdates(to: OperationQueue.current!) {
data, error in
guard let acceleration = data?.acceleration,
error == nil else { return }
// g值(1 g = 9.8 m/s²)
let magnitude = sqrt(
acceleration.x * acceleration.x +
acceleration.y * acceleration.y +
acceleration.z * acceleration.z
)
// 如果magnitude > 2.5 g — 检测到摇晃
if magnitude > 2.5 {
DispatchQueue.main.async {
self.handleShake()
}
}
}
在示例中,accelerometerUpdateInterval设置为1/60秒(约60 Hz) — 适用于流畅动画和游戏。isAccelerometerAvailable方法检查设备上是否存在传感器。加速度值以g为单位返回(1 g = 9.8 m/s²)。矢量magnitude计算为三个分量的欧几里得范数 — 如果值超过2.5 g,则被解释为设备摇晃(shake)。要停止更新,请在离开屏幕时调用stopAccelerometerUpdates。
加速度计广泛应用于各类移动应用。最明显的场景是自动旋转屏幕:系统根据加速度计数据在竖屏和横屏方向之间切换。在游戏中,加速度计用作控制手柄 — 倾斜设备可以转动方向盘或移动角色。健身应用根据行走时特征性的加速度峰值来计步。下表列出了典型场景及传感器要求。
| 场景 | 频率(Hz) | 精度 | 过滤 |
|---|---|---|---|
| 自动屏幕旋转 | 5-10 | 低 | 低通滤波器 |
| 计步 | 20-50 | 中 | 高通滤波器 + 峰值检测 |
| 游戏(赛车) | 50-200 | 高 | 校准 + 低通滤波器 |
| 相机稳定 | 200-1000 | 最高 | 互补滤波器 |
| 手势识别 | 50-100 | 中 | 高通滤波器 + 阈值检测 |
在实现加速度计时需要注意,设备发热和传感器老化可能会影响读数的准确性。对于关键测量(视频稳定、指南针),建议在传感器融合(sensor fusion)框架下额外使用陀螺仪和磁力计。
加速度计容易出现几种类型的误差:零偏(bias)— 传感器在静止时显示非零值;比例因子误差(scale factor error)— 不同轴上的灵敏度不同;以及测量噪声(noise)— 降低单次读数的准确性。MEMS传感器在出厂时经过校准,但随着时间的推移,参数可能因温度和机械负载而发生漂移。在应用中进行校正可以实现简单的校准:在静止状态下记录平均值(偏移量),然后从所有后续测量中减去该值。更精确的校准需要将设备绕所有轴旋转 — 这种方法称为六点校准(six-point calibration),误差低于0.5%。
常见问题
加速度计是智能手机中约1毫米大小的MEMS传感器,用于测量三个轴上的加速度。它无需外部源即可确定设备方向(竖屏或横屏)、摇晃、步数和运动。
加速度计测量线性加速度(包括重力),而陀螺仪测量角速度(旋转)。加速度计确定方向,陀螺仪确定旋转。它们一起提供空间中运动的精确跟踪(传感器融合)。
使用SensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)获取传感器,然后使用SensorEventListener注册监听器。在onSensorChanged中,event.values数组包含X、Y、Z值(单位为m/s²)。在onPause中注销。
计算magnitude = sqrt(x² + y² + z²)。如果magnitude超过2-3g(重力过滤后),则设备被摇晃。iOS使用CMMotionManager,阈值为2.5g;Android使用Sensor.TYPE_LINEAR_ACCELERATION,阈值为15 m/s²。
可以。进行简单的校准时,将设备放在平坦表面上,记录每个轴上2-3秒内的平均读数,然后从所有后续测量中减去这些值。这可以补偿零偏(bias),但不能补偿比例误差。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。