找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9915|回复: 6
打印 上一主题 下一主题
收起左侧

2018年TI杯电赛D题作品,FDC2214手势识别源代码分享

[复制链接]
跳转到指定楼层
楼主
ID:219605 发表于 2018-7-26 09:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  此次电赛,指定TI的fdc2214芯片,前期申请阶段也是一波三折,到后来拿到EVM板测试,也费了一番周折。  个人认为,这个题目还是很简单的,比的就是数据处理的思想,毕竟不需要别的东西,只需要准备一块单片机开发板,一个fdc2214评估板,再加一块履铜板,还就是一些按键之类的基本元器件了。
  先附上题目要求,具体题目内容的话,大家去自己下载吧。
http://www.51hei.com/bbs/dpj-129251-1.html
  arduino开发系统,一直以来都是简单,上手快的代名词,的确,arduino用起来比stm32简单多了,没有复杂的寄存器操作,非常适合新手做东西,也可以说是非常适合所有人用吧,工具嘛,肯定是越容易用越好,所以我这次选用arduino来做这个题。
  手势识别,题目要求有训练模式和判决模式,有的同学想法过于高大上,以为训练模式要用到那种记忆的算法,然后越想越难,最后搞得结果不理想。我这边认真读题过后,果断确定了一套简单有效的方案。
  首先分析传感器:fdc2214的arduino库中的测试例程,我们可以发现(当然,数据手册里更加详细),fdc2214传感器的返回值是8位十进制数(其实读取的是28位二进制数,不过是arduino的串口打印出来默认转换成十进制了,反正灵敏度还是不得不佩服),我们就以这8位的十进制数来进行分析处理。
  如何理解训练模式?我是这样想的,训练模式,我可以理解成是系统在开始就录入你的手势数据(不同的手势的返回值不同),由此可以区别不同的手势。但是录入这块,很多人就有了疑问,寄存器?数组?这些我都想过,最后都没用,我写了一套更加简单的“录入”程序。就是定义全局变量,然后赋值再去调用就可以了。
  如何理解判决模式?我这样想,判决,就是一个比较,两个值之间的比较,所以当a=b(临时假设)时,就得出结论:这个手势就是录入时候的手势。但是这下就出了一点问题。
  问题一:如何确保判决模式时你的手势值完全等于你当时录入的值?
  要完全等于,这个操作难度过大了,也不容易判决,所以这里我用了一种用范围来确定的思想。就是录入手势值,给这个手势值加减一个相同的值,就可以得出一个范围,我们将用这个范围去进行判决,如果判决模式下采集到的值属于这个范围,那么就显示判决结果。
  问题二:如何确保录入手势时没有误差?
  当然,没有误差的系统是不存在的,稳态也有稳态误差,所以,我们是要尽量的避免误差,使误差最小化,近似消灭误差。这里,在我录入手势值的时候,采用了一种简单的滤波————算术平均滤波法。简单说就是取平均值,取采样多少次的一个平均值作为录入值,再给其加减一设定值,得到一个范围,就是我的判定范围了。
整个程序的思想就是这样,具体的话,我贴上程序吧。

// ARDUINO <--> FDC
// A4 <-------> SDA
// A5 <-------> SCL

#include <Wire.h>
#include "FDC2214.h"
int Filter_Value;
#define FILTER_N 30
unsigned long mean,Min,Max,fw=8,X,Min1,Max1,Min2,Max2,Min3,Max3,Min4,Max4,Min5,Max5,Min6,Max6;
int XL = 5;
int CQ = 6;
int HQ = 7;
FDC2214 capsense(FDC2214_I2C_ADDR_0);
void setup() {
  pinMode(XL, INPUT_PULLUP);
  pinMode(CQ, INPUT_PULLUP);
  pinMode(HQ, INPUT_PULLUP);
  digitalWrite(XL, HIGH);
  digitalWrite(CQ, HIGH);
  digitalWrite(HQ, HIGH);
  Wire.begin();
  Serial.begin(115200);
  Serial.println("\nFDC2x1x test");
  bool capOk = capsense.begin(0x3, 0x4, 0x5);
  if (capOk) Serial.println("Sensor OK");  
  else Serial.println("Sensor Fail");   
}
void loop()
{  
  X=capsense.getReading28(0)/1000;
  if(digitalRead(XL) == LOW)//开启训练模式
  {   
     train();   
   if(digitalRead(CQ) == LOW)//开启猜拳模式
  {
   decide1();
   }
  if(digitalRead(HQ) == LOW)//开启划拳模式
  {
    decide2();
   }
  }
}
/****训练模式*****/

