|
項目描述:模塊采用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手勢識別模塊
最小系統的原理圖如下所示:
51hei截圖20210902215537.png (166.26 KB, 下載次數: 95)
下載附件
STM32最小系統
2021-9-2 21:55 上傳
硬件連接為:
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)
2021-9-2 23:16 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
ATK-PAJ7620手勢識別模塊用戶手冊_V1.0.pdf
(1.13 MB, 下載次數: 98)
2021-9-2 22:15 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|
評分
-
查看全部評分
|