ขอคำแนะนำ การเขียนโปรแกรมรับค่าจาก IR Remote Control Kit หน่อยครับ

  • 25 Replies
  • 7543 Views
*

Offline JENG

  • *****
  • 808
  • รู้ทุกเรื่องเว้นเรื่องจริง
    • View Profile
dead loop เยอะไปหน่อย เี่ดี๋ยวหาบอร์ดมาลองเทสก่อน
สามารถติดตาม electoday ได้ที่

Facebook
www.facebook.com/groups/coopmicro

Google+
https://plus.google.com/communities/103482067769375459277

☺☺☺ความรู้ และความฉลาด ไม่ใช่สิ่งเดียวกัน จะมีประโยชน์อะไร ถ้าฉลาดแต่อยู่ในกะลา☺☺☺


*

Offline JENG

  • *****
  • 808
  • รู้ทุกเรื่องเว้นเรื่องจริง
    • View Profile
มันพอใช้ได้นะไปเรียบเรียงเอาหน่อย ของเดิมมั่วไม่ไหว เลยด้นเขียนใหม่จากตัวอย่างของ avr ที่เคยทำไว้

Code: [Select]
//--------------------------------------------------
//  Program     :IR-Remote receiver NEC protocol
//  Author      :Somlak Mangnimit(JENG)
//  Date        :23/08/2013
//  Device      :PIC16F877
//  XTAL        :4MHZ
//  Compiler    :CCS V4.114
//--------------------------------------------------

#include <16F877.h>
#fuses  HS,NOLVP,NOWDT,NOPROTECT
#use delay (clock = 4000000)    // Crytal = 4MHz
#include "LCD.c"
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)

#define  IR_PIN  PIN_B0
#define IR_RISING()         ext_int_edge(L_TO_H)
#define IR_FALLING()        ext_int_edge(H_TO_L)
volatile unsigned char IR_STATE;
volatile unsigned long  BIT_BUF;
volatile unsigned char buffer[4];
#define Adr                 buffer[0]
#define AdrInv              buffer[1]
#define Cmd                 buffer[2]
#define CmdInv              buffer[3]
volatile unsigned char bit_flag, bit_cnt, byte_cnt, ndat;
enum{ir_state1=0, ir_state2, ir_state3, ir_state4};

#INT_EXT
void int_service1(void){

    ir_read();

}

//--------------------------------------------------
//
//
//
//--------------------------------------------------
void reset_ir(void){

    IR_STATE = ir_state1;
    bit_flag = 0;
    byte_cnt = 0;
    bit_cnt = 0;
    IR_FALLING();

}

//--------------------------------------------------
//
//
//
//--------------------------------------------------
unsigned char log_inv(unsigned char a,unsigned char b){
    a ^= a;
    if(a==b){return 0;}
    else{return 1;}
}

//--------------------------------------------------
//
//
//
//--------------------------------------------------
void ir_read(void){

    switch(IR_STATE){

        //-----------------------------------
        case ir_state1:
            IR_STATE++;
            IR_RISING();
            set_timer1(0);
        break;

        //-----------------------------------
        case ir_state2:
            BIT_BUF = get_timer1();
            if(BIT_BUF>9000-300 && BIT_BUF<9000+300){
                IR_STATE++;
                IR_FALLING();
                set_timer1(0);
            }else{
                reset_ir();
            }
        break;

        //-----------------------------------
        case ir_state3:
            BIT_BUF = get_timer1();
            if(BIT_BUF>4400-300 && BIT_BUF<4400+300){
                IR_STATE++;
                IR_RISING();
                set_timer1(0);
            }else{
                reset_ir();
            }
        break;

        //-----------------------------------
        case ir_state4:
            if(!bit_flag){
                bit_flag = 1;
                IR_FALLING();
                set_timer1(0);
            }else{
                bit_flag = 0;
                BIT_BUF = get_timer1();

                buffer[byte_cnt] >>= 1;         //LSB

                if(BIT_BUF>1500&&BIT_BUF<1700){

                buffer[byte_cnt] |= 0x80;}

                else if(BIT_BUF>300&&BIT_BUF<600){

                buffer[byte_cnt] &= ~0x80;}

                else{RESET_IR();break;}

                IR_RISING();
            }

            if(++bit_cnt>15){
                if(++byte_cnt>3){
                    RESET_IR();
                    if(log_inv(Adr,AdrInv)&&log_inv(Cmd,CmdInv)){
                        ndat = 1;
                    }
                }
                else{bit_cnt = 0;}
            }
        break;

    }

}


