|
项目描述:模块采用ATK-PAJ7620_V1.2,自带九种手势识别,支持上、下、左、右、前、后、顺时针旋转、逆时针旋转和挥动的手势动作识别,STM32与模块之间采用IIC进行通信,识别不同的手势通过IIC读取模块寄存器的值是不相同的,根据识别不同手势的值控制对应的器件。4个灯的亮灭分别代表4种手势的识别,STM32通过IO口控制灯亮灭,例如判别为第一种手势,灯1亮,第二个手势灯1灭灯2亮,识别不了按照前面的方式亮。风扇控制方面采用PWM波控制,三个PWM波分别为低中高,然后满占空比对应全开,0占空比对应关,以此对应5种手势状态。
项目分为以下几个部分:
1.基于正点原子的ATK-PAJ7620红外手势识别模块IIC通信与手势判别
2.基于L298N的PWM电机控制
3.LED灯的控制
硬件部分:
1.STM32最小系统
2.L298N电机驱动模块及电机和扇叶
3.LED灯模块
4.ATK-PAJ7620手势识别模块
最小系统的原理图如下所示:
硬件连接为:
1.ATK-PAJ7620 IIC PB10:SCL PB11:SDA
2.L298N PWM控制口:PB5
3.LED接口:PB6 PB7 PB8 PB9
首先是ATK-PAJ7620模块的IIC初始化
单片机源程序如下:
PWM初始化:配置TIM3定时器产生PWM频率为80KHZ
- #include "timer.h"
- #include "led.h"
- #include "usart.h"
-
- //通用定时器3中断初始化
- //这里时钟选择为APB1的2倍,而APB1为36M
- //arr:自动重装值。
- //psc:时钟预分频数
- //这里使用的是定时器3!
- void TIM3_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
-
- TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
-
- }
- //定时器3中断服务程序
- void TIM3_IRQHandler(void) //TIM3中断
- {
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
- {
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
- //LED1=!LED1;
- }
- }
- //TIM3 PWM部分初始化
- //PWM输出初始化
- //arr:自动重装值
- //psc:时钟预分频数
- void TIM3_PWM_Init(u16 arr,u16 psc)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟
-
- GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
-
- //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
-
- //初始化TIM3
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
-
- //初始化TIM3 Channel2 PWM模式
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
- TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2
- TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
-
- TIM_Cmd(TIM3, ENABLE); //使能TIM3
-
- }
复制代码
LED灯初始化不再赘述,ATK-PAJ7620功能函数如下,主要通过IIC通信返回的数据再结合手册可做判断模块识别到为什么手势进而进行相应的控制
- #include "paj7620u2.h"
- #include "paj7620u2_cfg.h"
- #include "delay.h"
- #include "usart.h"
- #include "led.h"
- #include "lcd.h"
- #include "key.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唤醒
- u8 paj7620u2_wakeup(void)
- {
- u8 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:成功
- u8 paj7620u2_init(void)
- {
- u8 i;
- u8 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寄存器区域
-
- return 1;
- }
- //主菜单
- void paj7620u2_test_ui(void)
- {
- POINT_COLOR=BLUE;//设置字体为蓝色
- LCD_Fill(30,170,300,300,WHITE);
- LCD_ShowString(30,170,200,16,16,"KEY1: Gesrure test");//手势识别测试
- LCD_ShowString(30,190,200,16,16,"KEY0: Ps test ");//接近距离测试
-
- }
- //手势识别测试
- void Gesrure_test(void)
- {
- u8 i;
- u8 status;
- u8 key;
- u8 data[2]={0x00};
- u16 gesture_data;
- u8 ledflash=0;
-
- 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
- i=0;
- POINT_COLOR=BLUE;//设置字体为蓝色
- // LCD_Fill(30,170,300,300,WHITE);
- // LCD_ShowString(30,180,200,16,16,"KEY_UP: Exit the test");
- // LCD_ShowString(30,210,200,16,16,"Gesrure test");
- // POINT_COLOR=RED;//设置字体为蓝色
- while(1)
- {
- key = KEY_Scan(0);
- if(key==WKUP_PRES)
- {
- GS_Write_Byte(PAJ_SET_INT_FLAG1,0X00);//关闭手势识别中断输出
- GS_Write_Byte(PAJ_SET_INT_FLAG2,0X00);
- break;
- }
- status = GS_Read_nByte(PAJ_GET_INT_FLAG1,2,&data[0]);//读取手势状态
- if(!status)
- {
- gesture_data =(u16)data[1]<<8 | data[0];
- if(gesture_data)
- {
- switch(gesture_data)
- {
- case GES_UP: GPIO_SetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,1000);
- printf("Up\r\n"); ledflash=1; break; //向上
- case GES_DOWM: GPIO_SetBits(GPIOB,GPIO_Pin_7); GPIO_ResetBits(GPIOB,GPIO_Pin_6);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,1000);
- printf("Dowm\r\n"); ledflash=1; break; //向下
- case GES_LEFT: GPIO_SetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,1000);
- printf("Left\r\n"); ledflash=1; break; //向左
- case GES_RIGHT: GPIO_SetBits(GPIOB,GPIO_Pin_9); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_6);TIM_SetCompare2(TIM3,1000);
- printf("Right\r\n"); ledflash=1; break; //向右
- case GES_FORWARD: GPIO_ResetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,1000);
- printf("Forward\r\n"); ledflash=1; break; //向前
- case GES_BACKWARD: GPIO_ResetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,0);
- printf("Backward\r\n"); ledflash=1; break; //向后
- case GES_CLOCKWISE: GPIO_ResetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,50);
- printf("Clockwise\r\n"); ledflash=1; break; //顺时针
- case GES_COUNT_CLOCKWISE: GPIO_ResetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,200);
- printf("AntiClockwise\r\n"); ledflash=1; break; //逆时针
- case GES_WAVE: GPIO_ResetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_7);
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);TIM_SetCompare2(TIM3,550);
- printf("Wave\r\n"); ledflash=1; break; //挥动
- default: ledflash=0; break;
-
- }
- if(ledflash)//DS1闪烁
- {
- // LED1=0;delay_ms(80);LED1=1;delay_ms(80);
- // LED1=0;delay_ms(80);LED1=1;delay_ms(80);
- delay_ms(300);
- //LCD_ShowString(40,250,200,16,24," ");
- ledflash=0;
- }
- }
-
- }
- delay_ms(50);
- // i++;
- // if(i==5)
- // {
- // LED0=!LED0;//提示系统正在运行
- // i=0;
- // }
- }
- }
- //接近检测测试
- void Ps_test(void)
- {
- u8 i;
- u8 key;
- u8 data[2]={0x00};
- u8 obj_brightness=0;
- u16 obj_size=0;
-
- paj7620u2_selectBank(BANK0);//进入BANK0
- for(i=0;i<PROXIM_SIZE;i++)
- {
- GS_Write_Byte(proximity_arry[i][0],proximity_arry[i][1]);//接近检测模式初始化
- }
- paj7620u2_selectBank(BANK0);//切换回BANK0
- i=0;
- POINT_COLOR=BLUE;//设置字体为蓝色
- LCD_Fill(30,170,300,300,WHITE);
- LCD_ShowString(30,180,200,16,16,"KEY_UP: Exit the test");
- LCD_ShowString(30,210,200,16,16,"Ps test");
- LCD_ShowString(30,240,200,16,16,"Brightness");
- LCD_ShowString(160,240,200,16,16,"Size");
- POINT_COLOR=RED;//设置字体为蓝色
-
- while(1)
- {
- key = KEY_Scan(0);
- if(key==WKUP_PRES) break;
-
- 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 = ((u16)data[1] & 0x0f)<<8 | data[0];
- LCD_ShowxNum(50,270,obj_brightness,3,24,0);
- LCD_ShowxNum(152,270,obj_size,3,24,0);
- printf("obj_brightness: %d\r\n",obj_brightness);
- printf("obj_size: %d\r\n",obj_size);
-
- delay_ms(100);
- // i++;
- // if(i==5)
- // {
- // LED0=!LED0;//提示系统正在运行
- // i=0;
- // }
- }
-
- }
- //PAJ7620U2传感器测试
- void paj7620u2_sensor_test(void)
- {
- u8 i=0;
- u8 key;
-
- paj7620u2_test_ui();//主菜单显示
- while(1)
- {
- key = KEY_Scan(0);//按键扫描
- if(key)
- {
- switch(key)
- {
- case KEY1_PRES: Gesrure_test(); break;//手势检测模式
- case KEY0_PRES: Ps_test(); break;//接近检测模式
- }
- paj7620u2_test_ui();
- }
- delay_ms(50);
- i++;
- if(i==5)
- {
- //LED0=!LED0;//提示系统正在运行
- i=0;
- }
-
- }
- }
复制代码 代码工程与pdf资料51hei附件下载:
手势识别.7z
(252.15 KB, 下载次数: 193)
ATK-PAJ7620手势识别模块用户手册_V1.0.pdf
(1.13 MB, 下载次数: 98)
|
评分
-
查看全部评分
|