1. 程式人生 > >基於FDC2214感測器的手勢識別裝置(MSP430)

基於FDC2214感測器的手勢識別裝置(MSP430)

今年的江蘇省電賽,我們選擇了手勢識別裝置(D題)。

裝置使用MSP430F5529開發板,TI的FDC2214電容感測器,外設使用4*4矩陣按鍵進行功能切換、數碼管顯示感測器數值、LED燈顯示手勢狀態。

FDC2214是4路輸入電容感測器,我們使用覆銅板平均分成八分,構成四路差分結構,識別結果比較穩定。

以下是實現程式碼:

​
#include "bsp.h"

#define delaytime 250 //檢測到手勢後延時檢測比較時間  毫秒
#define Stable 10    //穩定後數值變化範圍

//#define scissors 500   //手勢剪刀分界
#define num0_1 400   //開始判斷的分界

#define rock 1900   //手勢剪刀石頭的分界
#define paper 2900   //手勢石頭布的分界


#define num1_2 800   //手勢數值1和2的分界
#define num2_3 1150   //手勢數值2和3的分界
#define num3_4 1450   //手勢數值3和4的分界
#define num4_5 1950   //手勢數值4_5的分界

#define ratio 6       //讀數右移位數

#define s1 0.67       //第1通道係數
#define s2 1       //第2通道係數
#define s3 1       //第3通道係數
#define s4 0.82       //第4通道係數

#define numfun5 50   //功能5 燈開始亮分界


#define Led0_off P3OUT |=BIT0
#define Led1_off P3OUT |=BIT1
#define Led2_off P3OUT |=BIT2
#define Led3_off P3OUT |=BIT3
#define Led4_off P3OUT |=BIT4
#define Led5_off P3OUT |=BIT5
#define Led6_off P3OUT |=BIT6
#define Led7_off P3OUT |=BIT7
#define Led0_on P3OUT &=~BIT0
#define Led1_on P3OUT &=~BIT1
#define Led2_on P3OUT &=~BIT2
#define Led3_on P3OUT &=~BIT3
#define Led4_on P3OUT &=~BIT4
#define Led5_on P3OUT &=~BIT5
#define Led6_on P3OUT &=~BIT6
#define Led7_on P3OUT &=~BIT7
#define buzzer_off P2OUT |=BIT0
#define buzzer_on P2OUT &=~BIT0

unsigned long int temp0_zero, temp1_zero, temp2_zero, temp3_zero;
unsigned char numf = 0, numf1 = 0;
unsigned char key1_f = 0, key2_f = 0, key3_f = 0, key4_f = 0, key5_f = 0;
unsigned char key6_f = 0, key7_f = 0, key8_f = 0, key9_f = 0, key10_f = 0;
unsigned char key11_f = 0, key12_f = 0, key13_f = 0, key14_f = 0, key15_f = 0;
unsigned char key16_f = 0, key3_f_x = 1, key4_f_x = 1;
unsigned char delayf = 1, ms_f = 0;
unsigned int rock_p, paper_p;
unsigned int num1_2_p, num2_3_p, num3_4_p, num4_5_p;
unsigned int scissors_s, rock_s, paper_s;
unsigned int num0_1_s, num1_2_s, num2_3_s, num3_4_s, num4_5_s;
float temp_f;

