SL.pro
博客 · · 9分钟阅读

水平仪应用的工作原理:手机加速度计解析

您的手机之所以知道哪边朝下,是因为它内部有一个叫做MEMS加速度计的微型传感器。这个传感器会同时测量重力在三个方向上对手机的拉力。水平仪应用读取这三个数字,做一点三角运算,就能显示出角度。它每秒钟要做上百次这样的运算,而这一切都发生在一个肉眼几乎看不见的芯片里。本文就来讲讲其中到底发生了什么。

关键要点
  • 加速度计测量的是重力在三个轴上的分布。手机静止不动时,它并不测量运动。
  • 俯仰角和横滚角是把这三个重力读数代入反正切公式算出来的。
  • Spirit Level Pro会把原始读数经过指数移动平均(alpha=0.15)处理,防止气泡抖动。
  • MEMS传感器会随温度漂移,所以要在你实际干活的地方校准。
  • 只要手机静止贴在一个表面上,加速度计就能独立完成全部工作,用不上陀螺仪。
Close-up macro photo of a Kionix MEMS tri-axis accelerometer chip from a mobile device
您手机内的MEMS加速度计芯片比米粒还小,却能精确测量重力。

什么是MEMS加速度计?

MEMS是微机电系统的缩写。手机加速度计里的感应元件非常小,只有几百微米,比一粒盐还小。它和普通芯片电路一样长在同一块硅片上,用同样的工艺制造。正因为如此,这类传感器很便宜,几乎每部手机里都有。

只要在脑子里想象一下,它的原理就很简单了。一小块质量块挂在刻蚀进芯片里的硅弹簧上。当芯片倾斜时,重力会把质量块稍微拉偏。这个位移改变了梳齿状金属电极之间的间隙,而间隙的变化又会改变它们之间的电容。芯片读取这个变化,把它换算成一个以g为单位的加速度数值。

接下来这一点才是水平仪能成立的关键。手机静止不动时,加速度计读到的不是运动,而是重力沿它三个轴各分了多少。重力是一个恒定且已知的力。一旦你知道它在三个轴之间是怎么分配的,就能精确算出手机是怎么倾斜的。

三轴加速度计如何测量倾斜?

三轴加速度计给手机定义了自己的一套方向:X是从左到右,Y是从上到下,Z是从前到后。把手机平放在桌上,重力几乎全部沿Z轴作用,所以Z读到约9.81 m/s²,而X和Y都接近零。一旦倾斜手机,重力就会重新分配,Z上少一些,X和Y上多一些,比例正好对应倾斜的角度。

把这三个读数换算成角度,用的是基础的三角运算。俯仰角是前后方向的倾斜,横滚角是左右方向的倾斜,两者都用反正切算出来:

俯仰角 = arctan( Y / sqrt(X² + Z²) ) 横滚角 = arctan( X / sqrt(Y² + Z²) )

这两行就是一个水平仪应用全部的数学核心。把三个原始数值代进去,算一遍,就得到以弧度为单位的俯仰角和横滚角。再乘以180/π换成度数,那就是你屏幕上看到的那个数字。

你也许会好奇,为什么分母用的是另外两个轴的平方根,而不是单独一个轴。这是为了让读数在整整一圈旋转里都保持稳定。如果只除以某一个轴,那么在接近垂直时算式就会出问题,因为那个轴会降到零,你等于是在除以一个几乎为零的数。改用另外两个轴合起来的大小,就能避开这个麻烦。

Freescale Semiconductor 3-axis MEMS accelerometer breakout board on white background
3轴加速度计同时测量X、Y和Z轴上的重力拉力。
实时感受物理原理在运作

Spirit Level Pro实时显示俯仰角和横滚角,带EMA平滑、五档容差预设和一键校准。无需下载。

免费试用 Spirit Level Pro

为什么原始传感器数据这么吵?

