这是一个多部分的文章系列,旨在给读者讲清楚MPR121传感器的工作原理,以及如何调参以适应各种应用场景。这个传感器在中文社区中资料较少。唯一能查询到的资料不是解释不清楚,不完整,就是有一点点错误。我希望通过这个系列的文章,能够让硬件玩家或者音游手台制作大佬制作出更好的作品。
文章目录:
契机
今年年初的时候接触到了一个游戏叫乌蒙地插舞萌DX。这个游戏是一个音乐游戏,每一个框体可以同时让两个玩家游玩,每个游玩区域拥有八个按键和34个触摸感应区。
本来我是想用一些文字来介绍这个游戏的大概游玩方式的,但是我想起来这一系列文章的目的是讲MPR121而不是maimai(舞萌吃犯病)。
简单来讲的话,就是说这个游戏有一部分(或者全部的)游戏内容需要通过触摸来完成,需要实现的效果是当玩家的手指只要触碰到某一个触摸区域的话,这个区域就应该有反应。如果使用普通的多点触摸屏的话,一个手掌拍上去可能只会识别到一个触摸点,手掌边缘碰到的触摸区域可能会被忽略,所以不太适合用作这个游戏的触摸方案。并且,官方的机台就是使用的34个单独的触摸传感器来感应玩家的手部是否碰到该区域。下图是这个游戏的34个触摸区域。
原理
说在前面,我不是物理专业也不是电子专业的,如有错误请指正。
触摸检测原理
为了实现这样的触摸效果,我们可以使用某种透明的导电材料1来覆盖每一个触摸区域,并用细引线引出电极,接入控制器。当玩家的手部靠近某一个触摸区域时,该区域的有效电容会增加。如果我们使用控制器测量每个区域的电容,并和一个基线2电容进行比较,检查其差别是否超过一个阈值的话,那么我们就可以决定用户是否按下了某个区域。
而实际上,在传感器的内部,我们不是直接去测量电容值来决定是否触摸的。我们是通过测量一定时间内,使用一定的电流对电容进行充电,最后测得的电压值来间接测得电容。在测试完成后,我们再对这个电极接地放电,以准备下一次的测量。下图是MPR121手册中的示意图3。
但是,我们如何知道如何选择最佳的充电电流和充电时间呢?不用担心!MPR121已经具备了自动搜索(AUTO CONFIG)这些参数的功能,我们不需要担心这些!
简单触摸检测算法
根据上面的知识,我们可以知道,我们的MPR121测量出来的,实际上是每个触摸区域的一组电压值。当用户接近或者触摸到这个触摸区域时,这个电压值会降低4。
知道了这些知识,这个问题就好办了。我们只需要一直对我们关心的电极进行测量,当我们发现测量值减少了,减少的程度超过一个阈值,就认为用户触摸了那个电极!
但是具体来说我们如何知道我们的测量值减少了呢?我们可以这样子做:对于每个电极存储一个值,这个值是用户没有触摸的时候这个电极的测量值,用于在每一个时刻与测量的数据进行比较,我们称之为基线。
看起来似乎我们已经拥有所有信息了!我们可以来尝试写一个非常基础的算法。这个算法假设在程序启动的时候,用户是没有触摸任何电极的。我们把每个电极的初始测量值作为每个电极的基线。然后每毫秒,我们读取每个电极的数据,使用每个电极的基线减数据,可以获得每个电极的数据偏差。如果这个数据偏差大于某个预先设定的阈值,那么就认为用户触摸了这个电极。
呜呼!恭喜你!我们已经可以检测用户的触摸了!!!
但是别高兴地太早,我们这个程序还大有问题!主要是下面这两点:
- 实际生活中的信号是有噪声的,不是像理想情况下那样不触摸是一个值,触摸了之后就是另外一个值。这些噪声可能是环境中各种电器导致的,可能是电源不稳定导致的等等。我们需要把这些噪声过滤掉,获得一个相对平稳的信号,减少误触发率。
- 我们上面的算法的基线值是恒定的,但是实际情况下基线是有可能变化的。这些变化可能会由环境的温度变化,湿度变化,用户使用湿毛巾擦拭触摸表面,触摸背后显示屏电气性质变化等因素影响。所以我们需要实时追踪这些环境变化,动态调整基线。而实际上,MPR121的基线调整方式是在第二级过滤的数据上,使用一个非常慢的滤波器,作为基线的值。这里暂时听不懂也没关系,我们在之后的文章中会详细解释。
所以,我们在使用MPR121的时候不会去直接使用最原始的数据进行触摸检测,而是使用MPR121滤波后的信号进行触摸检测。
MPR121功能
MPR121的强大之处就在于,它的设计者在设计这个芯片的时候考虑了这些问题,并且把滤波和基线追踪内置在MPR121里面,我们只需要调整一些少量的参数,就可以控制它们。而且在大部分情况下,这些参数都不需要进行非常大的变化!
MPR121中数据流如下图所示5:
- 首先,MPR121对用户启用的每一个电极进行我们上面提到的测量,每一次测量的间隔时间是上面所提到的充电时间的两倍。
- 之后,这些原始数据会被送入第一级滤波器。这一级滤波器会将一定量的原始数据收集起来,去掉最大值和最小值,对剩余的值进行平均。最后将平均后的值送入第二级滤波器。
- 第二级滤波器会将一定时间内的数据收集起来,进行平均。平均后的数值就是用作触摸判断的数据。
- 这些经过二级滤波后的数据还会被送入基线滤波器,用于更新基线的数值以适应环境的变化。
- 这一层的滤波通常的策略是当测量的数值有上升的变化时,快速调整基线为上升后的数值。当测量的数值有下降变化时,缓慢调整基线为下降后的数值。当检测到触摸时,暂停基线的更新。
- 上升的变化需要快速适应的原因是因为上升是用户松开触摸的方向,这个方向的变化几乎都是由环境因素引起的,我们需要快速适应。
- 下降的变化需要缓慢适应的原因是,如果用户以较慢的速度接触触摸板,而我们以过快的速度更新基线的话,在用户物理上已经触摸到电极的时候,基线可能已经和滤波后数据相等,无法检测到触摸。
- MPR121会以一定的时间间隔去检查滤波后的数据和基线的差值,如果这个差值超过了用户预先设定的阈值,那么它就会更新该电极的触摸状态寄存器。
- 当任意一个已启用的电极的触摸状态变化时(被触摸或被释放),MPR121会通过IRQ pin发出中断信号,使用中断信号可以更高效地与MPR121进行通信,并且抗噪声能力也更强6。
我们在实际使用MPR121的时候,只需要去轮询MPR121的触摸状态寄存器就可以知道某个电极的触摸状态了!如果你出于某种原因不想使用轮询的话,也可以使用MPR121的中断功能来获得触摸状态变化的通知。
文章系列的组织结构
该系列的剩余文章我初步打算以下面的方式组织:
- 第二部分: 充放电参数自动搜索
- 第三部分: 两级滤波
- 第四部分: 基线系统(第三极滤波)
- 第五部分: 触摸检测,阈值和防抖
- 第六部分: 程序使用流程,设置和读取寄存器
- 应用篇一: maimaiTouchControl 中参数对应关系
- 应用篇二: maimaiTouchControl Q&A
当剩下部分的文章发布后,我会更新每个文章的头部,添加其余文章的超链接,让读者可以方便地跳到感兴趣的部分。
脚注
- 氧化铟锡(ITO)就是这样的材料,当其被覆在塑料膜或者玻璃上时可以实现透明并导电的效果。这一层薄膜的透光率有80%以上,取决于实际的覆盖厚度(百纳米级),方阻在几十到几百欧姆之间。 ↩︎
- 基线电容指的是用户没有触摸的时候测量到的电容值。在之后的讲解中我们会详细说明。 ↩︎
- AN3889 第2页 ↩︎
- 还是参考 AN3889 第2页。里面有个公式指出测量电压与电容成反比。这个部分非常底层,我的建议是不用非常了解,只需要知道触摸时,测量出来的值会降低就可以了! ↩︎
- 该图是参照AN3889-AN3892中第一页的图画的。我这个图里面标的时间的意思是每一级滤波出来的样本时间间隔,可能和原图中的不太一样。 ↩︎
- 如果我们使用轮询的方式检查触摸状态,那么在任意一次轮询中如果有噪声干扰I2C总线的通信,整个系统都有可能会出问题。如果使用中断的话,我们的通信只会在必要时才进行通信,减少了被干扰的可能性。 ↩︎