//--------------------------------------------------
//
//
//
//--------------------------------------------------
void main(){

    set_tris_C(0x00);
    enable_interrupts(INT_EXT);  // Enable Interrupt Capture
    enable_interrupts(GLOBAL);    // Enable Interrupt Global
    lcd_init();
    lcd_gotoxy(1,1);
    printf(lcd_putc,"TEST IR Remote..");
    output_C(0xF0);
    delay_ms(1000);
    output_C(0x00);
    lcd_gotoxy(1,1);
    printf(lcd_putc,"Address = %lX    ",Adr);
    lcd_gotoxy(1,2);
    printf(lcd_putc,"Command = %lX    ",Cmd);
    setup_counters(RTCC_INTERNAL,RTCC_DIV_1);    // Get low
    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
    BIT_BUF = 0;
    reset_ir();

    for(;;){
        if(ndat){
        ndat = 0;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"Address = %lX    ",Adr);
            lcd_gotoxy(1,2);
            printf(lcd_putc,"Command = %lX    ",Cmd);
        }
        output_high(PIN_C7);
        delay_ms(200);
        output_low(PIN_C7);
        delay_ms(200);
    }
}


สามารถติดตาม electoday ได้ที่

Facebook
www.facebook.com/groups/coopmicro

Google+
https://plus.google.com/communities/103482067769375459277

☺☺☺ความรู้ และความฉลาด ไม่ใช่สิ่งเดียวกัน จะมีประโยชน์อะไร ถ้าฉลาดแต่อยู่ในกะลา☺☺☺

ขอบคุณ ท่าน JENG มากครับ ที่เสียสละเวลา

แต่ตอนแรกก็ยังไม่เวิค เนื่องจากเวลาที่ตรวจจับได้นั้นมีความคลาดเคลื่อนจากที่ทฤษฎีมากครับ
ต้องทำการสั่ง Print ค่าเวลาให้แต่ช่วงต่างๆดู ถึงได้รู้ และได้ปรับเปลี่ยนตามความเหมาะสมถึงได้เวิคครับ

ขอบคุณท่าน JENG อีกครั้งครับ :)

ของ pic เจอแต่ sony-protocol ครับ  :P

Code: [Select]
//--------------------------------------------------
// Program  :IR Receiver (SIRC Protocol)
// Author   :Somlak Mangnimit
// Date     :21/03/2012
// Device   :PIC16F676 @int clock 4Mhz
//--------------------------------------------------
#include    <htc.h>
#define     _XTAL_FREQ 4000000
__CONFIG(FOSC_INTRCIO&WDTE_ON&MCLRE_OFF);

#define     LED1            PORTCbits.RC0
#define     LED2            PORTCbits.RC1
#define     LED3            PORTCbits.RC2
#define     LED4            PORTCbits.RC3
#define     LED5            PORTCbits.RC4
#define     LED6            PORTCbits.RC5
#define     LED7            PORTAbits.RA4
#define     LED8            PORTAbits.RA5

#define     ClrWDT();       asm("CLRWDT");

volatile unsigned char
Current_state,Counter,Got_data,bit_count,Command_code,
Device_code,WaitRelease
;

volatile unsigned int
input_data
;

enum{
Idle,Start_bit,Capture_bit
};

