简介:Gesture_PAJ7620-master.zip 是一份面向 Arduino 与开源硬件爱好者的 PAJ7620 手势识别传感器驱动库,适合具备一定 I2C 与嵌入式基础、希望快速将手势交互引入项目的开发者。PAJ7620U2 将手势识别与通用 I2C 接口集成于单芯片,可识别 9 种基本手势,通过 I2C 总线即可读取手势信息,常用于控制执行单元、计算机、手机、智能车或机器人等设备。压缩包共 8 个文件,约 12KB,包含 2 个 ino 示例、cpp 与 h 驱动源码、keywords.txt 关键字文件、library.properties 库描述、README.md 说明及 LICENSE 授权文件,示例覆盖 9 种与 15 种手势两种演示场景,便于直接编译验证。目前已有 724 人学习下载。借助该库,读者可省去底层寄存器调试,快速完成传感器初始化、手势读取与串口输出,并在此基础上扩展手势控制逻辑,是入门手势识别与交互项目的实用参考。
1. 手势识别模块 PAJ7620 上手:从一颗传感器到一套可跑的手势交互原型
如果你手上正好有一块 PAJ7620 手势识别传感器,又不想从零啃数据手册,那这份Gesture_PAJ7620-master.zip基本就是为你准备的。它把传感器初始化、手势方向解析、串口输出和示例交互逻辑打包成了一个可以直接编译烧录的工程,属于开源硬件圈里比较典型的“拿到就能跑”的 Arduino 项目。PAJ7620 本身是一颗集成红外 LED 和图像传感器的模块,能识别上、下、左、右、前、后、顺时针、逆时针以及挥手等动作,I2C 接口,3.3V 供电,接线不复杂。这个项目适合做非接触控制、互动装置、教学演示的开发者,尤其是想快速验证手势交互可行性、再决定要不要深入做产品化的人。下面我按“先看清结构、再跑通、最后能改”的顺序,把这份源码拆开讲一遍。
2. 工程结构与硬件链路:先搞清传感器怎么接、代码怎么分层
2.1 目录里有什么,各自负责哪一段
拿到压缩包解压后,根目录通常是一个 Arduino 风格的工程文件夹,里面至少包含主程序.ino文件、PAJ7620 的驱动库文件夹,以及若干示例。常见结构如下:
Gesture_PAJ7620-master/ ├── Gesture_PAJ7620.ino # 主程序,负责初始化和循环读取 ├── PAJ7620U2.cpp # 传感器驱动实现 ├── PAJ7620U2.h # 寄存器定义、类声明 ├── examples/ # 示例程序,通常按功能分 │ ├── Gesture_Test/ │ └── Gesture_Control/ └── README.md # 接线和依赖说明主程序只做三件事:初始化串口、初始化传感器、在loop()里轮询手势结果。驱动层把 I2C 读写、寄存器配置、手势标志位解析封装成类方法,这样上层不需要关心 0x43 还是 0x44 寄存器。示例目录里一般会有一个最简测试程序和一个带控制逻辑的程序,前者用来确认硬件没问题,后者用来演示怎么把手势映射成具体动作。
2.2 接线与供电:别在 5V 上翻车
PAJ7620 模块的典型接线是四根线:VCC、GND、SDA、SCL。这里有一个血泪经验:模块标称支持 3.3V,但很多国产小板子上带了稳压和电平转换,实际可以接 5V;如果你手里的是裸芯片或者没有电平转换的版本,直接上 5V 大概率会烧。稳妥做法是先看模块背面丝印,有5V标注的再接 5V,否则统一用 3.3V。
I2C 引脚在 Arduino Uno 上是 A4(SDA)和 A5(SCL),在 ESP32 上可以自定义。接线时注意 SDA 和 SCL 不要接反,接反了表现为Wire.begin()之后读不到设备地址,串口一直打印初始化失败。常见做法是先用 I2C 扫描程序确认地址,PAJ7620 的 7 位地址通常是0x73。
#include <Wire.h> void setup() { Wire.begin(); Serial.begin(9600); Serial.println("I2C scanning..."); for (byte addr = 1; addr < 127; addr++) { Wire.beginTransmission(addr); if (Wire.endTransmission() == 0) { Serial.print("Found device at 0x"); Serial.println(addr, HEX); } } } void loop() {}这段扫描代码不依赖任何驱动库,用来排除接线和供电问题。如果扫不到0x73,先查线,再查电压,最后才怀疑模块本身。参数上,Wire.begin()不带参数时使用默认引脚,ESP32 可以写成Wire.begin(SDA_PIN, SCL_PIN)。
2.3 驱动初始化:寄存器配置不是玄学
PAJ7620 上电后需要写一批寄存器才能进入手势识别模式。驱动里通常有一个init()方法,内部按数据手册的流程走:先唤醒,再设置手势使能,最后配置中断或轮询模式。下面是从驱动中摘出来的典型初始化片段:
bool PAJ7620U2::init() { // 软复位,等待传感器稳定 writeRegister(PAJ7620_ADDR_CMD, 0x00); delay(10); // 选择手势识别模式 writeRegister(PAJ7620_ADDR_MODE, 0x00); delay(10); // 使能全部手势,具体位定义见头文件 writeRegister(PAJ7620_ADDR_GESTURE_ENABLE, 0xFF); delay(10); // 读取一次状态,确认配置生效 uint8_t status = readRegister(PAJ7620_ADDR_STATUS); return (status & 0x01) == 0x01; }writeRegister和readRegister内部就是标准的 I2C 读写,地址是 7 位地址左移一位。PAJ7620_ADDR_GESTURE_ENABLE写0xFF表示打开所有手势,如果你只想识别左右,可以改成0x0C之类的掩码。初始化失败时,init()返回false,主程序里一般会卡在while(1)并打印错误,这时候优先检查供电和 I2C 上拉电阻。很多模块自带上拉,但如果你用长杜邦线,上拉不够会导致通信不稳定,表现是偶尔能读到数据、偶尔失败。
3. 核心逻辑拆解:手势数据怎么读、怎么解析、怎么用
3.1 轮询读取与手势标志位
PAJ7620 的手势结果放在一个寄存器里,读一次得到一个字节,不同位代表不同手势。驱动层通常会提供一个readGesture()方法,返回一个枚举或者位掩码。主程序里最常见的写法是:
void loop() { uint8_t gesture = sensor.readGesture(); if (gesture != 0) { switch (gesture) { case GESTURE_UP: Serial.println("Up"); break; case GESTURE_DOWN: Serial.println("Down"); break; case GESTURE_LEFT: Serial.println("Left"); break; case GESTURE_RIGHT: Serial.println("Right"); break; case GESTURE_CLOCKWISE: Serial.println("Clockwise"); break; case GESTURE_WAVE: Serial.println("Wave"); break; default: break; } } delay(50); // 轮询间隔,太短会重复触发 }这里的关键参数是delay(50)。PAJ7620 识别一次手势大约需要几十毫秒,轮询太快会读到重复标志位,表现为一次挥手串口打印好几行。我一般会设 50 到 100 毫秒,具体看你的交互节奏。另外,readGesture()内部通常会先读状态寄存器,确认有新手势再读数据寄存器,避免读到旧值。
3.2 手势映射成控制指令
拿到手势之后,下一步是把它映射成具体动作。示例里常见的是控制 LED 或者舵机。下面这段代码把左右手势映射成两个 LED 的开关:
const int LED_LEFT = 8; const int LED_RIGHT = 9; void handleGesture(uint8_t gesture) { switch (gesture) { case GESTURE_LEFT: digitalWrite(LED_LEFT, !digitalRead(LED_LEFT)); // 翻转状态 break; case GESTURE_RIGHT: digitalWrite(LED_RIGHT, !digitalRead(LED_RIGHT)); break; case GESTURE_WAVE: // 挥手全部熄灭 digitalWrite(LED_LEFT, LOW); digitalWrite(LED_RIGHT, LOW); break; default: break; } }digitalRead读当前状态再取反,实现“挥一次开、再挥一次关”。如果你要控制舵机,把digitalWrite换成servo.write(angle)并维护一个角度变量即可。注意手势识别有误触发概率,尤其是环境红外干扰强的时候,所以重要操作最好加一个确认手势,比如连续两次同方向才执行。
3.3 串口调试与数据观察
调试阶段最有用的是把原始寄存器值打出来。驱动里可以加一个debug()方法,把手势字节以二进制形式打印:
void PAJ7620U2::debugPrint() { uint8_t raw = readRegister(PAJ7620_ADDR_GESTURE_RESULT); Serial.print("Raw gesture: 0b"); for (int i = 7; i >= 0; i--) { Serial.print((raw >> i) & 0x01); } Serial.println(); }这样你能看到具体是哪一位被置位,对照头文件里的宏定义就能确认识别结果是否符合预期。如果发现某一位一直置位,可能是传感器被固定光源干扰,尝试调整模块朝向或者加遮光罩。串口波特率一般用 9600 或 115200,和主程序保持一致即可。
4. 避坑与常见问题:接线、供电、误触发、库冲突
4.1 初始化失败,串口一直打印错误
现象是上传程序后串口没有任何手势输出,只有初始化失败提示。原因通常是 I2C 通信没建立,可能是 SDA/SCL 接反、供电不足、或者模块损坏。解决步骤:先用 2.2 节的扫描程序确认地址;如果扫不到,用万用表量 VCC 和 GND 之间电压,低于 3.0V 就换供电;都正常再换一个模块测试。注意有些开发板的 I2C 引脚默认被其他外设占用,比如某些 ESP32 板子,需要改引脚定义。
4.2 手势重复触发,一次动作打印多次
现象是挥一次手,串口连续输出好几行同样的手势。原因是轮询间隔太短,传感器还没清标志位就被再次读取。解决办法是在loop()里加delay(50)以上,或者在驱动里读完之后手动清一次状态寄存器。我一般会在readGesture()返回非零后延时 100 毫秒再继续轮询,这样基本不会重复。
4.3 环境光干扰导致误识别
现象是没人动手,串口偶尔蹦出一个手势。原因是 PAJ7620 靠红外反射工作,阳光、白炽灯、其他红外遥控器都可能干扰。解决方法是调整模块安装角度,避免正对光源;或者在软件里加连续确认,比如连续三次读到同一手势才认为是有效输入。常见做法是加一个简单的计数器:
uint8_t lastGesture = 0; uint8_t count = 0; void loop() { uint8_t g = sensor.readGesture(); if (g == lastGesture && g != 0) { count++; if (count >= 3) { handleGesture(g); count = 0; } } else { lastGesture = g; count = 0; } delay(50); }4.4 库冲突导致编译报错
现象是编译时提示Wire.h重复定义或者PAJ7620U2未声明。原因可能是你同时装了多个 I2C 库,或者驱动文件没有放在工程根目录。解决方法是确认PAJ7620U2.cpp和.h与.ino在同一级目录,或者放在libraries文件夹下。Arduino IDE 对文件夹结构比较敏感,.ino文件名必须和文件夹名一致,否则会报找不到主程序。
4.5 供电不足导致识别距离变短
现象是手势要贴得很近才能识别,稍微远一点就没反应。原因是模块供电电流不够,红外 LED 发射功率下降。解决方法是不要用开发板的 3.3V 引脚直接供电,改用外部 3.3V 稳压电源,或者确认开发板 3.3V 输出能提供至少 100mA。USB 供电时也要注意线材质量,劣质线压降大,同样影响识别距离。
5. 二次开发与改造:从示例到自己的交互逻辑
5.1 增加新手势映射和组合逻辑
示例里通常只处理了基本方向,你可以扩展成组合手势。比如“先左后右”触发一个特定动作,实现方式是维护一个手势序列缓冲区:
#define SEQ_LEN 4 uint8_t seq[SEQ_LEN]; uint8_t idx = 0; void pushGesture(uint8_t g) { seq[idx % SEQ_LEN] = g; idx++; // 检查最近两个手势是否为左+右 if (idx >= 2) { uint8_t prev = seq[(idx - 2) % SEQ_LEN]; if (prev == GESTURE_LEFT && g == GESTURE_RIGHT) { Serial.println("Combo: Left then Right"); // 执行你的组合动作 } } }这个缓冲区长度可以根据需要调整,SEQ_LEN越大能识别的组合越长,但误触发概率也越高。我一般用 4 个长度,配合 300 毫秒内的时间窗口,超过时间就清空序列。
5.2 把串口输出改成无线通信
如果你用的是 ESP32 或 ESP8266,可以把串口打印换成 Wi-Fi 或蓝牙发送。以 ESP32 为例,用BLEKeyboard库把手势映射成键盘按键,就能做非接触翻页器。改造时只需要把handleGesture里的Serial.println换成bleKeyboard.write(KEY_RIGHT_ARROW)之类的调用。注意蓝牙库会占用大量内存,PAJ7620 的 I2C 通信要放在单独的 task 里,避免阻塞。
5.3 降低功耗用于电池供电
如果要做便携设备,功耗是绕不开的。PAJ7620 支持低功耗模式,通过写特定寄存器可以让它在无手势时休眠。驱动里可以加一个sleep()和wakeup()方法,主程序在空闲一段时间后调用。唤醒方式可以是定时轮询或者外部中断。常见做法是每 500 毫秒唤醒一次读一次手势,其余时间让 MCU 也进入轻睡眠,这样整体电流能降到毫安级。
5.4 验证改造是否成功的三个检查点
改完之后不要直接上整机,按这三个点验证:第一,用原始示例确认硬件和接线没动过;第二,在新逻辑里加串口日志,确认手势解析结果和预期一致;第三,用连续操作测试边界情况,比如快速挥手、慢速挥手、手停在传感器前不动。我自己的习惯是每次改完驱动层,都强制走一遍 I2C 扫描和原始数据打印,确认底层没被改坏。从那以后我每次动传感器相关代码,都先把原始数据打出来看一眼,这个习惯帮我省了很多返工时间。希望帮到你。
本文还有配套的精品资源,点击获取