void train()
{   
  if(Serial.available()>0)
  {      
  // a = Serial.parseInt();
    switch(Serial.parseInt())
     {         
  case 1:deal();Min1=Min;Max1=Max;Serial.print("   ");Serial.print(Min1);Serial.print("   ");Serial.print(Max1);Serial.print("   ");Serial.println("1 FINISH");break;
  case 2:deal();Min2=Min;Max2=Max;Serial.print("   ");Serial.print(Min2);Serial.print("   ");Serial.print(Max2);Serial.print("   ");Serial.println("2 FINISH");break;
  case 3:deal();Min3=Min;Max3=Max;Serial.print("   ");Serial.print(Min3);Serial.print("   ");Serial.print(Max3);Serial.print("   ");Serial.println("3 FINISH");break;
  case 4:deal();Min4=Min;Max4=Max;Serial.print("   ");Serial.print(Min4);Serial.print("   ");Serial.print(Max4);Serial.print("   ");Serial.println("4 FINISH");break;
  case 5:deal();Min5=Min;Max5=Max;Serial.print("   ");Serial.print(Min5);Serial.print("   ");Serial.print(Max5);Serial.print("   ");Serial.println("5 FINISH");break;
  case 6:deal();Min6=Min;Max6=Max;Serial.print("   ");Serial.print(Min6);Serial.print("   ");Serial.print(Max6);Serial.print("   ");Serial.println("6 FINISH");break;
  case 7:Serial.print("   ");Serial.println("ALL FINISH");break;
      }
  }
}
/**判断***猜拳模式******/

void decide1()
{
    //oled(显示猜拳模式)
    //oled(显示按键进入猜拳模式)
   Serial.print(Min2);
   Serial.print(Max2);
   Serial.println(mean);
     if(Min2<X&&X<Max2)
    {
      Serial.println("jiandao");
     }
     if(Min5<X&&X<Max5)
    {
      Serial.println("baofu");
     }
     if(Min6<X&&X<Max6)
    {
      Serial.println("chuizi");
     }     
}
/***判断**划拳模式******/

void decide2()
{
    //oled(显示猜拳模式)
    //oled(显示按键进入猜拳模式)
   if(Min1<X&&X<Max1)
   {
     Serial.println("1");
    }
    if(Min2<X&&X<Max2)
   {
     Serial.println("2");
    }
    if(Min3<X&&X<Max3)
   {
     Serial.println("3");
    }
    if(Min4<X&&X<Max4)
   {
     Serial.println("4");
    }
    if(Min5<X&&X<Max5)
   {
     Serial.println("5");
    }
}


/*****录入手势范围约束,返回******/
unsigned long deal()
{
  Filter();
  Min=mean-fw;
  Max=mean+fw;
  return (Min&&Max);
}

/***********求平均值返回mean********/
unsigned long Filter() //测 次的平均值
{
  int i;
unsigned long filter_sum = 0;
  for(i = 0; i < FILTER_N; i++)
  {
    filter_sum +=capsense.getReading28(0)/1000;
    delay(1);
  }
  mean=filter_sum / FILTER_N;
return (unsigned long)(mean);

}

4060D,我的作品编号,作品使用的按键控制,用六个按键来分别录入1,2(剪刀)3,4,5(布)和6(石头)。这样连线多的话会出现干扰的情况,可以构建一个通信,让蓝牙给arduino发数据来实现手势采集,从而替代按键,以达到消除电磁干扰的目的。



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:399007 发表于 2019-8-7 18:41 | 只看该作者
请问您用的是什么极板
回复

使用道具 举报

板凳
ID:511461 发表于 2019-10-12 19:08 | 只看该作者
有没有原理图
回复

使用道具 举报

地板
ID:219605 发表于 2019-11-1 18:36 | 只看该作者
shaoduidui 发表于 2019-8-7 18:41
请问您用的是什么极板

是mega2560
回复

使用道具 举报

5#
ID:219605 发表于 2019-11-1 18:38 | 只看该作者

您是指mega2560的原理图还是整个系统的接线图?
回复

使用道具 举报

6#
ID:513617 发表于 2020-2-16 12:12 | 只看该作者
xprice 发表于 2019-11-1 18:38
您是指mega2560的原理图还是整个系统的接线图?

整个系统的连接图有吗
回复

使用道具 举报

7#
ID:733810 发表于 2020-4-20 18:55 | 只看该作者
请问下 bool capOk = capsense.begin(0x3, 0x4, 0x5);报错说没有这个功能该怎么办
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表