//------------------------------------------------
// Interrupt Service
//------------------------------------------------
void interrupt service(void){
//-------------------------
// External interrupt RB0
//-------------------------
    if(INTF){
        switch (Current_state){
            case Idle:
                INTEDG = 1;                     //interrupt on rising edge.
                Counter = 0;
                Current_state = Start_bit;
            break;
            //-------------------------
            // found the rising edge,
            // check lenght for 2.4ms
            //-------------------------
            case Start_bit:
                if(Counter == 4){               //correct signal, move on to next state
                    Counter = 0;
                    bit_count = 0;
                    input_data = 0;
                    Current_state = Capture_bit;
                }

                else {
                    INTEDG = 0;             //interrupt on falling edge.
                    Current_state = Idle;       //fault signal, reset to Idle
                }
            break;
            //-------------------------
            // check plus length
            // for 0 or 1
            //-------------------------
            case Capture_bit:
                if(Counter == 2){
                    input_data >>= 1;           // add 0 to received data
                    bit_count++;
                } 
                else{
                    if(Counter == 3){
                        input_data >>= 1;
                        input_data |= 0x8000;   //add 1 to received data
                        bit_count++;
                    }
                    //-------------------------
                    // error occurs,
                    // reset to Idle state
                    //-------------------------
                    else{
                        INTEDG = 0;             //interrupt on falling edge.
                        Current_state = Idle;
                    }
                }
                //-------------------------
                //compleat 12 bit
                //-------------------------
                if(bit_count >= 12){
                    Got_data = 1;
                    input_data >>= 4;
                    INTEDG = 0;                 //interrupt on falling edge.
                    Current_state = Idle;
                }
                Counter = 0;
            break;

            default:
                INTEDG = 0;                     //interrupt on falling edge.
                Current_state = Idle;
        }
        INTF = 0;                               //clear interrupt flag.
    }

    if(T0IF){
        TMR0 = 110;     //600us@4mhz
        T0IF = 0;       //Clear flag
        Counter++;

        if(Counter>5){
            INTEDG = 0;                     //interrupt on falling edge.
            Current_state = Idle;
        }

        if(Counter>40){
            LED8 = 0;
        }

        if(Counter>50){
            WaitRelease = 0;
        }
        ClrWDT();
    }
}

//--------------------------------------------------
// Initial start up
//--------------------------------------------------
void Start_up(void){
PORTA = 0x00;
PORTC = 0x00;

ANSEL = 0x00;               //All digital I/O
CMCON = 0x05;               //Turn off comparator
ADCON0 = 0x00;

TRISA = 0x00;
TRISC = 0x00;

TRISAbits.TRISA2 = 1;       //IR input
TRISAbits.TRISA3 = 1;       //Sw input

//-----
T0CS = 0;
PSA = 0;                    //prescaler timer0
PS2 = 0;                    //1:4
PS1 = 0;
PS0 = 1;
INTEDG = 0;                 //Falling edge

//-----
T0IE = 1;
INTE = 1;                   //External interrupt
PEIE = 1;                   //Peripheral interrupt
GIE = 1;                    //Global interrupt

}

//--------------------------------------------------
// Main program
//--------------------------------------------------
void main(void){
Start_up();

    while(1){
        if(Got_data){
            Command_code = input_data & 0x7F;
            Device_code = input_data >> 7;
            Got_data = 0;
            if(Device_code == 1 && !WaitRelease){
            WaitRelease = 1;
                switch (Command_code){
                    case 0: LED1 = ~LED1; LED8 = 1;break;
                    case 1: LED2 = ~LED2; LED8 = 1;break;
                    case 2: LED3 = ~LED3; LED8 = 1;break;
                    case 3: LED4 = ~LED4; LED8 = 1;break;
                    case 4: LED5 = ~LED5; LED8 = 1;break;
                    case 5: LED6 = ~LED6; LED8 = 1;break;
                    //case 6: LED7 = ~LED7; LED8 = 1;break;
                    //case 7: LED8 = ~LED8; break;
                }
            }
        }
    }
}

Code: [Select]
...
    if(T0IF){
...
        ClrWDT();
    }
...

ใน code นี้ ของท่าน Jeng  ขอทักเรื่องการใช้ Trigger watchdog นะครับ เผื่อท่านจะลืมไป
ถ้าไม่มีเหตุผลอื่นใด ก็ไม่ควรทำการ trigger watchdog  ให้อยู่ใน Timer Interrupt นะครับ มันผิดหลักการใช้งาน watchdog ครับ
จะทำการ trigger watchdog ใน ISR ควรมีเหตุผลที่สมควรประกอบด้วยครับ ทำแบบโต้งๆนี้ไม่ควรครับ (เช่นต้องการตรวจสอบ variable/flag บางตัว แล้วหากผิดพลาดจึงใหทำการ trigger watchdog อะไรทำนองนี้ จะเป็นเหตุเป็นผลมากกว่าครับ)

"Stay Hungry, Stay Foolish"
จงกระหาย และ ทำตัวโง่ให้ตลอดเวลา
"Innovation distinguishes between a leader and a follower."
นวัตกรรมแยกผู้นำกับผู้ตามออกจากกัน

คนฉลาด...ต้องโง่เป็น คนโง่ไม่เป็น...จะไม่มีทางฉลาด

*

Offline JENG

  • *****
  • 808
  • รู้ทุกเรื่องเว้นเรื่องจริง
    • View Profile
ของ pic เจอแต่ sony-protocol ครับ  :P

