2.59 PAJ7620U2 手势识别传感器模块(来自 TaurusHard 的贡献)
2.59.1 模块来源
采购链接:https://item.taobao.com/item.htm?spm=a21n57.1.0.0.6330523cm0XUFK&id=567942906496&ns=1&abbucket=15#detail 资料下载:https://pan.baidu.com/s/1vtqdX0ZbfqszxFoYROvrbQ 提取码:asvs
2.59.2 规格参数
工作电压:3.3V/5V工作电流:2.82mA通信方式:I2C通信速率:400kHz(Max)默认从机地址:0x73工作环境光:<100K Lux有效探测距离:50mm~100mm手势识别种类:9 种(上、下、左、右、前、后、顺时针、逆时针、挥动)工作温度:-20℃~70℃引脚数量:5(VCC、GND、SCL、SDA、INT)模块尺寸:19.7mm x 15mm
2.59.3 模块原理
2.59.3.1 PAJ7620U2 简介
PAJ7620U2 是原相科技(PixArt)公司推出的一款光学数组式传感器,内置光源和环境光抑制滤波器集成的 LED,镜头和手势感测器在一个小的立方体模组,能在黑暗或低光环境下工作。同时传感器内置手势识别,支持 9 个手势类型和输出的手势中断和结果。除此之外,模组还提供接近检测功能,可用于感知测量物体的亮度及物体的接近或离开。 PAJ7620U2 的特点包括: 1.IIC 接口,支持高达 400KHz 通信速率;2.内置 9 个手势类型(上、下、左、右、前、后、顺时针旋转、逆时针旋转、挥动),支持输出中断;3.支持接近检测功能,检测物体体积大小和亮度;4.待机功耗电流 15uA;5.抗灯光干扰。 PAJ7620U2 的模块功能框图如下图所示:
其中,I2C_SCL 和 I2C_SDA 是连接 MCU 的 IIC 接口,MCU 通过 I2C 接口来控制 PAJ7620U2,PAJ7620U2 内部自带 LED 驱动器,传感器感应阵列、目标信息提取阵列和手势识别阵列。PAJ7620U2 工作时通过内部 LED 驱动器,驱动红外 LED 向外发射红外线信号,当传感器阵列在有效的距离中探测到物体时,目标信息提取阵列会对探测目标进行特征原始数据的获取,获取的数据会存在寄存器中,同时手势识别阵列会对原始数据进行识别处理,最后将手势结果存到寄存器中,用户可根据 I2C 接口对原始数据和手势识别的结果进行读取。2.59.3.2 模块寄存器简介
注:PAJ7620U2 的内部有两个 BANK 寄存器区域,分别为 BANK0 和 BANK1。不同的区域用于访问不同的功能寄存器,访问某一 BANK 区域下的寄存器前需发送控制指令进入该寄存器区域,进入 BANK0 区域需向传感器 0xEF 地址写 0x00,而 BANK1 区域需向传感器 0xEF 地址写 0x01。
2.59.3.3 挂起管理寄存器
该寄存器地址为 0X03,其中的 bit0 位用来控制挂起,设置该位为 1 即可使 PAJ7620 进入挂起状态。2.59.3.4 使能工作寄存器
该寄存器地址为 0X72,用于使能 PAJ7620 工作,bit0 位设置为 1 则使能 PAJ7620 工作,设置为 0 则失能 PAJ7620 工作。2.59.3.5 手势检测输出中断使能寄存器 1
该寄存器地址为 0X41,用于手势识别,bit0~bit7 位用于使能不同手势识别结果的中断输出,默认值为 0XFF,其中 bit0 位为“上”、bit1 位为“下”、bit2 位为“左”、bit3 位为“右”、bit4 位为“前”、bit5 位为“后”、bit6 位为“顺时针旋转”、而 bit7 位为“逆时针旋转”。若对应位设置为 1 则开启当检测到对应的手势识别时,会输出对应手势识别结果中断;若对应位设置为 0 则关闭手势识别结果中断。2.59.3.6 手势检测输出中断使能寄存器 2
该寄存器地址为 0X42,用于手势识别,寄存器默认值为 0XFF。bit0 位用于使能手势识别“挥动”的输出中断,该位设置为 1 则使能输出中断,设置为 0 则关闭输出中断。2.59.3.7 手势识别中断标志寄存器 1
该地址为 0X43,用于手势识别,实现手势识别输出结果的中断标志。当 BANK0 寄存器 0X41 使能了对应手势中断位后,当 PAJ7620U2 检测到内置的手势,则对应的寄存器手势标志会置 1,读取标志可清除对应的中断标志位。用户可以根据读取对应的状态得知当前手势识别的结果。2.59.3.8 手势识别中断标志寄存器 2
该地址为 0X44,用于手势识别,实现手势识别输出结果的中断标志,当 BANK0 寄存器 0X42 使能了“Wave”手势中断位后,PAJ7620U2 检测到“Wave”的手势,该寄存器 bit0 位会置 1,读取该标志可清除对应的中断标志位。用户可以根据读取对应的状态得知当前手势识别的结果。2.59.3.9 检测物体亮度寄存器
该地址为 0XB0,用于实现获取检测物体亮度值。在接近检测模式下,当物体在 PAJ7620U2 的有效检测距离内,读取该寄存器能获得物体的亮度,亮度值为 0~255。2.59.3.10 检测物体体积大小寄存器
该地址为 0XB2 和 0XB1,用于检测物体体积大小,其值由两个寄存器值组合而成,分别是为 0XB2 寄存器的低 4 位值和 0XB1 寄存器 8 位值。在接近检测下,当物体在 PAJ7620U2 的有效检测距离内,读取这两个寄存器能获得物体体积大小,体积值为 0~900。2.59.4 移植工程
2.59.4.1 引脚选择
PAJ7620U2 | 立创·梁山派 | 接线图 |
---|
2.59.4.2 移植步骤
本例程在 Hardware 文件夹下新建一个 PAJ7620U2 文件夹,在其中创建 5 个文件,分别为 paj7620u2_cfg.h、paj7620u2_iic.h、paj7620u2_iic.c、paj7620u2.h、paj7620u2.c,下面逐一介绍每个文件。
paj7620u2_cfg.h
该部分代码主要包含 3 个初始化的配置数组,分别为上电初始化、手势识别初始化和接近检测初始化,本质为二维数组,每个元素的第一个字节为寄存器地址,第二个字节为该地址下要写入的值。
数据手册的第 32-33 页为上电初始化的配置数组,第 35 页为手势识别初始化的配置数组,第 34 页为接近检测初始化的配置数组,直接复制即可,代码如下:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年09月01日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#ifndef __PAJ7620U2_CFG_H
#define __PAJ7620U2_CFG_H
// 上电初始化数组
const unsigned char init_Array[][2] = {
{ 0xEF, 0x00 },
{ 0x37, 0x07 },
{ 0x38, 0x17 },
{ 0x39, 0x06 },
{ 0x41, 0x00 },
{ 0x42, 0x00 },
{ 0x46, 0x2D },
{ 0x47, 0x0F },
{ 0x48, 0x3C },
{ 0x49, 0x00 },
{ 0x4A, 0x1E },
{ 0x4C, 0x20 },
{ 0x51, 0x10 },
{ 0x5E, 0x10 },
{ 0x60, 0x27 },
{ 0x80, 0x42 },
{ 0x81, 0x44 },
{ 0x82, 0x04 },
{ 0x8B, 0x01 },
{ 0x90, 0x06 },
{ 0x95, 0x0A },
{ 0x96, 0x0C },
{ 0x97, 0x05 },
{ 0x9A, 0x14 },
{ 0x9C, 0x3F },
{ 0xA5, 0x19 },
{ 0xCC, 0x19 },
{ 0xCD, 0x0B },
{ 0xCE, 0x13 },
{ 0xCF, 0x64 },
{ 0xD0, 0x21 },
{ 0xEF, 0x01 },
{ 0x02, 0x0F },
{ 0x03, 0x10 },
{ 0x04, 0x02 },
{ 0x25, 0x01 },
{ 0x27, 0x39 },
{ 0x28, 0x7F },
{ 0x29, 0x08 },
{ 0x3E, 0xFF },
{ 0x5E, 0x3D },
{ 0x65, 0x96 },
{ 0x67, 0x97 },
{ 0x69, 0xCD },
{ 0x6A, 0x01 },
{ 0x6D, 0x2C },
{ 0x6E, 0x01 },
{ 0x72, 0x01 },
{ 0x73, 0x35 },
{ 0x74, 0x00 },
{ 0x77, 0x01 },
};
// 手势识别初始化数组
const unsigned char gesture_arry[][2] = {
{ 0xEF, 0x00 },
{ 0x41, 0x00 },
{ 0x42, 0x00 },
{ 0xEF, 0x00 },
{ 0x48, 0x3C },
{ 0x49, 0x00 },
{ 0x51, 0x10 },
{ 0x83, 0x20 },
{ 0x9F, 0xF9 },
{ 0xEF, 0x01 },
{ 0x01, 0x1E },
{ 0x02, 0x0F },
{ 0x03, 0x10 },
{ 0x04, 0x02 },
{ 0x41, 0x40 },
{ 0x43, 0x30 },
{ 0x65, 0x96 },
{ 0x66, 0x00 },
{ 0x67, 0x97 },
{ 0x68, 0x01 },
{ 0x69, 0xCD },
{ 0x6A, 0x01 },
{ 0x6B, 0xB0 },
{ 0x6C, 0x04 },
{ 0x6D, 0x2C },
{ 0x6E, 0x01 },
{ 0x74, 0x00 },
{ 0xEF, 0x00 },
{ 0x41, 0xFF },
{ 0x42, 0x01 },
};
// 接近检测初始化数组
const unsigned char proximity_arry[][2] = {
{ 0xEF, 0x00 },
{ 0x41, 0x00 },
{ 0x42, 0x00 },
{ 0x48, 0x3C },
{ 0x49, 0x00 },
{ 0x51, 0x13 },
{ 0x83, 0x20 },
{ 0x84, 0x20 },
{ 0x85, 0x00 },
{ 0x86, 0x10 },
{ 0x87, 0x00 },
{ 0x88, 0x05 },
{ 0x89, 0x18 },
{ 0x8A, 0x10 },
{ 0x9f, 0xf8 },
{ 0x69, 0x96 },
{ 0x6A, 0x02 },
{ 0xEF, 0x01 },
{ 0x01, 0x1E },
{ 0x02, 0x0F },
{ 0x03, 0x10 },
{ 0x04, 0x02 },
{ 0x41, 0x50 },
{ 0x43, 0x34 },
{ 0x65, 0xCE },
{ 0x66, 0x0B },
{ 0x67, 0xCE },
{ 0x68, 0x0B },
{ 0x69, 0xE9 },
{ 0x6A, 0x05 },
{ 0x6B, 0x50 },
{ 0x6C, 0xC3 },
{ 0x6D, 0x50 },
{ 0x6E, 0xC3 },
{ 0x74, 0x05 },
};
#define INIT_SIZE sizeof(init_Array) / 2
#define GESTURE_SIZE sizeof(gesture_arry) / 2
#define PROXIM_SIZE sizeof(proximity_arry) / 2
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
paj7620u2_iic.h
该部分代码主要定义软仿 IIC 使用的接口及相关函数声明,代码如下:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年09月01日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#ifndef __PAJ7620U2_IIC_H
#define __PAJ7620U2_IIC_H
#include "gd32f4xx.h"
#include "sys.h"
#define RCU_SDA RCU_GPIOB
#define PORT_SDA GPIOB
#define PIN_SDA GPIO_PIN_14
#define RCU_SCL RCU_GPIOB
#define PORT_SCL GPIOB
#define PIN_SCL GPIO_PIN_15
#define GS_SDA_IN() \
{ \
GPIO_CTL(GPIOB) &= ~GPIO_MODE_MASK(14); \
GPIO_CTL(GPIOB) |= GPIO_MODE_SET(14, GPIO_MODE_INPUT); \
}
#define GS_SDA_OUT() \
{ \
GPIO_CTL(GPIOB) &= ~GPIO_MODE_MASK(14); \
GPIO_CTL(GPIOB) |= GPIO_MODE_SET(14, GPIO_MODE_OUTPUT); \
}
// IO操作函数
#define GS_IIC_SCL PBout(15) // SCL
#define GS_IIC_SDA PBout(14) // SDA
#define GS_READ_SDA PBin(14) // 输入SDA
uint8_t GS_Write_Byte(uint8_t REG_Address, uint8_t REG_data);
uint8_t GS_Read_Byte(uint8_t REG_Address);
uint8_t GS_Read_nByte(uint8_t REG_Address, uint16_t len, uint8_t *buf);
void GS_i2c_init(void);
void GS_WakeUp(void);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
paj7620u2_iic.c
该部分代码为软仿 IIC 的具体实现,主要包括引脚 IO 初始化、IIC 底层驱动读写函数及唤醒(WakeUp)命令函数。
其中,数据手册的第 21 页描述了由挂起态至运行态的操作,如下图所示,首先通过 SlaveAddr 发送 WakeUp 命令,然后使能 PAJ7620U2 即可。
WakeUp 命令操作见数据手册的第 25 页时序图,只需向地址发送写命令,无需等待回复即可,如下图所示。
具体代码如下:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年09月01日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#include "paj7620u2.h"
#include "paj7620u2_iic.h"
#include "systick.h"
// PAJ2670U2 I2C初始化
void GS_i2c_init(void)
{
/* 使能时钟 */
rcu_periph_clock_enable(RCU_SDA);
rcu_periph_clock_enable(RCU_SCL);
/* 配置为输出模式 浮空模式 */
gpio_mode_set(PORT_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, PIN_SDA);
gpio_mode_set(PORT_SCL, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, PIN_SCL);
/* 配置为推挽输出 50MHZ */
gpio_output_options_set(PORT_SDA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, PIN_SDA);
gpio_output_options_set(PORT_SCL, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, PIN_SCL);
/* SDA SCL输出高 */
GS_IIC_SDA = 1;
GS_IIC_SCL = 1;
}
// 产生IIC起始信号
static void GS_IIC_Start(void)
{
GS_SDA_OUT(); // sda线输出
GS_IIC_SDA = 1;
GS_IIC_SCL = 1;
delay_us(4);
GS_IIC_SDA = 0; // START:when CLK is high,DATA change form high to low
delay_us(4);
GS_IIC_SCL = 0; // 钳住I2C总线,准备发送或接收数据
}
// 产生IIC停止信号
static void GS_IIC_Stop(void)
{
GS_SDA_OUT(); // sda线输出
GS_IIC_SCL = 0;
GS_IIC_SDA = 0; // STOP:when CLK is high DATA change form low to high
delay_us(4);
GS_IIC_SCL = 1;
GS_IIC_SDA = 1; // 发送I2C总线结束信号
delay_us(4);
}
// 等待应答信号到来
// 返回值:1,接收应答失败
// 0,接收应答成功
static uint8_t GS_IIC_Wait_Ack(void)
{
uint8_t ucErrTime = 0;
GS_SDA_IN(); // SDA设置为输入
GS_IIC_SDA = 1;
delay_us(3);
GS_IIC_SCL = 1;
delay_us(3);
while(GS_READ_SDA)
{
ucErrTime++;
if(ucErrTime > 250)
{
GS_IIC_Stop();
return 1;
}
}
GS_IIC_SCL = 0; // 时钟输出0
return 0;
}
// 产生ACK应答
static void GS_IIC_Ack(void)
{
GS_IIC_SCL = 0;
GS_SDA_OUT();
GS_IIC_SDA = 0;
delay_us(3);
GS_IIC_SCL = 1;
delay_us(3);
GS_IIC_SCL = 0;
}
// 不产生ACK应答
static void GS_IIC_NAck(void)
{
GS_IIC_SCL = 0;
GS_SDA_OUT();
GS_IIC_SDA = 1;
delay_us(2);
GS_IIC_SCL = 1;
delay_us(2);
GS_IIC_SCL = 0;
}
// IIC发送一个字节
// 返回从机有无应答
// 1,有应答
// 0,无应答
static void GS_IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
GS_SDA_OUT();
GS_IIC_SCL = 0; // 拉低时钟开始数据传输
for(t = 0; t < 8; t++)
{
if((txd & 0x80) >> 7)
GS_IIC_SDA = 1;
else
GS_IIC_SDA = 0;
txd <<= 1;
delay_us(5);
GS_IIC_SCL = 1;
delay_us(5);
GS_IIC_SCL = 0;
delay_us(5);
}
}
// 读1个字节,ack=1时,发送ACK,ack=0,发送nACK
static uint8_t GS_IIC_Read_Byte(uint8_t ack)
{
uint8_t i, receive = 0;
GS_SDA_IN(); // SDA设置为输入
for(i = 0; i < 8; i++)
{
GS_IIC_SCL = 0;
delay_us(4);
GS_IIC_SCL = 1;
receive <<= 1;
if(GS_READ_SDA)
receive++;
delay_us(4);
}
if(!ack)
GS_IIC_NAck(); // 发送nACK
else
GS_IIC_Ack(); // 发送ACK
return receive;
}
// PAJ7620U2写一个字节数据
uint8_t GS_Write_Byte(uint8_t REG_Address, uint8_t REG_data)
{
GS_IIC_Start();
GS_IIC_Send_Byte(PAJ7620_ID);
if(GS_IIC_Wait_Ack())
{
GS_IIC_Stop(); // 释放总线
return 1; // 没应答则退出
}
GS_IIC_Send_Byte(REG_Address);
GS_IIC_Wait_Ack();
GS_IIC_Send_Byte(REG_data);
GS_IIC_Wait_Ack();
GS_IIC_Stop();
return 0;
}
// PAJ7620U2读一个字节数据
uint8_t GS_Read_Byte(uint8_t REG_Address)
{
uint8_t REG_data;
GS_IIC_Start();
GS_IIC_Send_Byte(PAJ7620_ID); // 发写命令
if(GS_IIC_Wait_Ack())
{
GS_IIC_Stop(); // 释放总线
return 0; // 没应答则退出
}
GS_IIC_Send_Byte(REG_Address);
GS_IIC_Wait_Ack();
GS_IIC_Start();
GS_IIC_Send_Byte(PAJ7620_ID | 0x01); // 发读命令
GS_IIC_Wait_Ack();
REG_data = GS_IIC_Read_Byte(0);
GS_IIC_Stop();
return REG_data;
}
// PAJ7620U2读n个字节数据
uint8_t GS_Read_nByte(uint8_t REG_Address, uint16_t len, uint8_t *buf)
{
GS_IIC_Start();
GS_IIC_Send_Byte(PAJ7620_ID); // 发写命令
if(GS_IIC_Wait_Ack())
{
GS_IIC_Stop(); // 释放总线
return 1; // 没应答则退出
}
GS_IIC_Send_Byte(REG_Address);
GS_IIC_Wait_Ack();
GS_IIC_Start();
GS_IIC_Send_Byte(PAJ7620_ID | 0x01); // 发读命令
GS_IIC_Wait_Ack();
while(len)
{
if(len == 1)
{
*buf = GS_IIC_Read_Byte(0);
}
else
{
*buf = GS_IIC_Read_Byte(1);
}
buf++;
len--;
}
GS_IIC_Stop(); // 释放总线
return 0;
}
// PAJ7620唤醒
void GS_WakeUp(void)
{
GS_IIC_Start();
GS_IIC_Send_Byte(PAJ7620_ID); // 发写命令
GS_IIC_Stop(); // 释放总线
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
paj7620u2.h
该部分代码为模块寄存器、手势识别效果等的宏定义声明及函数声明。
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年09月01日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#ifndef __PAJ7620U2_H
#define __PAJ7620U2_H
#include "paj7620u2_iic.h"
// BANK寄存器枚举
typedef enum
{
BANK0 = 0, // BANK0寄存器
BANK1, // BANK1寄存器
} bank_e;
#define PAJ7620_ID 0x73 << 1 // 设备地址
#define PAJ_REGITER_BANK_SEL 0XEF // BANK选择寄存器
#define PAJ_BANK0 0X00 // BANK0
#define PAJ_BANK1 0X01 // BANK1
// BANK0 寄存器组
#define PAJ_SUSPEND_CMD 0X03 // 设置设备挂起
#define PAJ_SET_INT_FLAG1 0X41 // 设置手势检测中断寄存器1
#define PAJ_SET_INT_FLAG2 0X42 // 设置手势检测中断寄存器2
#define PAJ_GET_INT_FLAG1 0X43 // 获取手势检测中断标志寄存器1(获取手势结果)
#define PAJ_GET_INT_FLAG2 0X44 // 获取手势检测中断标志寄存器2(获取手势结果)
#define PAJ_GET_STATE 0X45 // 获取手势检测工作状态
#define PAJ_SET_HIGH_THRESHOLD 0x69 // 设置滞后高阀值(仅在接近检测模式下)
#define PAJ_SET_LOW_THRESEHOLD 0X6A // 设置滞后低阀值
#define PAJ_GET_APPROACH_STATE 0X6B // 获取接近状态 (1:PS data>= PS threshold ,0:PS data<= Low threshold)
#define PAJ_GET_GESTURE_DATA 0X6C // 获取接近数据
#define PAJ_GET_OBJECT_BRIGHTNESS 0XB0 // 获取被照物体亮度(最大255)
#define PAJ_GET_OBJECT_SIZE_1 0XB1 // 获取被照物体大小低八位(bit7:0)(最大900)
#define PAJ_GET_OBJECT_SIZE_2 0XB2 // 获取被照物体大小高四位(bit3:0)
// BANK1 寄存器组
#define PAJ_SET_PS_GAIN 0X44 // 设置检测增益大小 (0:1x gain 1:2x gain)
#define PAJ_SET_IDLE_S1_STEP_0 0x67 // 设置S1的响应因子
#define PAJ_SET_IDLE_S1_STEP_1 0x68
#define PAJ_SET_IDLE_S2_STEP_0 0X69 // 设置S2的响应因子
#define PAJ_SET_IDLE_S2_STEP_1 0X6A
#define PAJ_SET_OP_TO_S1_STEP_0 0X6B // 设置OP到S1的过度时间
#define PAJ_SET_OP_TO_S1_STEP_1 0X6C
#define PAJ_SET_S1_TO_S2_STEP_0 0X6D // 设置S1到S2的过度时间
#define PAJ_SET_S1_TO_S2_STEP_1 0X6E
#define PAJ_OPERATION_ENABLE 0X72 // 设置PAJ7620U2使能寄存器
// 手势识别效果
#define PAJ_BIT(x) 1 << (x)
#define GES_UP PAJ_BIT(0) // 向上
#define GES_DOWM PAJ_BIT(1) // 向下
#define GES_LEFT PAJ_BIT(2) // 向左
#define GES_RIGHT PAJ_BIT(3) // 向右
#define GES_FORWARD PAJ_BIT(4) // 向前
#define GES_BACKWARD PAJ_BIT(5) // 向后
#define GES_CLOCKWISE PAJ_BIT(6) // 顺时针
#define GES_COUNT_CLOCKWISE PAJ_BIT(7) // 逆时针
#define GES_WAVE PAJ_BIT(8) // 挥动
uint8_t paj7620u2_init(void);
void paj7620u2_selectBank(bank_e bank);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
paj7620u2.c
该部分代码包含 BANK 区域的切换、PAJ7620U2 唤醒及 PAJ7620U2 初始化函数。
唤醒操作参考的是数据手册第 32 页第一部分,唤醒器件需要三个步骤:1.等待 700us 至器件稳定;2.通过 SlaveAddr 发送 WakeUp 命令;3.读取 0x00 寄存器,如果返回 0x20 则代表唤醒成功。
具体代码如下:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年09月01日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#include "systick.h"
#include "paj7620u2.h"
#include "paj7620u2_cfg.h"
// 选择PAJ7620U2 BANK区域
void paj7620u2_selectBank(bank_e bank)
{
switch(bank)
{
case BANK0:
GS_Write_Byte(PAJ_REGITER_BANK_SEL, PAJ_BANK0);
break; // BANK0寄存器区域
case BANK1:
GS_Write_Byte(PAJ_REGITER_BANK_SEL, PAJ_BANK1);
break; // BANK1寄存器区域
}
}
// PAJ7620U2唤醒
uint8_t paj7620u2_wakeup(void)
{
uint8_t data = 0x0a;
// GS_WakeUp(); // 唤醒PAJ7620U2
delay_ms(5); // 唤醒时间>700us
GS_WakeUp(); // 唤醒PAJ7620U2
delay_ms(5); // 唤醒时间>700us
paj7620u2_selectBank(BANK0); // 进入BANK0寄存器区域
data = GS_Read_Byte(0x00); // 读取状态
if(data != 0x20)
return 0; // 唤醒失败
return 1;
}
// PAJ7620U2初始化
// 返回值:0:失败 1:成功
uint8_t paj7620u2_init(void)
{
uint8_t i;
uint8_t status;
GS_i2c_init(); // IIC初始化
status = paj7620u2_wakeup(); // 唤醒PAJ7620U2
if(!status)
return 0;
paj7620u2_selectBank(BANK0); // 进入BANK0寄存器区域
for(i = 0; i < INIT_SIZE; i++)
{
GS_Write_Byte(init_Array[i][0], init_Array[i][1]); // 初始化PAJ7620U2
}
paj7620u2_selectBank(BANK0); // 切换回BANK0寄存器区域
delay_ms(500);
paj7620u2_selectBank(BANK0); // 进入BANK0寄存器区域
for(i = 0; i < GESTURE_SIZE; i++)
{
GS_Write_Byte(gesture_arry[i][0], gesture_arry[i][1]); // 手势识别模式初始化
}
paj7620u2_selectBank(BANK0); // 切换回BANK0寄存器区域
return 1;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
注:要实现接近检测功能时,只需将 paj7620u2_init()函数中的
for(i = 0; i < GESTURE_SIZE; i++)
{
GS_Write_Byte(gesture_arry[i][0], gesture_arry[i][1]); // 手势识别模式初始化
}
2
3
4
修改为以下代码即可。
for(i = 0; i < PROXIM_SIZE; i++)
{
GS_Write_Byte(proximity_arry[i][0], proximity_arry[i][1]); // 接近检测模式初始化
}
2
3
4
2.59.5 移植验证
2.59.5.1 手势识别验证
注:传感器放置方式如下图所示(将其平行于桌面放置,有窗口的一端朝向前方)。
在 main.c 中的 while(1)中增加以下代码,测试手势识别结果。
while(1)
{
status = GS_Read_nByte(PAJ_GET_INT_FLAG1, 2, &data[0]); // 读取手势状态
if(!status)
{
gesture_data = (uint16_t)data[1] << 8 | data[0];
if(gesture_data)
{
switch(gesture_data)
{
case GES_UP: // 向上
printf("Up\r\n");
break;
case GES_DOWM: // 向下
printf("Down\r\n");
break;
case GES_LEFT: // 向左
printf("Left\r\n");
break;
case GES_RIGHT: // 向右
printf("Right\r\n");
break;
case GES_FORWARD: // 向前
printf("Forward\r\n");
break;
case GES_BACKWARD: // 向后
printf("Backward\r\n");
break;
case GES_CLOCKWISE: // 顺时针
printf("Clockwise\r\n");
break;
case GES_COUNT_CLOCKWISE: // 逆时针
printf("AntiClockwise\r\n");
break;
case GES_WAVE: // 挥动
printf("Wave\r\n");
break;
default:
break;
}
}
}
delay_ms(50);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
将 DAP-Link 连接至电脑 USB 接口,打开串口调试助手,编译代码下载到梁山派开发板后,运行代码,观察串口调试助手打印信息,出现“PAJ7620U2 Init OK”即为初始化成功。
将手放置在传感器的上方,保持与传感器的垂直距离,分别做出向上、向下、向左、向右、挥手等操作,观察串口打印,是否出现一致结果。
注:顺时针旋转和逆时针旋转可能会被误识别,多尝试几次即可,若想识别精度高则需要增加相关算法加以判断处理。
移植成功代码见下文件。
2.59.5.2 物体检测验证
在 main.c 中的 while(1)中增加以下代码,测试手势识别结果。
while(1)
{
obj_brightness = GS_Read_Byte(PAJ_GET_OBJECT_BRIGHTNESS); // 读取物体亮度
data[0] = GS_Read_Byte(PAJ_GET_OBJECT_SIZE_1); // 读取物体大小低字节
data[1] = GS_Read_Byte(PAJ_GET_OBJECT_SIZE_2); // 读取物体大小高字节
obj_size = ((uint16_t)data[1] & 0x0f) << 8 | data[0];
printf("obj_brightness: %d\r\n", obj_brightness);
printf("obj_size: %d\r\n", obj_size);
delay_ms(500);
}
2
3
4
5
6
7
8
9
10
11
同 5.1,编译下载代码后,观察串口调试助手打印信息,出现“PAJ7620U2 Init OK”即为初始化成功。
将手放置在传感器的上方,当手在模块上方动作时,串口会打印当前测量的亮度值和体积值。
移植成功代码见下文件。