原始加速度计输出的跳动比你想象的要大得多。哪怕手机纹丝不动地放着,读数也会有小幅晃动。其中一部分是传感器本身的电噪声,一部分是从桌面传上来的振动,还有一部分是模拟信号转成数字时的舍入误差。把这种原始数据直接显示出来,气泡就会一刻不停地抖,做精细活儿根本没法用。

噪声来自几个方面。热噪声是热量引起的随机电波动。它去不掉,决定了传感器能安静到什么极限。振动噪声来自周围的世界:冰箱压缩机、脚步声、窗外的车流。此外,传感器的零点也会随时间慢慢自行漂移。每一种都得用不同的办法来对付。

常见的软件办法是低通滤波器。它让慢变化(比如真实的倾斜)通过,把快变化(比如振动)挡在外面。最常用的做法是指数移动平均,简称EMA。每个新读数只占一小部分权重alpha,其余部分则沿用上一次的滤波结果:

滤波后 = alpha × 新读数 + (1 - alpha) × 之前滤波后

Spirit Level Pro用的是alpha=0.15的EMA。这个数字是我们手动试了一系列取值之后定下来的。alpha取0.05时,读数平滑得像玻璃一样,但反应慢,移动手机时气泡会明显跟不上。alpha取0.3时跟得很紧,但抖动大到很难读到一个精确值。0.15正好在两者之间,气泡显得灵活,又不至于神经兮兮。

这里的取舍: alpha越大,显示跟随真实倾斜越快,但放进来的振动也越多。alpha越小,平滑得越狠,但延迟也越大。0.15在两者之间取得了平衡,大约150毫秒就能稳定下来。

陀螺仪起什么作用?

陀螺仪测量的是手机转得有多快,单位是每秒多少度,而不是手机朝向哪里。这个区别很重要。单靠陀螺仪,它没法告诉你手机是不是水平的。它只知道手机在不在转、转得快不快。要在手机静止时读水平,加速度计已经把该有的信息都给了你。

陀螺仪真正派上用场,是在手机运动的时候,靠的是传感器融合。加速度计读静态倾斜很在行,但在快速运动时又慢又吵。陀螺仪跟踪快速旋转很在行,但会漂移,因为它的小误差会随时间累积。互补滤波器或卡尔曼滤波器把两者结合起来:陀螺仪负责快速运动,加速度计把长期读数拉回到准确值。

大多数水平仪应用,包括Spirit Level Pro,都不用传感器融合,因为它面对的是静态场景。你把手机放下,等它稳定,再读角度。这种情况下加速度计自己就能搞定。传感器融合更适合飞行中的东西,比如无人机跟踪自身的运动,而不是你检查一块搁板。

为什么校准这么重要?

每个MEMS传感器出厂时都带着一点内置偏差。这是制造过程中形成的固定偏移,每次读数都一样:方向固定、大小固定。所以哪怕手机真的放平了,芯片也可能读出一两度的偏差。这就是水平仪应用开箱即用时读数不准的头号原因。

校准的办法,是在一个你确信平整的表面上测出这个偏差,再把它存下来。Spirit Level Pro把这些值存在localStorage里的calibrationPitchcalibrationRoll下。从此以后,每次读数在显示到屏幕之前,都会先减掉这两个存下来的数。偏差就此消失。

这个差别很大。不校准的话,一部有1.5°偏差的手机,对什么都会读偏1.5°。它可能在一个真实倾斜1.5°的斜面上却显示0.0°。同一部手机校准之后,误差就降到零点几度。这是你能拿到的最大的一次精度提升,而代价不过是几秒钟。

温度如何影响精度?

MEMS传感器会对温度起反应。托着质量块的硅弹簧会随着芯片变热、变冷而胀缩,零点也就跟着挪动。所以把手机从暖和的车里拿进冰凉的车库,读数会先漂一下,等传感器适应了新温度才稳定下来。这个变化不算大,但确实存在。

实用的一条经验很简单:在你打算干活的那个温度下校准。在暖和的办公室里校准好的手机,拿到冷车库里就不完全靠得住了。你不用为每一件活儿都纠结这个。挂画、检查搁板这类活儿,漂移小到根本看不出来。但要做零点几度以内的精细活儿,那就在温度大幅变化后给手机一两分钟适应,然后再校准。