Code: [Select]
//--------------------------------------------------
// Program  :IR Receiver (SIRC Protocol)
// Author   :Somlak Mangnimit
// Date     :21/03/2012
// Device   :PIC16F676 @int clock 4Mhz
//--------------------------------------------------
#include    <htc.h>
#define     _XTAL_FREQ 4000000
__CONFIG(FOSC_INTRCIO&WDTE_ON&MCLRE_OFF);

#define     LED1            PORTCbits.RC0
#define     LED2            PORTCbits.RC1
#define     LED3            PORTCbits.RC2
#define     LED4            PORTCbits.RC3
#define     LED5            PORTCbits.RC4
#define     LED6            PORTCbits.RC5
#define     LED7            PORTAbits.RA4
#define     LED8            PORTAbits.RA5

#define     ClrWDT();       asm("CLRWDT");

volatile unsigned char
Current_state,Counter,Got_data,bit_count,Command_code,
Device_code,WaitRelease
;

volatile unsigned int
input_data
;

enum{
Idle,Start_bit,Capture_bit
};

//------------------------------------------------
// Interrupt Service
//------------------------------------------------
void interrupt service(void){
//-------------------------
// External interrupt RB0
//-------------------------
    if(INTF){
        switch (Current_state){
            case Idle:
                INTEDG = 1;                     //interrupt on rising edge.
                Counter = 0;
                Current_state = Start_bit;
            break;
            //-------------------------
            // found the rising edge,
            // check lenght for 2.4ms
            //-------------------------
            case Start_bit:
                if(Counter == 4){               //correct signal, move on to next state
                    Counter = 0;
                    bit_count = 0;
                    input_data = 0;
                    Current_state = Capture_bit;
                }

                else {
                    INTEDG = 0;             //interrupt on falling edge.
                    Current_state = Idle;       //fault signal, reset to Idle
                }
            break;
            //-------------------------
            // check plus length
            // for 0 or 1
            //-------------------------
            case Capture_bit:
                if(Counter == 2){
                    input_data >>= 1;           // add 0 to received data
                    bit_count++;
                } 
                else{
                    if(Counter == 3){
                        input_data >>= 1;
                        input_data |= 0x8000;   //add 1 to received data
                        bit_count++;
                    }
                    //-------------------------
                    // error occurs,
                    // reset to Idle state
                    //-------------------------
                    else{
                        INTEDG = 0;             //interrupt on falling edge.
                        Current_state = Idle;
                    }
                }
                //-------------------------
                //compleat 12 bit
                //-------------------------
                if(bit_count >= 12){
                    Got_data = 1;
                    input_data >>= 4;
                    INTEDG = 0;                 //interrupt on falling edge.
                    Current_state = Idle;
                }
                Counter = 0;
            break;

            default:
                INTEDG = 0;                     //interrupt on falling edge.
                Current_state = Idle;
        }
        INTF = 0;                               //clear interrupt flag.
    }

    if(T0IF){
        TMR0 = 110;     //600us@4mhz
        T0IF = 0;       //Clear flag
        Counter++;

        if(Counter>5){
            INTEDG = 0;                     //interrupt on falling edge.
            Current_state = Idle;
        }

        if(Counter>40){
            LED8 = 0;
        }

        if(Counter>50){
            WaitRelease = 0;
        }
        ClrWDT();
    }
}

//--------------------------------------------------
// Initial start up
//--------------------------------------------------
void Start_up(void){
PORTA = 0x00;
PORTC = 0x00;

ANSEL = 0x00;               //All digital I/O
CMCON = 0x05;               //Turn off comparator
ADCON0 = 0x00;

TRISA = 0x00;
TRISC = 0x00;

TRISAbits.TRISA2 = 1;       //IR input
TRISAbits.TRISA3 = 1;       //Sw input

//-----
T0CS = 0;
PSA = 0;                    //prescaler timer0
PS2 = 0;                    //1:4
PS1 = 0;
PS0 = 1;
INTEDG = 0;                 //Falling edge

//-----
T0IE = 1;
INTE = 1;                   //External interrupt
PEIE = 1;                   //Peripheral interrupt
GIE = 1;                    //Global interrupt

}

