此次电赛,指定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发数据来实现手势采集,从而替代按键,以达到消除电磁干扰的目的。
|