Spirit level mounted on a camera showing how angular measurement works
多个传感器协同工作,确定设备在三维空间中的朝向。

iPhone和Android:传感器硬件不一样吗?

确实不一样,而且用起来能感觉到。苹果自己做整套运动方案。从iPhone 6s往后,机型里都带一颗苹果的运动协处理器,单独处理传感器数据,不占用主CPU。三星Galaxy旗舰用的是意法半导体的芯片,把三轴加速度计和三轴陀螺仪做在同一块晶粒上。谷歌Pixel则视年份不同,用过博世和TDK InvenSense的传感器。

校准之后,旗舰iPhone和旗舰Android的表现其实差不多。真正拉开差距的是旗舰和廉价Android之间。廉价手机用的是更便宜、分辨率更低的MEMS,原始输出也更吵。校准仍然能把它们拉得很近,对大多数DIY活儿来说结果都够用了。

让iPhone在水平仪应用里出彩的,与其说是加速度计,不如说是那颗运动协处理器。哪怕应用不在前台,它也在以很高的频率持续采集传感器数据,这样平滑滤波器就有更多样本可用。这很大程度上解释了为什么iPhone在这里用起来格外顺滑,哪怕对手是纸面参数一样好的Android手机。

常见问题

水平仪应用在手机上是怎么工作的?

它们读取手机的MEMS加速度计,这个传感器测量的是重力沿三个轴(X、Y、Z)的拉力。手机一倾斜,重力就在这三个轴之间重新分配。应用用反正切公式算出俯仰角和横滚角,再做平滑处理压住传感器噪声,然后显示成气泡水准或一个数字。整个过程每秒要跑上百次。

手机加速度计当水平仪用,精度怎么样?

校准过的旗舰手机能读到零点几度以内。廉价Android手机不校准时读数会差一些,因为它们的传感器更便宜、单机之间的差异也更大。影响最大的一环是校准:它能去掉出厂偏差,把几乎任何手机都拉得很近。对大多数DIY和工地活儿来说,一部校准过的中端手机就足够准了。

水平仪应用会用到陀螺仪吗?

手机静止时,不会。加速度计自己就能给出倾斜角。陀螺仪测的是旋转速度,不是朝向,所以它没法告诉你手机是不是水平的,只知道它转得多快。有些应用会把两个传感器结合起来,好让运动中的读数更平滑,但要把手机贴在墙上读个角度,加速度计一个就够了。

为什么我的水平仪应用放在平面上读数也略有偏差?

通常是出厂偏差在作怪。每颗MEMS芯片都带一点内置偏移,哪怕手机放平了也读不到零。在一个你信得过的平面上校准就能把它清掉。其他原因还包括温度漂移、手机壳把一边垫高了,或者手机底下有灰。任何一次大的温度变化之后,在干净的玻璃桌上校准一下,基本就能解决大部分问题。

完整的图景

水平仪应用之所以可靠,是因为背后的物理靠得住。重力恒定不变,加速度计时刻在测量它,三角运算再把三个数字变成一个角度。从感应元件到气泡显示,这一路都是固定的数学,没有任何靠猜的成分。

一个水平仪应用比另一个好在哪,靠的不是硬件。每部旗舰手机出厂时带的传感器都已经绰绰有余。差别在软件:原始数据流过滤得好不好,校准是怎么存、怎么用的,容差预设是不是对得上真实的活儿。这些做对了,一颗便宜的MEMS芯片也能顶得上贵出许多的专业工具。

搞懂传感器怎么工作,也会让你用得更好。在干活的温度下校准。做精确读数时把手机壳摘掉。相信读数之前先让它稳定一秒。这几个习惯,全都直接来自你明白硬件到底在做什么。

免费试用 Spirit Level Pro

在任何手机或平板电脑上工作。无需下载。专业功能从$10一次性付费。

打开 Spirit Level Pro

无需账户 · 离线工作 · 20种语言