//--------------------------------------------------
// Main program
//--------------------------------------------------
void main(void){
Start_up();

    while(1){
        if(Got_data){
            Command_code = input_data & 0x7F;
            Device_code = input_data >> 7;
            Got_data = 0;
            if(Device_code == 1 && !WaitRelease){
            WaitRelease = 1;
                switch (Command_code){
                    case 0: LED1 = ~LED1; LED8 = 1;break;
                    case 1: LED2 = ~LED2; LED8 = 1;break;
                    case 2: LED3 = ~LED3; LED8 = 1;break;
                    case 3: LED4 = ~LED4; LED8 = 1;break;
                    case 4: LED5 = ~LED5; LED8 = 1;break;
                    case 5: LED6 = ~LED6; LED8 = 1;break;
                    //case 6: LED7 = ~LED7; LED8 = 1;break;
                    //case 7: LED8 = ~LED8; break;
                }
            }
        }
    }
}

Code: [Select]
...
    if(T0IF){
...
        ClrWDT();
    }
...

ใน code นี้ ของท่าน Jeng  ขอทักเรื่องการใช้ Trigger watchdog นะครับ เผื่อท่านจะลืมไป
ถ้าไม่มีเหตุผลอื่นใด ก็ไม่ควรทำการ trigger watchdog  ให้อยู่ใน Timer Interrupt นะครับ มันผิดหลักการใช้งาน watchdog ครับ
จะทำการ trigger watchdog ใน ISR ควรมีเหตุผลที่สมควรประกอบด้วยครับ ทำแบบโต้งๆนี้ไม่ควรครับ (เช่นต้องการตรวจสอบ variable/flag บางตัว แล้วหากผิดพลาดจึงใหทำการ trigger watchdog อะไรทำนองนี้ จะเป็นเหตุเป็นผลมากกว่าครับ)



น่าจะติดมาจาก code เดิมของเว๊บบอร์ดต่างประเทศน่ะครับ ของเดิมน่าจะเป็น avr ผมเอามาแปลงตรงๆ จำได้ว่าตอนนั้นผมเพิ่งมาหัดเขียน c ใหม่ๆ  :)
สามารถติดตาม electoday ได้ที่

Facebook
www.facebook.com/groups/coopmicro

Google+
https://plus.google.com/communities/103482067769375459277

☺☺☺ความรู้ และความฉลาด ไม่ใช่สิ่งเดียวกัน จะมีประโยชน์อะไร ถ้าฉลาดแต่อยู่ในกะลา☺☺☺

*

Offline JENG

  • *****
  • 808
  • รู้ทุกเรื่องเว้นเรื่องจริง
    • View Profile
ขอบคุณ ท่าน JENG มากครับ ที่เสียสละเวลา

แต่ตอนแรกก็ยังไม่เวิค เนื่องจากเวลาที่ตรวจจับได้นั้นมีความคลาดเคลื่อนจากที่ทฤษฎีมากครับ
ต้องทำการสั่ง Print ค่าเวลาให้แต่ช่วงต่างๆดู ถึงได้รู้ และได้ปรับเปลี่ยนตามความเหมาะสมถึงได้เวิคครับ

ขอบคุณท่าน JENG อีกครั้งครับ :)

ค่าเวลาผมอ่านจาก timer1 ก็ตรงดีนะ บอกมั่งซิท่านปรับแบบไหนถึงใช้ได้ผมได้เอามาลองบ้าง ;D
สามารถติดตาม electoday ได้ที่

Facebook
www.facebook.com/groups/coopmicro

Google+
https://plus.google.com/communities/103482067769375459277

☺☺☺ความรู้ และความฉลาด ไม่ใช่สิ่งเดียวกัน จะมีประโยชน์อะไร ถ้าฉลาดแต่อยู่ในกะลา☺☺☺

Code ที่ท่าน JENG ให้มานั้น เมื่อนำมาทดลองกับของผมแล้ว
ผลคือ กดปุ่มที่ Remote ซักประมาณ 10 กว่าครั้ง จะได้ค่า address command ได้ซักครั้ง

ผมก็เลยแก้โค๊ดโดยการสั่งให้ led ติดในแต่ละ state เมื่อมันทำงานใน state นั้นเสร็จ
ผลคือ led มันไม่ติดใน state ที่ 4 (จากโค๊ด)
ผมก็เลยสั่ง print ค่า Timer ใน state นั้นดู พบว่าในการเกิด Logic 1

--------------Logic 1--------------
|----------|
|             |
|             |_______________|
    560               1690


ที่ช่วง Low (1690) Timer ผมมันอ่านค่าได้ประมาณ 2XXX ครับ ผมเลยปรับเงื่อนในส่วนนี้ใหม่ครับ แล้วก็เวิคเลยครับ

ขอบคุณครับ :)