标题:
电赛FDC2214手势识别装置改进(基于手势识别控制舵机)
[打印本页]
作者:
Ivy_Lee
时间:
2018-11-6 14:10
标题:
电赛FDC2214手势识别装置改进(基于手势识别控制舵机)
2018年电子设计大赛省赛题制作方案改进,变成基于手势识别控制舵机
可用于实现开关锁之类的小活动
剪刀模拟识别开锁
石头关锁
其他功能详见代码
单片机源程序如下:
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "myiic.h"
#include "FDC2X2X_CMD.h"
#include "FDC2214.h"
#include "DataScope_DP.h"
#include "OLED.h"
#include "IMG.h"
#include "TIM.h"
#include "LED.h"
#define VOLUME 1000
//接线方式:
//ch0:拇指
//ch1:手掌
//ch2:食指
//ch3:中指
//ch4:无名指
//ch5:小指
u8 STA;
u8 pwm;
u8 STA_num;
u8 STA_num_1;
#define HAND_FORMS_ONE 0x06
#define HAND_FORMS_TWO 0x0e
#define HAND_FORMS_THREE 0x1e
#define HAND_FORMS_FOUR 0x3e
#define HAND_FORMS_FIVE 0x3f
#define HAND_FORMS_SIX 0x23
#define HAND_FORMS_SIVEN 0x0f
#define HAND_FORMS_EIGHT 0x07
#define HAND_FORMS_NINE 0x03
#define HAND_FORMS_TEN 0x02
#define HAND_FORMS_JD 0x0e
#define HAND_FORMS_ST 0x02
#define HAND_FORMS_B 0x3f
#define FINGER_PIANO_1 ((0x03) &0xfd)
#define FINGER_PIANO_2 ((0x06) &0xfd)
#define FINGER_PIANO_3 ((0x0a) &0xfd)
#define FINGER_PIANO_4 ((0x12) &0xfd)
#define FINGER_PIANO_5 ((0x22) &0xfd)
//**特别注意:使用时SDA、SCL要接4.7K上拉电阻,地址线接地**//
//**寄存器值的读取及电容的计算具体在 FDC2214_read_CHx() 中**/
float i;//for循环专用变量
u8 s[100];//sprintf
void Data_BackUp()
{
BKP->DR1=(u32)FDC_CH0.Threshold;
BKP->DR2=((u32)FDC_CH0.Threshold>>16);
BKP->DR3=(u32)FDC_CH1.Threshold;
BKP->DR4=((u32)FDC_CH1.Threshold>>16);
BKP->DR5=(u32)FDC_CH2.Threshold;
BKP->DR6=((u32)FDC_CH2.Threshold>>16);
BKP->DR7=(u32)FDC_CH3.Threshold;
BKP->DR8=((u32)FDC_CH3.Threshold>>16);
BKP->DR9=(u32)FDC_CH4.Threshold;
BKP->DR10=((u32)FDC_CH4.Threshold>>16);
BKP->DR11=(u32)FDC_CH5.Threshold;
BKP->DR12=((u32)FDC_CH5.Threshold>>16);
}
void Data_Load()
{
FDC_CH0.Threshold = (float)(BKP->DR1 | (BKP->DR2<<16) );
FDC_CH1.Threshold = (float)(BKP->DR3 | (BKP->DR4<<16) );
FDC_CH2.Threshold = (float)(BKP->DR5 | (BKP->DR6<<16) );
FDC_CH3.Threshold = (float)(BKP->DR7 | (BKP->DR8<<16) );
FDC_CH4.Threshold = (float)(BKP->DR9 | (BKP->DR10<<16) );
FDC_CH5.Threshold = (float)(BKP->DR11| (BKP->DR12<<16) );
}
int main(void)
{
pwm=190;
delay_init(); //延时函数初始化
OLED_Init();
OLED_ShowString(10,32,"Loading...");OLED_Refresh_Gram();
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(256000); //串口初始化为9600
uart5_init(9600);
KEY_Init();
LED_Init();
//开启后备寄存器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启后备电源
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启后备寄存器
PWR->CR|=0x00100;//取消后备寄存器的写保护
FDC2214_Init();
FDC2214_Init_2();
// Read_REG();
// Read_REG_2();
TIM_1_PWM_Init(7199,0);//不分频。PWM频率=72000/(7199+1)=10Khz
TIM2_PWM_Init(199,7199);//不分频。PWM频率=72000/(7199+1)/(199+1)=50hz
TIM1->CCR4=0;//比较值,音量设置
TIM1->PSC=0; //预分频系数,频率设置
// delay_ms(10000);
while(1)
{
static int timer=19;
static u8 step=3;
static u8 mode=0;//0:划拳//1:猜拳//2:手指琴//3:划拳(扩充)
static u8 mode_1=5;
static u8 key_sta;
delay_ms(10);
Date_Back(0);//刷新数据并上传给上位机
switch(STA)
{
case HAND_FORMS_ONE : STA_num=1; break;
case HAND_FORMS_TWO : STA_num=2; break;
case HAND_FORMS_THREE: STA_num=3; break;
case HAND_FORMS_FOUR : STA_num=4; break;
case HAND_FORMS_FIVE : STA_num=5; break;
case HAND_FORMS_SIX : STA_num=6; break;
case HAND_FORMS_SIVEN: STA_num=7; break;
case HAND_FORMS_EIGHT: STA_num=8; break;
case HAND_FORMS_NINE : STA_num=9; break;
case HAND_FORMS_TEN : STA_num=10; break;
default : STA_num=0; break;
}
// if( (STA_num_1 != STA_num) || (mode_1 != mode) )
// {
while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
UART5->DR = (u8)'*';
while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
UART5->DR = (u8) mode;
while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
UART5->DR = (u8) STA_num;
while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
UART5->DR = (u8) '#';
// }
STA_num_1=STA_num;
mode_1=mode;
switch(step)
{
case 0://校准Normal值
if(timer<=0)//倒计时时间到
{
FDC_CH0.Normal=From_History_Get_Average(FDC_CH0.History,10);
FDC_CH1.Normal=From_History_Get_Average(FDC_CH1.History,10);
FDC_CH2.Normal=From_History_Get_Average(FDC_CH2.History,10);
FDC_CH3.Normal=From_History_Get_Average(FDC_CH3.History,10);
FDC_CH4.Normal=From_History_Get_Average(FDC_CH4.History,10);
FDC_CH5.Normal=From_History_Get_Average(FDC_CH5.History,10);
OLED_Clear();OLED_Refresh_Gram();
step=1;timer=39;
}
else //倒计时未到
{
timer--;
OLED_SHOW_Imag(0,0,32,32,(u8*)gImage_qing,2,0);
OLED_SHOW_Imag(32,0,32,32,(u8*)gImage_wu,2,0);
OLED_SHOW_Imag(64,0,32,32,(u8*)gImage_chu,2,0);
OLED_SHOW_Imag(96,0,32,32,(u8*)gImage_peng,2,0);
OLED_SHOW_Imag(0,32,24,24,(u8*)gImage_xun,2,0);
OLED_SHOW_Imag(24,32,24,24,(u8*)gImage_lian,2,0);
OLED_Refresh_Gram();
}
break;
case 1://校准Put值
if(timer<=0)//倒计时时间到
{
FDC_CH0.Put=From_History_Get_Average(FDC_CH0.History,10);
FDC_CH1.Put=From_History_Get_Average(FDC_CH1.History,10);
FDC_CH2.Put=From_History_Get_Average(FDC_CH2.History,10);
FDC_CH3.Put=From_History_Get_Average(FDC_CH3.History,10);
FDC_CH4.Put=From_History_Get_Average(FDC_CH4.History,10);
FDC_CH5.Put=From_History_Get_Average(FDC_CH5.History,10);
step=2;timer=39;
}
else //倒计时时间未到
{
timer--;
OLED_SHOW_Imag(0,0,32,32,(u8*)gImage_fang,2,0);
OLED_SHOW_Imag(32,0,32,32,(u8*)gImage_zhi,2,0);
OLED_SHOW_Imag(64,0,32,32,(u8*)gImage_shou,2,0);
OLED_SHOW_Imag(96,0,32,32,(u8*)gImage_zhang,2,0);
sprintf((char *)s,"Counter:%d",timer/10);
OLED_ShowString(0,32,s);
OLED_Refresh_Gram();
}
break;
case 2://计算阈值
FDC_CH0.Threshold=(FDC_CH0.Put+FDC_CH0.Normal)/2;
FDC_CH1.Threshold=(FDC_CH1.Put+FDC_CH1.Normal)/2;
FDC_CH2.Threshold=(FDC_CH2.Put+FDC_CH2.Normal)/2;
FDC_CH3.Threshold=(FDC_CH3.Put+FDC_CH3.Normal)/2;
FDC_CH4.Threshold=(FDC_CH4.Put+FDC_CH4.Normal)/2;
FDC_CH5.Threshold=(FDC_CH5.Put+FDC_CH5.Normal)/2;
Data_BackUp();
OLED_Clear();
step=4;
break;
case 3://读取数据
Data_Load();
step=4;
break;
case 4://清屏
OLED_Clear();
step=5;
break;
case 5://状态解算
FDC_CH0.STA<<=1;
FDC_CH1.STA<<=1;
FDC_CH2.STA<<=1;
FDC_CH3.STA<<=1;
FDC_CH4.STA<<=1;
FDC_CH5.STA<<=1;
if( FDC_CH0.Now < FDC_CH0.Threshold )
FDC_CH0.STA|=0x01;
else
FDC_CH0.STA&=0xfe;
if( FDC_CH1.Now < FDC_CH1.Threshold )
FDC_CH1.STA|=0x01;
else
FDC_CH1.STA&=0xfe;
if( FDC_CH2.Now < FDC_CH2.Threshold )
FDC_CH2.STA|=0x01;
else
FDC_CH2.STA&=0xfe;
if( FDC_CH3.Now < FDC_CH3.Threshold )
FDC_CH3.STA|=0x01;
else
FDC_CH3.STA&=0xfe;
if( FDC_CH4.Now < FDC_CH4.Threshold )
FDC_CH4.STA|=0x01;
else
FDC_CH4.STA&=0xfe;
if( FDC_CH5.Now < FDC_CH5.Threshold )
FDC_CH5.STA|=0x01;
else
FDC_CH5.STA&=0xfe;
STA = ((FDC_CH5.STA&0x01)<<5) | ((FDC_CH4.STA&0x01)<<4) | ((FDC_CH3.STA&0x01)<<3) | ((FDC_CH2.STA&0x01)<<2) | ((FDC_CH1.STA&0x01)<<1) | (FDC_CH0.STA&0x01);
key_sta = KEY_Scan(0);
if(key_sta != 0)
OLED_Clear(),timer=19;
if( key_sta == KEY0_PRES)//换模式
mode=!mode;
if( key_sta == WKUP_PRES)//换模式,附加模式
{
if(mode == 2)
mode=3;
else
mode=2;
}
switch(mode)
{
case 0:step=7;break;
case 1:step=8;break;
case 2:step=9;break;
case 3:step=10;break;
}
if(key_sta == KEY1_PRES)//去校准
{
step=0;
timer=19;
}
break;
case 7://猜拳
if(timer>0)//倒计时时间未到
{
timer--;
OLED_SHOW_Imag(60,16,16,16,(u8*)cai,2,0),OLED_SHOW_Imag(76,16,16,16,(u8*)quan,2,0);
OLED_Refresh_Gram();
}
else //倒计时到
{
switch(STA)
{
case HAND_FORMS_JD:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_jiandao,1,0);
if(pwm>60)
{
TIM_SetCompare3(TIM2,pwm--);
delay_ms(10);
}
OLED_Refresh_Gram();
break;
case HAND_FORMS_ST:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_shitou,1,0);
if(pwm==60|pwm<190)
{
// pwm=190;
TIM_SetCompare3(TIM2,pwm++);
delay_ms(10);}
OLED_Refresh_Gram();
break;
case HAND_FORMS_B:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_bu,1,0);
// TIM_SetCompare3(TIM2,0);
OLED_Refresh_Gram();
break;
default:
OLED_Fill(30,0,94,64,0);OLED_Refresh_Gram();
break;
}
step=5;
}
break;
case 8://划拳
if(timer>0)//倒计时时间未到
{
timer--;
OLED_SHOW_Imag(60,16,16,16,(u8*)hua,2,0),OLED_SHOW_Imag(76,16,16,16,(u8*)quan,2,0);
OLED_Refresh_Gram();
}
else //倒计时到
{
switch(STA)
{
case HAND_FORMS_ONE:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_one,1,0);OLED_Refresh_Gram();
break;
case HAND_FORMS_TWO:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_two,1,0);OLED_Refresh_Gram();
break;
case HAND_FORMS_THREE:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_three,1,0);OLED_Refresh_Gram();
break;
case HAND_FORMS_FOUR:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_foul,1,0);OLED_Refresh_Gram();
break;
case HAND_FORMS_FIVE:
OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_five,1,0);OLED_Refresh_Gram();
break;
default:
OLED_Fill(30,0,94,64,0);OLED_Refresh_Gram();
break;
}
step=5;
}
break;
case 9://手指琴
if(timer>0)//倒计时时间未到
{
timer--;
OLED_ShowString(15,16,(u8*)"Finger Piano");
OLED_Refresh_Gram();
}
else //倒计时到
{
switch(STA)
{
case FINGER_PIANO_1: TIM1->PSC=7;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_2: TIM1->PSC=6;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_3: TIM1->PSC=5;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_4: TIM1->PSC=4;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_5: TIM1->PSC=3;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_1|FINGER_PIANO_2: TIM1->PSC=13;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_1|FINGER_PIANO_3: TIM1->PSC=12;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_1|FINGER_PIANO_4: TIM1->PSC=11;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_1|FINGER_PIANO_5: TIM1->PSC=10;TIM1->CCR4=VOLUME; break;
case FINGER_PIANO_2|FINGER_PIANO_3: TIM1->PSC=9;TIM1->CCR4=VOLUME; break;
default :TIM1->CCR4=0;//比较值,音量设置
break;
}
//
step=5;
}
break;
case 10://划拳(扩充)
if(timer>0)//倒计时时间未到
{
timer--;
OLED_SHOW_Imag(60,16,16,16,(u8*)hua,2,0),OLED_SHOW_Imag(76,16,16,16,(u8*)quan,2,0);
OLED_ShowString(60,32,(u8*)"plus");
OLED_Refresh_Gram();
}
else //倒计时到
{
switch(STA)
{
case HAND_FORMS_ONE:OLED_Fill(64,0,128,64,0);
OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_1,1,1);OLED_Refresh_Gram();
break;
case HAND_FORMS_TWO:OLED_Fill(64,0,128,64,0);
OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_2,1,1);OLED_Refresh_Gram();
break;
case HAND_FORMS_THREE:OLED_Fill(64,0,128,64,0);
OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_3,1,1);OLED_Refresh_Gram();
break;
case HAND_FORMS_FOUR:OLED_Fill(64,0,128,64,0);
OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_4,1,1);OLED_Refresh_Gram();
break;
case HAND_FORMS_FIVE:OLED_Fill(64,0,128,64,0);
OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_5,1,1);OLED_Refresh_Gram();
break;
case HAND_FORMS_SIX:
OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_6,1,0);OLED_Refresh_Gram();
break;
case HAND_FORMS_SIVEN:
OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_7,1,0);OLED_Refresh_Gram();
break;
case HAND_FORMS_EIGHT:
OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_8,1,1);OLED_Refresh_Gram();
break;
case HAND_FORMS_NINE:
OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_9,1,1);OLED_Refresh_Gram();
break;
case HAND_FORMS_TEN:
OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_10,1,1);OLED_Refresh_Gram();
break;
default:
OLED_Clear();OLED_Refresh_Gram();
break;
}
step=5;
}
break;
default:
OLED_Fill(0,0,128,64,1);OLED_Refresh_Gram();delay_ms(10000);
break;
}
}
}
复制代码
所有资料51hei提供下载:
fingers.rar
(363.18 KB, 下载次数: 35)
2018-11-9 00:49 上传
点击文件名下载附件
仅可用于学习,禁用于其他任何用途
下载积分: 黑币 -5
作者:
Ivy_Lee
时间:
2018-11-6 14:11
除了题目要求以外的拓展功能:
作者:
Ivy_Lee
时间:
2018-11-6 14:12
划拳plus:识别6~10特殊手势
拇指琴:利用蜂鸣器发出不同音调的声音
2s快速校准手型,适用于更多人
作者:
admin
时间:
2018-11-9 00:50
好资料,51黑有你更精彩!!!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1