此次電賽,指定TI的fdc2214芯片,前期申請階段也是一波三折,到后來拿到EVM板測試,也費了一番周折。 個人認為,這個題目還是很簡單的,比的就是數據處理的思想,畢竟不需要別的東西,只需要準備一塊單片機開發板,一個fdc2214評估板,再加一塊履銅板,還就是一些按鍵之類的基本元器件了。
先附上題目要求,具體題目內容的話,大家去自己下載吧。
http://www.zg4o1577.cn/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發數據來實現手勢采集,從而替代按鍵,以達到消除電磁干擾的目的。
|