阅读我以前关于APDS-9960的
文章的评论,其中涉及颜色识别和亮度,对我来说,有两件事变得显而易见:1)手势识别主题很有趣,并且2)这个主题没有公开。
的确,如果我讲了APDS-9960的说明,那么在不考虑手势的情况下,说明看起来有些不完整。 因此,我也有一些空闲时间来探索这个主题。
在本文中,我提醒您注意APDS-9960传感器提供的手势识别功能。
本文将考虑用于设置传感器,数据收集,处理和表示的机制。 您自己可以看到使用APDS-9960进行手势操作有多么容易。
上次,本文将附带一个代码,其中将详细描述发生的所有事情。 本文末尾提供了完整的代码版本。
随便一句话:APDS-9960没有内置的自动手势检测机制; 也就是说,在这里,我读到了它的意思,即寄存器,并且已经存在经过处理的手势-这不在APDS-9960中; 这意味着您必须编写自己的手势解释算法,稍后我们将做。
总的来说,这既好又不好。 并非如此-因为它可以使初学者对该传感器的研究变得复杂,但是很好,因为,加上近似数据,您甚至可以细化自己的各种手势。
但是,由于本文仅具有概述功能,因此我们只限于基本的UP-DOWN-LEFT-RIGHT手势。
好吧,让我们开始吧。
理论
我会给自己一点物资。
为了获得有关运动和运动方向的必要信息,APDS-9960使用一个IR LED和四个光电二极管,如下图所示,它们检测近红外(NIR)范围内的信号。

IR LED(LED)具有背光功能,而光电二极管(UDLR)记录从“障碍物”反射的光。
光电二极管以这样的方式位于传感器上:根据“障碍物”的移动方向,相应的光电二极管将在输入端接收大部分反射的IR信号,并在输出端接收较小的一部分。 同时,APDS-9960上的文档明确告诉我们,您可以通过测量和比较UDLR光电二极管信号的幅度和相位差来解释运动方向。

练习
要与APDS-9960以及
上一次一起使用,我们将使用STM32VLDISCOVERY。 连接也没有改变。
配置APDS-9960我们进行传感器的初始设置。
像这样:
APDS9960_initvoid APDS9960_init(void) { i2c1_write(APDS9960_CONTROL, DEFAULT_PGAIN); i2c1_write(APDS9960_GPENTH, DEFAULT_GPENTH); i2c1_write(APDS9960_GEXTH, DEFAULT_GEXTH); i2c1_write(APDS9960_GCONF2, DEFAULT_GGAIN); i2c1_write(APDS9960_GPULSE, DEFAULT_PULSE_LENGTH); i2c1_write(APDS9960_PPULSE, DEFAULT_PULSE_LENGTH); }
这是怎么回事 让我们做对。
i2c1_write(APDS9960_CONTROL, DEFAULT_PGAIN);
PGAIN(接近度增益控制)是控制接近度灵敏度的增益的参数。 给它分配一个值为2的值,它对应于增益的四倍。
i2c1_write(APDS9960_GPENTH, DEFAULT_GPENTH); i2c1_write(APDS9960_GEXTH, DEFAULT_GEXTH);
GPENTH(手势接近度输入阈值寄存器)-此参数设置用于确定手势识别开始的接近度阈值。
GEXTH(手势退出阈值寄存器)分别设置用于确定手势识别结束的阈值。
i2c1_write(APDS9960_GCONF2, DEFAULT_GGAIN);
在GCONF2(两个手势配置)寄存器中,我们仅将GGAIN(手势增益控制)参数显式设置为增益值的四倍。
i2c1_write(APDS9960_GPULSE, DEFAULT_PULSE_LENGTH); i2c1_write(APDS9960_PPULSE, DEFAULT_PULSE_LENGTH);
背光灯 默认情况下,红外LED背光源的电流值设置为0(对应于100 mA的电流),这将非常适合我们-我们将不会对其进行更改。
APDS-9960中的IR照明是一个脉冲序列,其特征在于手势GPULSE(手势脉冲计数和长度)的相应寄存器参数:GPLEN(手势脉冲长度)和GPULSE(手势脉冲数),以及PPULSE(接近脉冲计数寄存器)的近似值):PPLEN(接近脉冲长度)和PPULSE(接近脉冲计数)设置脉冲数和每个单独脉冲的周期。
定义GPLEN和PPLEN的值为2等于16μs,GPULSE和PPULSE的值为9,对应10个脉冲。
如您所见,与以前的APDS-9960评论中的颜色识别和照明设置相比,该设置要稍微复杂一些。
读取数据现在,我们进入主程序循环,在该循环中,我们不时开始注册和解释光电二极管中的数据,并学习如何将一个手势与另一个手势区分开。
首先,让我们以手势和缩放功能启动APDS-9960。
GesturesSet(GESTURES_START);
然后我们立即开始跟踪GVALID参数。 GVALID(手势FIFO数据)是GSTATUS寄存器(手势状态寄存器)的参数,处于非零状态时,通知我们传感器具有可用的手势数据。
该文档告诉我们手势信息位于RAM区域的缓冲区中,该缓冲区的大小通常为32 x 4字节。
实际上,该缓冲区的实际大小可以通过读取GFLVL(手势FIFO级别)寄存器的值来找到,即 根据我的纯粹经验实验观察,获得GFLVL * 4。 像这样:

好吧,如下所示,根据缓冲区的名称,缓冲区中的数据按照先进先出的顺序排列。 也就是说,粗略地说,来自每个光电二极管的信号“越早”到达,其在GFLVL中的“越高”。
可以从相应的手势FIFO寄存器读取光电二极管(UDLR)的数据:
-GFIFO_U(手势FIFO数据,UP)
-GFIFO_D(手势FIFO数据,向下)
-GFIFO_L(手势FIFO数据,左)
-GFIFO_R(手势FIFO数据,右)
每次从这些寄存器中读取值后,GFLVL都会减小。 因此,有必要以良好的方式读取整个缓冲区,直到GFLVL达到零为止。
要定义手势,我们只需要此缓冲区的前四个字节,就不需要更多。 因此,我们只会阅读它们。
GestureUp = i2c1_read(APDS9960_GFIFO_U); GestureDown = i2c1_read(APDS9960_GFIFO_D); GestureLeft = i2c1_read(APDS9960_GFIFO_L); GestureRight = i2c1_read(APDS9960_GFIFO_R);
手势识别为了解释发生了哪种手势,我们将进行简单的计算:
GestUpDown = GestureUp-GestureDown; GestLeftRight = GestureLeft-GestureRight;
要确定当前发生了哪些手势,对我们而言,重要的不是GestUpDown和GestLeftRight的值,而是一个实数的符号。
也就是说,以GestUpDown和GestLeftRight变量的负值和正值作为输入,我们确定哪个手势是完美的。
下图显示了GestUpDown和GestLeftRight变量的真值表。

现在重置GFLVL:
GesturesSet(GESTURES_STOP);
...然后回到主程序周期的开始。
现在整个代码:
main.c #include "stm32f10x.h" #define APDS9960_I2C_ADDR 0x39 #define APDS9960_ENABLE 0x80 #define APDS9960_GSTATUS 0xAF #define APDS9960_GFLVL 0xAE
我想指出,APDS-9960的手势机制工作得很好。 识别稳定,APDS-9960紫外和红外内置的滤光片工作良好。
我希望这些材料对某人有用。 谢谢您的关注。