手势传感器模块https://wiki.seeedstudio.com/Grove-Gesture_v1.0/
PAJ7620U2 Gesture Sensor是一款基于PAJ7620U2的手势识别模块,可直接识别9种基本手势,支持I2C接口,兼容3.3V/5V电平。
特点
基于PAJ7620U2传感器,可直接识别9种基本手势,支持手势中断输出
内置红外LED和光学镜头,能在低光和黑暗环境下工作
支持I2C接口通信,仅需两根信号脚即可控制
板载电平转换电路,可兼容3.3V/5V的逻辑电平
产品参数
工作电压:3.3V/5V
通信接口:I2C
识别距离:5CM ~ 15CM
识别手势:上、下、左、右、前、后、顺时针、逆时针、摇摆
速度:240HZ
识别视角:60° (对角线)
环境光免疫力:<100K LUX
产品尺寸:20MM × 20MM
过孔直径:2.0MM
应用场景:智能家居、办公室和教学;机器人交互、手势玩具、体感游戏装备
接口说明
引脚功能
引脚号 标识 管脚描述
1 GND 电源地
2 VCC 3.3V/5V电源正
3 SDA I2C数据线
4 SCL I2C时钟线
选择开发板上的i2c1接口
stm32cube的配置
驱动代码
#ifndef _PAJ7620U2_ #define _PAJ7620U2_ //i2c address #define PAJ7620U2_I2C_ADDRESS 0x73<<1 //Register Bank select #define PAJ_BANK_SELECT 0xEF /*Bank0=0x00,Bank1=0x01*/ //Register Bank 0 #define PAJ_SUSPEND 0x03 /*I2C suspend command (Write 0x01 to enter suspend state). I2C wake-up command is slave ID wake-up. Refer to topic “I2C Bus Timing Characteristics and Protocol”*/ #define PAJ_INT_FLAG1_MASK 0x41 /*Gesture detection interrupt flag mask*/ #define PAJ_INT_FLAG2_MASK 0x42 /*Gesture/PS detection interrupt flag mask*/ #define PAJ_INT_FLAG1 0x43 /*Gesture detection interrupt flag*/ #define PAJ_INT_FLAG2 0x44 /*Gesture/PS detection interrupt flag*/ #define PAJ_STATE 0x45 /*State indicator for gesture detection (Only functional at gesture detection mode)*/ #define PAJ_PS_HIGH_THRESHOLD 0x69 /*PS hysteresis high threshold (Only functional at proximity detection mode)*/ #define PAJ_PS_LOW_THRESHOLD 0x6A /*PS hysteresis low threshold (Only functional at proximity detection mode)*/ #define PAJ_PS_APPROACH_STATE 0x6B /*PS approach state, Approach = 1 , (8 bits PS data >= PS high threshold), Not Approach = 0 , (8 bits PS data <= PS low threshold)(Only functional at proximity detection mode)*/ #define PAJ_PS_DATA 0x6C /*PS 8 bit data(Only functional at gesture detection mode)*/ #define PAJ_OBJ_BRIGHTNESS 0xB0 /*Object Brightness (Max. 255)*/ #define PAJ_OBJ_SIZE_L 0xB1 /*Object Size(Low 8 bit)*/ #define PAJ_OBJ_SIZE_H 0xB2 /*Object Size(High 8 bit)*/ //Register Bank 1 #define PAJ_PS_GAIN 0x44 /*PS gain setting (Only functional at proximity detection mode)*/ #define PAJ_IDLE_S1_STEP_L 0x67 /*IDLE S1 Step, for setting the S1, Response Factor(Low 8 bit)*/ #define PAJ_IDLE_S1_STEP_H 0x68 /*IDLE S1 Step, for setting the S1, Response Factor(High 8 bit)*/ #define PAJ_IDLE_S2_STEP_L 0x69 /*IDLE S2 Step, for setting the S2, Response Factor(Low 8 bit)*/ #define PAJ_IDLE_S2_STEP_H 0x6A /*IDLE S2 Step, for setting the S2, Response Factor(High 8 bit)*/ #define PAJ_OPTOS1_TIME_L 0x6B /*OPtoS1 Step, for setting the OPtoS1 time of operation state to standby 1 state(Low 8 bit)*/ #define PAJ_OPTOS2_TIME_H 0x6C /*OPtoS1 Step, for setting the OPtoS1 time of operation state to standby 1 stateHigh 8 bit)*/ #define PAJ_S1TOS2_TIME_L 0x6D /*S1toS2 Step, for setting the S1toS2 time of standby 1 state to standby 2 state(Low 8 bit)*/ #define PAJ_S1TOS2_TIME_H 0x6E /*S1toS2 Step, for setting the S1toS2 time of standby 1 state to standby 2 stateHigh 8 bit)*/ #define PAJ_EN 0x72 /*Enable/Disable PAJ7620U2*/ //Gesture detection interrupt flag #define PAJ_UP 0x01 #define PAJ_DOWN 0x02 #define PAJ_LEFT 0x04 #define PAJ_RIGHT 0x08 #define PAJ_FORWARD 0x10 #define PAJ_BACKWARD 0x20 #define PAJ_CLOCKWISE 0x40 #define PAJ_COUNT_CLOCKWISE 0x80 #define PAJ_WAVE 0x100 //Initialize array size #define Init_Array sizeof(Init_Register_Array)/2 #define PS_Array_SIZE sizeof(Init_PS_Array)/2 #define Gesture_Array_SIZE sizeof(Init_Gesture_Array)/2 //Power up initialize array const unsigned char Init_Register_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}, }; //Approaches register initialization array const unsigned char Init_PS_Array[][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}, }; //Gesture register initializes array const unsigned char Init_Gesture_Array[][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}, }; #endif
实现
/***************************************************************************** * | File : DEV_Config.c * | Author : Waveshare team * | Function : Hardware underlying interface * | Info : * Used to shield the underlying layers of each master * and enhance portability *---------------- * | This version: V1.0 * | Date : 2018-11-22 * | Info : # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documnetation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # ******************************************************************************/ #include "DEV_Config.h" UWORD IIC_Addr_t = IIC_Addr; void DEV_Set_I2CAddress(UBYTE add_) { IIC_Addr_t = add_; } /****************************************************************************** function: I2C Write and Read ******************************************************************************/ void DEV_I2C_WriteByte(UBYTE add_, UBYTE data_) { UBYTE Buf[1] = {0}; Buf[0] = data_; HAL_I2C_Mem_Write(&hi2c1, IIC_Addr_t, add_, I2C_MEMADD_SIZE_8BIT, Buf, 1, 0x10); } void DEV_I2C_WriteWord(UBYTE add_, UWORD data_) { UBYTE Buf[2] = {0}; Buf[0] = data_ >> 8; Buf[1] = data_; HAL_I2C_Mem_Write(&hi2c1, IIC_Addr_t, add_, I2C_MEMADD_SIZE_8BIT, Buf, 2, 0x10); } UBYTE DEV_I2C_ReadByte(UBYTE add_) { UBYTE Buf[1]={add_}; HAL_I2C_Mem_Read(&hi2c1, IIC_Addr_t, add_, I2C_MEMADD_SIZE_8BIT, Buf, 1, 0x10); return Buf[0]; } UWORD DEV_I2C_ReadWord(UBYTE add_) { UBYTE Buf[2]={0, 0}; HAL_I2C_Mem_Read(&hi2c1, IIC_Addr_t, add_, I2C_MEMADD_SIZE_8BIT, Buf, 2, 0x10); return ((Buf[1] << 8) | (Buf[0] & 0xff)); }
主函数测试
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "i2c.h" #include "memorymap.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "DEV_Config.h" #include "PAJ7620U2.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ unsigned char PAJ7620U2_init() { unsigned char i,State; DEV_Set_I2CAddress(PAJ7620U2_I2C_ADDRESS); DEV_Delay_ms(5); State = DEV_I2C_ReadByte(0x00); //Read State if (State != 0x20) return 0; //Wake up failed DEV_I2C_WriteByte(PAJ_BANK_SELECT, 0); //Select Bank 0 for (i=0;i< Init_Array;i++) { DEV_I2C_WriteByte(Init_Register_Array[i][0], Init_Register_Array[i][1]);//Power up initialize } return 1; } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_MEMORYMAP_Init(); MX_USART3_UART_Init(); MX_I2C1_Init(); /* USER CODE BEGIN 2 */ printf("Gesture Sensor Test Program ...\r\n"); if(!PAJ7620U2_init()) { printf("\nGesture Sensor Error\r\n"); return 0; } printf("\nGesture Sensor OK\r\n"); DEV_I2C_WriteByte(PAJ_BANK_SELECT, 0); //Select Bank 0 for (int i = 0; i < Gesture_Array_SIZE; i++) { DEV_I2C_WriteByte(Init_Gesture_Array[i][0], Init_Gesture_Array[i][1]);//Gesture register initializes } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { // HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); //HAL_Delay(100); //printf("hello\n"); UWORD Gesture_Data = DEV_I2C_ReadWord(PAJ_INT_FLAG1); if (Gesture_Data) { switch (Gesture_Data) { case PAJ_UP: printf("Up\r\n"); break; case PAJ_DOWN: printf("Down\r\n"); break; case PAJ_LEFT: printf("Left\r\n"); break; case PAJ_RIGHT: printf("Right\r\n"); break; case PAJ_FORWARD: printf("Forward\r\n"); break; case PAJ_BACKWARD: printf("Backward\r\n"); break; case PAJ_CLOCKWISE: printf("Clockwise\r\n"); break; case PAJ_COUNT_CLOCKWISE: printf("AntiClockwise\r\n"); break; case PAJ_WAVE: printf("Wave\r\n"); break; default: break; } Gesture_Data=0; DEV_Delay_ms(50); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0); while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {} /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLL1_SOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 3; RCC_OscInitStruct.PLL.PLLN = 62; RCC_OscInitStruct.PLL.PLLP = 2; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 2; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1_VCIRANGE_3; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE; RCC_OscInitStruct.PLL.PLLFRACN = 4096; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2 |RCC_CLOCKTYPE_PCLK3; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */
接线
效果