int main(void)
{
    unsigned int temp, temp0_h, temp0_l, temp1_h, temp1_l, temp2_h, temp2_l, temp3_h, temp3_l;
    unsigned long int temp0, temp1, temp2, temp3;
    unsigned int temp_pr = 0, Difference = 0;
    // Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
    P3DIR = 0xff;
    P2DIR = 0xff;
    buzzer_off;
    P3OUT = 0xff;
    bsp_Init();
    Init_Keypad();
    _EINT();
    Initdisplay();
    delay_ms(500);
    delay_ms(500);
    //開機清零
    temp0_h = ReadRegfdc2214(0x00); //讀取第1通道的值
    temp0_l = ReadRegfdc2214(0x01); //讀取第1通道的值
    temp0 = temp0_h;
    temp0 = (temp0 << 16) + temp0_l;
    temp0_zero = temp0;
    temp1_h = ReadRegfdc2214(0x02); //讀取第2通道的值
    temp1_l = ReadRegfdc2214(0x03); //讀取第2通道的值
    temp1 = temp1_h;
    temp1 = (temp1 << 16) + temp1_l;
    temp1_zero = temp1;
    temp2_h = ReadRegfdc2214(0x04); //讀取第3通道的值
    temp2_l = ReadRegfdc2214(0x05); //讀取第3通道的值
    temp2 = temp2_h;
    temp2 = (temp2 << 16) + temp2_l;
    temp2_zero = temp2;
    temp3_h = ReadRegfdc2214(0x06); //讀取第4通道的值
    temp3_l = ReadRegfdc2214(0x07); //讀取第4通道的值
    temp3 = temp3_h;
    temp3 = (temp3 << 16) + temp3_l;
    temp3_zero = temp3;
    
    while (1)
    {
      //讀取4通道資料
        temp0_h = ReadRegfdc2214(0x00); //讀取第1通道的值
        temp0_l = ReadRegfdc2214(0x01); //讀取第1通道的值
        temp0 = temp0_h;
        temp0 = (temp0 << 16) + temp0_l;
        if (temp0_zero > temp0)
            temp0 = temp0_zero - temp0;
        else
            temp0 = 0;
        temp0 = temp0 >> ratio;
        temp1_h = ReadRegfdc2214(0x02); //讀取第2通道的值
        temp1_l = ReadRegfdc2214(0x03); //讀取第2通道的值
        temp1 = temp1_h;
        temp1 = (temp1 << 16) + temp1_l;
        if (temp1_zero > temp1)
            temp1 = temp1_zero - temp1;
        else
            temp1 = 0;
        temp1 = temp1 >> ratio;
        temp2_h = ReadRegfdc2214(0x04); //讀取第3通道的值
        temp2_l = ReadRegfdc2214(0x05); //讀取第3通道的值
        temp2 = temp2_h;
        temp2 = (temp2 << 16) + temp2_l;
        if (temp2_zero > temp2)
            temp2 = temp2_zero - temp2;
        else
            temp2 = 0;
        temp2 = temp2 >> ratio;
        temp3_h = ReadRegfdc2214(0x06); //讀取第4通道的值
        temp3_l = ReadRegfdc2214(0x07); //讀取第4通道的值
        temp3 = temp3_h;
        temp3 = (temp3 << 16) + temp3_l;
        if (temp3_zero > temp3)
            temp3 = temp3_zero - temp3;
        else
            temp3 = 0;
        temp3 = temp3 >> ratio;
        temp_f = temp0 * s1 + temp1 * s2 + temp2 * s3 + temp3 * s4; //求4通道讀數之和
        temp = (unsigned int )temp_f;
        
        if(key5_f)//功能5
        {
        if(temp0>numfun5)Led1_on;
        else Led1_off;
        if(temp1>numfun5)Led3_on;
        else Led3_off;        
        if(temp2>numfun5)Led5_on;
        else Led5_off; 
        if(temp3>numfun5)Led7_on;
        else Led7_off; 
        
        if((temp0>numfun5)&&(temp1>numfun5)){Led2_on;}//Led1_off;Led3_off;
        else Led2_off;
        if((temp1>numfun5)&&(temp2>numfun5)){Led4_on;}//Led3_off;Led5_off;
        else Led4_off;
        if((temp2>numfun5)&&(temp3>numfun5)){Led6_on;}//Led5_off;Led7_off;
        else Led6_off;        
      
      
        }
        
        //按鍵訊號處理
        if ((key3_f == 1) && key9_f)//功能3訓練 鍵9 :剪刀資料儲存
        {
            scissors_s = temp;
            Led5_on;
            key9_f = 0;
        }
        if ((key3_f == 1) && key10_f)//功能3訓練 鍵10 :石頭資料儲存
        {
            rock_s = temp;
            Led6_on;
            key10_f = 0;
        }
        if ((key3_f == 1) && key11_f)//功能3訓練 鍵11 :布資料儲存
        {
            paper_s = temp;
            Led7_on;
            key11_f = 0;
        }
        if ((key3_f == 2) && (key3_f_x))//功能3工作 
        {
            key3_f_x = 0;
            key9_f = 0;
            key10_f = 0;
            key11_f = 0;
            Led5_off;
            Led6_off;
            Led7_off;
            paper_p = (paper_s + rock_s) / 2;    //設定布和石頭分界
            rock_p = (rock_s + scissors_s) / 2;  //設定剪刀和石頭分界
        }
        if ((key4_f == 1) && key12_f)//功能4訓練 鍵12 :1資料儲存
        {
            num0_1_s = temp;
            Display_l(1);
            key12_f = 0;
        }
        if ((key4_f == 1) && key13_f)//功能4訓練 鍵13 :2資料儲存
        {
            num1_2_s = temp;
            Display_l(2);
            key13_f = 0;
        }
        if ((key4_f == 1) && key14_f)//功能4訓練 鍵14 :3資料儲存
        {
            num2_3_s = temp;
            Display_l(3);
            key14_f = 0;
        }
        if ((key4_f == 1) && key15_f)//功能4訓練 鍵15 :4資料儲存
        {
            num3_4_s = temp;
            Display_l(4);
            key15_f = 0;
        }
        if ((key4_f == 1) && key16_f)//功能4訓練 鍵16 :5資料儲存
        {
            num4_5_s = temp;
            Display_l(5);
            key16_f = 0;
        }
        if ((key4_f == 2) && (key4_f_x))//功能4工作
        {
            key4_f_x = 0;
            key12_f = 0;
            key13_f = 0;
            key14_f = 0;
            key15_f = 0;
            key16_f = 0;
            Display_l(16);
            num1_2_p = (num0_1_s + num1_2_s) / 2;//設定1和2分界
            num2_3_p = (num1_2_s + num2_3_s) / 2;//設定2和3分界
            num3_4_p = (num2_3_s + num3_4_s) / 2;//設定3和4分界
            num4_5_p = (num3_4_s + num4_5_s) / 2;//設定4和5分界
        }
//4種工作狀態
        if ((key1_f) || (key2_f) || (key3_f == 2) || (key4_f == 2))
        {
            if (temp > num0_1)              //如果數值大於下限,開始判別是哪個手勢
            {
                temp_pr = temp;//記錄第一次資料,延時
                delay_ms(delaytime);//延時設定時間
                temp0_h = ReadRegfdc2214(0x00); //讀取第1通道的值
                temp0_l = ReadRegfdc2214(0x01); //讀取第1通道的值
                temp0 = temp0_h;
                temp0 = (temp0 << 16) + temp0_l;
                if (temp0_zero > temp0)
                    temp0 = temp0_zero - temp0;
                else
                    temp0 = 0;
                temp0 = temp0 >> ratio;
                temp1_h = ReadRegfdc2214(0x02); //讀取第2通道的值
                temp1_l = ReadRegfdc2214(0x03); //讀取第2通道的值
                temp1 = temp1_h;
                temp1 = (temp1 << 16) + temp1_l;
                if (temp1_zero > temp1)
                    temp1 = temp1_zero - temp1;
                else
                    temp1 = 0;
                temp1 = temp1 >> ratio;
                temp2_h = ReadRegfdc2214(0x04); //讀取第3通道的值
                temp2_l = ReadRegfdc2214(0x05); //讀取第3通道的值
                temp2 = temp2_h;
                temp2 = (temp2 << 16) + temp2_l;
                if (temp2_zero > temp2)
                    temp2 = temp2_zero - temp2;
                else
                    temp2 = 0;
                temp2 = temp2 >> ratio;
                temp3_h = ReadRegfdc2214(0x06); //讀取第4通道的值
                temp3_l = ReadRegfdc2214(0x07); //讀取第4通道的值
                temp3 = temp3_h;
                temp3 = (temp3 << 16) + temp3_l;
                if (temp3_zero > temp3)
                    temp3 = temp3_zero - temp3;
                else
                    temp3 = 0;
                temp3 = temp3 >> ratio;
                temp_f = temp0 * s1 + temp1 * s2 + temp2 * s3 + temp3 * s4; //求4通道讀數之和
                temp = (unsigned int )temp_f;

                if(temp > temp_pr)Difference = temp - temp_pr;//記錄第二次資料,與延時前資料進行比較
                else Difference = temp_pr - temp;

                if(Difference < Stable)  //如果延時前後兩次資料相差小於設定值,則認為已經穩定,可以進行判斷。


                {

                    if ((key1_f) || (key3_f == 2))
                    {
                        if (temp > paper_p)//判定為紙
                        {
                            Led7_on;
                            Led6_off;
                            Led5_off;
                            numf1 = 3;
                        }
                        else if ((temp > rock_p) && (numf1 < 3))//判定為石頭
                        {
                            Led5_off;
                            Led6_on;
                            Led7_off;
                            numf1 = 2;
                        }
                        else if (numf1 < 2)//判定為剪刀
                        {
                            Led5_on;
                            Led6_off;
                            Led7_off;
                            numf1 = 1;
                        }
                    }
                    if ((key2_f) || (key4_f == 2))
                    {
                        if (temp > num4_5_p)//判定為5
                        {
                            Display_l(5);
                            numf = 5;
                        }
                        else if ((temp > num3_4_p) && (numf < 5))//判定為4
                        {
                            Display_l(4);
                            numf = 4;
                        }
                        else if ((temp > num2_3_p) && (numf < 4))//判定為3
                        {
                            Display_l(3);
                            numf = 3;
                        }
                        else if ((temp > num1_2_p) && (numf < 3))//判定為2
                        {
                            Display_l(2);
                            numf = 2;
                        }
                        else if (numf < 2)//判定為1
                        {
                            Display_l(1);
                            numf = 1;
                        }
                    }



                }
            }
            else
            {//無手勢,清顯示
                if ((key1_f) || (key3_f == 2))
                {
                    Led5_off;
                    Led6_off;
                    Led7_off;
                    numf1 = 0;
                }
                if ((key2_f) || (key4_f == 2))
                {
                    Display_l(0);
                    numf = 0;
                }
            }
        }
        //功能3、4訓練狀態時閃爍
        if (delayf && getdelayf() == 0)
        {
            delayf = 0;
            delaytim(300);
        }
        if ((delayf == 0) && getdelayf() == 0)
        {
            delayf = 1;
            ms_f = ~ms_f;
            if (key3_f == 1)
            {
                if (ms_f)
                    Led2_on;
                else
                    Led2_off;
            }
            else if (key3_f == 2)
                Led2_on;
            else
                Led2_off;
            if (key4_f == 1)
            {
                if (ms_f)
                    Led3_on;
                else
                    Led3_off;
            }
            else if (key4_f == 2)
                Led3_on;
            else
                Led3_off;
        }

        Display_h(temp);//顯示當前測量數值
        Key_Event();//檢測按鍵
        if (key_Flag == 1)//如果檢測到按鍵,進行按鍵標誌設定。
        {
            key_Flag = 0;
            buzzer_on;
            delay_ms(50);
            buzzer_off;
            switch (key_val)
            {
            case 1:
            {
                //鍵1 功能1
                key1_f = ~key1_f;
                if (key1_f)
                {
                    Led0_on;
                    Led2_off;
                    Led3_off;
                    Led4_off;
                    key3_f = 0;
                    key4_f = 0;
                    key5_f = 0;
                    rock_p = rock;
                    paper_p = paper;
                }
                else
                    Led0_off;
            }
            break;
            case 2:
            {
                //鍵2 功能2
                key2_f = ~key2_f;
                if (key2_f)
                {
                    Led1_on;
                    Led2_off;
                    Led3_off;
                    Led4_off;
                    key3_f = 0;
                    key4_f = 0;
                    key5_f = 0;
                    num1_2_p = num1_2;
                    num2_3_p = num2_3;
                    num3_4_p = num3_4;
                    num4_5_p = num4_5;
                }
                else
                    Led1_off;
            }
            break;
            case 3:
            {
                //鍵3 功能3
                Led0_off;
                Led1_off;
                Led2_on;
                Led3_off;
                Led4_off;
                key1_f = 0;
                key2_f = 0;
                key5_f = 0;
                if (key3_f < 2)
                    key3_f++;
                else
                    key3_f = 0;
                if (key3_f == 1)
                    key3_f_x = 1;
            }
            break;
            case 4:
            {
                //鍵4 功能4
                Led0_off;
                Led1_off;
                Led2_off;
                Led3_on;
                Led4_off;
                key1_f = 0;
                key2_f = 0;
                key5_f = 0;
                if (key4_f < 2)
                    key4_f++;
                else
                    key4_f = 0;
            }
            break;
            case 5:
            {
                //鍵5 功能5
                Led0_off;
                Led1_off;
                Led2_off;
                Led3_off;
                Led4_on;
                key1_f = 0;
                key2_f = 0;
                key3_f = 0;
                key4_f = 0;
                key5_f = 1;
            }
            break;
            case 6:
            {
                //清零鍵
                temp0_h = ReadRegfdc2214(0x00); //讀取第1通道的值
                temp0_l = ReadRegfdc2214(0x01); //讀取第1通道的值
                temp0 = temp0_h;
                temp0 = (temp0 << 16) + temp0_l;
                temp0_zero = temp0;
                temp1_h = ReadRegfdc2214(0x02); //讀取第2通道的值
                temp1_l = ReadRegfdc2214(0x03); //讀取第2通道的值
                temp1 = temp1_h;
                temp1 = (temp1 << 16) + temp1_l;
                temp1_zero = temp1;
                temp2_h = ReadRegfdc2214(0x04); //讀取第1通道的值
                temp2_l = ReadRegfdc2214(0x05); //讀取第1通道的值
                temp2 = temp2_h;
                temp2 = (temp2 << 16) + temp2_l;
                temp2_zero = temp2;
                temp3_h = ReadRegfdc2214(0x06); //讀取第2通道的值
                temp3_l = ReadRegfdc2214(0x07); //讀取第2通道的值
                temp3 = temp3_h;
                temp3 = (temp3 << 16) + temp3_l;
                temp3_zero = temp3;
            }
            break;
            case 7:
                break;
            case 8:
                break;
            case 9:
                key9_f = 1;
                key10_f = 0;
                key11_f = 0;
                break;
            case 10:
                key9_f = 0;
                key10_f = 1;
                key11_f = 0;
                break;
            case 11:
                key9_f = 0;
                key10_f = 0;
                key11_f = 1;
                break;
            case 12:
                key12_f = 1;
                key13_f = 0;
                key14_f = 0;
                key15_f = 0;
                key16_f = 0;
                break;
            case 13:
                key12_f = 0;
                key13_f = 1;
                key14_f = 0;
                key15_f = 0;
                key16_f = 0;
                break;
            case 14:
                key12_f = 0;
                key13_f = 0;
                key14_f = 1;
                key15_f = 0;
                key16_f = 0;
                break;
            case 15:
                key12_f = 0;
                key13_f = 0;
                key14_f = 0;
                key15_f = 1;
                key16_f = 0;
                break;
            case 16:
                key12_f = 0;
                key13_f = 0;
                key14_f = 0;
                key15_f = 0;
                key16_f = 1;
                break;
            default:
                break;
            }
        }
    }
}

​