《Arduino计算机视觉编程》一3.2 传感器数据采集-阿里云开发者社区

开发者社区> 华章出版社> 正文

《Arduino计算机视觉编程》一3.2 传感器数据采集

简介:

本节书摘来自华章出版社《Arduino计算机视觉编程》一书中的第3章,第3.2节,作者[土耳其] 欧森·奥兹卡亚(zen zkaya),吉拉伊·伊利茨(Giray Yilliki),更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.2 传感器数据采集

对大多数实时应用程序来说,视觉信息和传感器信息的结合对于更好地理解环境是至关重要的。系统的整体性能和各个子模块紧密相关,因此有效恰当地实现传感器数据采集就变得非常重要。
即使检测的是相同的物理对象,也有很多不同的传感器。举一个简单例子,有很多不同类型的温度传感器,尽管它们都是设计用来测量温度的。如果你想测量皮肤的温度而不是大气温度,那么该如何选择一个合适的传感器?该如何选择一个采样间隔?如何处理噪声?本章的目的是让你彻底了解传感器数据采集。在本章的结尾部分有一个用Arduino Uno R3开发的实际传感器接口的例子。
3.2.1 设置Arduino环境
如前所述,Arduino对于嵌入式系统应用的快速建模来说是一个非常完美的平台。在合适的背景下,因为拥有庞大的库以及社区支持,Arduino也是一个合适的传感器数据收集工具。
要开发Arduino应用,你需要在Arduino官方网站(http://arduino.cc/en/Main/Software)下载Arduino集成编辑器。在本书中,所有的应用程序都使用Arduino Uno R3。但同样的原则通用于其他Arduino平台。下图为一个典型的Arduino的集成编辑器。


2701cfd0921dad12f3e868e6414d5d9f074364e9

准备好你的Arduino Uno R3,下载Arduino集成编辑器并且设置好环境。安装过程就和安装其他应用一样简单。然后就可以开始实践了!
3.2.2 传感器基础
重要的是理解传感器基础进而充分理解传感器的接口。在本节中,将会讨论基础的传感器分类、采样定理以及处理噪声的方法。你会学到很多传感器的知识以及如何在计算机视觉应用中有效地使用它们。
3.2.2.1 传感器类型
传感器的类型几乎是无穷无尽的,但即使如此,对传感器做一个有意义的分类也有助于选择所需的传感器。
最基本的分类方法是基于测量的物理参数。温度、光照等级、压力、加速度和湿度都是物理参数的例子。尽管物理参数众多,但是绝大多数的接口是类似的。一旦你搞明白一个参数并且充分实践,测试其他物理参数也很容易。
可以根据输出信号类型将传感器分为两类:模拟传感器和数字传感器。模拟传感器输出连续信息。数字传感器输出离散信息。
因为几乎所有的嵌入式系统都是数字系统,所以在任何情况下,在嵌入式系统中都应该使用传感器数据的数字格式进行处理。由于这个原因,所有的模拟传感器都使用特殊的外接模拟数字转换器(Analog to Digital Converto,ADC)作为接口。这使得我们的开发变得非常简单。可以使用大致相同的代码以读取温度传感器数据的方式来读取光照传感器的数据。当然,读出数据的解释方法是不同的。
通常情况下,数字传感器都是通过相同的嵌入式通信接口(外设)进行访问,这些通信接口包括通用同步和异步接收/发送器(USART)、内部集成电路(Inter Integrated Circuit,I2C)以及串行外设接口(Serial Peripheral Interface,SPI)。通过访问名为寄存器的特殊内存区域,可以设置传感器并读取传感器内部的数据。因此,数字传感器一般提供了更多可以设置的选项。正因如此,复杂的传感器比如运动传感器往往设计为有一个数字格式的接口。最好的消息是一旦你学会使用这些通信接口,其他类型的传感器的使用都是大同小异的!需要注意的是Arduino集成编辑器提供了与这些通信方式进行接口的库,这使得这些传感器更加易于使用。
所以,准备开始学习如何使用这些接口吧!在接下来的内容中,将会覆盖关于传感器数据读取的两个重要主题:采样率和噪声抑制。
3.2.2.2 采样理论
传感数据的采样定义了从传感器读取出来的数据的采样率。如果你需要实时的采样传感器数据,那么应该多久对输入数据采样一次?每50ms或是100ms采样一次是否足够呢?你该如何确定最佳的采样率?关于这个问题的一个比较简单的答案是多试几个采样率然后选用效果最佳的那个!但是,这么做当然失败率很高。
在信号处理中,Nyquist判据用于确定采样率。Nyquist判据只是简单陈述了采样率必须至少是输入信号最高频率分量的频率的2倍。给定这么一个采样率,可以重建原始输入信号而不会丢失原始输入信号携带的信息。如果你知道信号的最大频率分量的频率是多少,那么这种方法是非常不错的。即使在这种情况下,采样率是信号最大频率分量的频率的5倍也是安全的。
但是一般情况下,不太可能限定传感器数据的最大频率分量。所以,当选择传感器的采样率时,基于知识推断一个采样率的效果更好。很幸运的是数字传感器的采样率一般可以通过考虑传感器的目的进行良好的推测。但是如果使用的是模拟传感器,你就需要考虑各种限制来猜测一个采样率了。其中一个选项是选择尽可能高的采样率,但是这并不是一个好主意,因为这会导致显著增多的能量消耗、存储器占用以及计算时间,所以这个方案会对我们想要尽量控制的东西产生不利影响。因此,解决这个问题必须采用其他的方法。
试想一下如果你想对大气的温度数据进行采样。房间的温度在一秒钟内变化10℃是不正常的。在这个示例应用程序的环境中每10s采样一次在大部分情况下是足够的。但是如果我们想对加速计进行采样来检测运动,应该看下要检测的最快的运动是什么,比如在手势检测中,最快的运动可能是持续2s左右的手势。要能够分离出手势的模式来,可能需要从手势的运动中进行200次采样,所以采样率为2/200 = 10ms(相当于100Hz),对于这个例子来说这是一个很好的起点。通过这种简单的推断有可能确定最佳的采样频率。
3.2.2.3 处理噪声
如果我们要从传感器中捕获数据,那么捕获的实际测量值里面会包含噪声。在实践中完全消除噪声是不可能的,但是可以把噪声降到一个可接受的范围内。医学应用程序的噪声容忍度很自然地要比一个业余时间开发的应用程序低。请不要忘记能接受什么程度的噪声完全是由应用程序决定的。
与传感器噪声的“战争”从传感器的电子接口就开始了。但愿每一个厂家都在传感器用户手册或者数据表中放了一个采样驱动电路(sample driving circuit)。请遵循这个参考设计,除非你有一个足以改变游戏规则的绝妙设计。
另一个处理噪声的方法是进行过滤处理来部分地从传感器数据里面移除噪声。如同采样率的选择过程一样,应用程序的上下文会对传感器数据的过滤处理产生影响。举例来说,如果你在处理温度传感器的数据,你可以简单地移除那些高频数据,它们就是噪声。这是因为1s发生10℃的变化是非常不合理的。同样,对于运动检测,你可以从应用程序中移除那些频率过高或者过低的部分。
噪声抑制可以通过基于硬件或者软件的方案来解决。基于硬件的方案需要电路上的额外组件来实现。另一方面,基于软件的方案可以通过编码来实现。一般在需要非常快速过滤的情况下才会选择基于硬件的方案,因为它的花费更高。很多时候改变电路不是很方便,所以使用基于软件的噪声抑制方案更容易也更加灵活。
因为嵌入式系统的资源往往是有限的,我们不能在嵌入式系统上使用非常复杂的滤波器。但是这不意味着在嵌入式系统上没有办法进行有效的过滤。在下面两个例子中,你将看到一些简单有效的过滤实现。
3.2.3 从温度传感器中读取数据
现在你已经有了足够的知识来进行实践,从了解一个相对简单的模拟传感器开始是非常好的起点。
LM35系列传感器是精确的摄氏温度传感器,它的输出电压与摄氏度成线性正比。在室温下LM35设备在无需外部校准的情况下能达到0.25℃的准确度。在-55℃~150℃的范围内,它能达到0.75℃的准确度。
用LM35来搭建一个传感器数据采集系统不需要太多设备。只需要Arduino Uno R3模块、LM35设备、面包板、一些连接线和电脑!很多传感器也采用类似的结构。距离传感器、光照传感器以及任意输出在0~5V之间的传感器都可以以类似的方式读取数据。
LM35有三个引脚:GND、+Vs和VOUT。首先用连接电缆将Arduino Uno R3的+5V引脚与+VS引脚相连。其次将Arduino面板上的Analog0(或者是A0)引脚与VOUT引脚相连。最后一步是将LM35的GND引脚与Arduino Uno R3的GND引脚相连。连接关系如下图所示。在这种配置下,LM35只能测零上的温度。


a0435643fca0b9b48bbf586fa734555130a6cb89

如前所述,模拟传感器应该用ADC作为接口。Arduino Uno R3有一个10比特的ADC。利用这10比特数据,可以写210=1024个数字。这意味着ADC可以把5V电压分成1024份。比如5V映射到ADC的值为1023,2.5V映射到ADC的值为512。所以可以从ADC的值换算出电压值,公式如下:


d3ceb86441257bc3c490ec04787e5cf053013987

ADC的采样值是你从ADC模块中读取的值。根据上面的公式,比如你读到的ADC采样值是135,那么该引脚的电压就应该是:


3f791d4d04124f10575d26bd533e12b8ed9401c3

LM35的数据手册上说,每10mv对应着1℃。因此660mv意味着66℃。我们把下列代码复制到Arduino编辑器中,并且把它下载到Arduino Uno R3:


ebe7cbdbf757a046a640d78b0f095313f2d12973


eb4128392a0c7587de613fc4ff7b26c2a4e07d3d

编译代码并把它下载到Arduino Uno R3之后,用一个USB串行终端与Arduino相连,你能看到一个摄氏度值。正如你看到的,我们每秒对传感器数据采样一次。
但是问题并没有解决。LM35能够测量的最大温度是150℃,这意味着最大的输出电压可能是1.5V。我们只用了0~5V的一小部分,大部分都被浪费了。所以当前的方案还有提高的空间。室温150℃并没有什么用处,可以找到一个更聪明的方法。
如果我们把模拟参考电压(第一次是5V)改成一个比较小的值比如1.1V,这样可以提高测量精度。在这种情况下,公式会发生变化,如下所示:


7aa20d2c303039c908cbe7067da16d7e326aa34f

要改变模拟参考电压值为1.1V,可以使用analogReference(INTERNAL)函数。我们还用了一个简单的滤波算法来去掉高频变化的影响,如下所示:


2d20f06180377376d4ff6e9ea0404c6ebf38743c


548734a6b5d515fc63c8a6c057dca85f40d4fd22

也许最重要的部分是过滤公式。这段代码使用的滤波器是boxcar积分器。滤波器的一般实现如下所示:


548734a6b5d515fc63c8a6c057dca85f40d4fd22

在上面的公式中,新的过滤后温度值(current_output)90%由新的温度测量值(input)决定,10%由旧的温度测量值决定。因此高频温度噪声会受到旧温度测量值10%的抑制。
此外,通过使用一个1.1V的区间,我们有了更高精度的温度信息。在这种情况下,能够测量的最高温度是110℃,这也是可以接受的。总之,现在我们有了一个更好的传感器接口。
请分析下Arduino的传感器例子并且试图找出如何使用在本章中学到的知识来提高这个例子的效果。你可以看到相同的原则可以轻松地应用到各种传感器应用程序上。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接