MS51FB9AE – Điều khiển từ xa bằng RF

Như mình đã nói ở trước là chỉ cần chủ động được GPIO và Timer là đã có thể làm được rất nhiều việc với Vi điều khiển.
Hôm nay mình sẽ viết về ứng dụng làm điều khiển từ xa bằng sóng RF với tay phát RF 433 MHz, sử dụng chip EV1527.
Khi đã hiểu được nguyên tắc thì có thể áp dụng để giải mã và làm điều khiển từ xa bằng hồng ngoại hoặc nhiều ứng dụng khác.
Tay phát RF mình dùng loại này

Bộ thu RF mình dùng loại này

Về bộ thu và bộ phát thì cần tương ứng với nhau về tần số thì mới hoạt động được.
Mình dùng logic analyzer đo thử tín hiệu của tay phát RF (đo tại chân tín hiệu của bộ thu)

Cách mã hóa của chip EV1527
Mỗi khung dữ liệu có 24 bit trong đó 20 bit đầu tiên là địa chỉ của module phát.

4 bit cuối cùng là 4 bit dữ liệu tương đương với 4 nút nhấn trên bộ điều khiển.
Mỗi khi ấn nút của 1 bộ điều khiển thì tín hiệu phát ra sẽ giống nhau 20 bit đầu tiên và 4 bit cuối sẽ khác nhau tùy thuộc vào nút nhấn.
Sẽ mã hóa được 2 mũ 20 bằng cỡ 1 triệu tay phát. Mỗi tay phát mã hóa được 2 mũ 4 – 1 bằng 15 lệnh. Tuy nhiên về cơ bản chỉ sử dụng 4 lệnh tương đương với 4 nút.
Mỗi khung dữ liệu truyền đi sẽ bắt đầu bằng Preamble rồi đến 20 bit địa chỉ và cuối cùng là 4 bit dữ liệu

Hình ảnh thực tế đo bằng mạch logic analyzer

Ví dụ khi ấn nút A trên tay phát và đo tín hiệu thấy thu được như sau

* Preamble
– Phần cao cỡ 0.3ms

– Phần thấp cỡ 9.9ms

* Các bit dữ liệu và địa chỉ:
– Bit 0:
+ Phần cao cỡ 0.3ms

+ Phần thấp cỡ 0.98ms

Bắt tay vào viết code
Dùng chân P15 làm chân nhận tín hiệu RF
Chân P14 điều khiển rơ le

Chương trình sẽ đóng/ngắt rơ le mỗi khi nhấn nút A từ tay phát RF
Chương trình con giải mã RF

#include "myRF.h"

static void Tim0SetValue(uint16_t u16Value);
static uint16_t Tim0GetValue(void);

void Tim0SetValue(uint16_t u16Value)
{
   
    TL0 = u16Value;
    TH0 = (u16Value >> 8);
}

uint16_t Tim0GetValue(void)
{
   
    return TH0 * 256 + TL0;
}

void RfInit(void)
{
    CKCON |= (1 << 3);
    TMOD &= ~(0x0F);
    TMOD |= 0x01;
    TR0 = 1;
   
    RF_PIN_INIT;
}

uint32_t RfDecode(void)
{
    uint32_t u32Result = 0;
    uint8_t u8Count = 0;
    uint8_t u8TimeOut = 0;
   
    if (RF_PIN) {
        return 0;
    }
   
    Tim0SetValue(0);
    u8TimeOut = 0;
    u8Count = 0;
    while (1) {
        if (RF_PIN) {
            break;
        }
        while (Tim0GetValue() < 16000) {
        }
        Tim0SetValue(0);
        ++u8Count;
        if (u8Count > 11) {
            u8TimeOut = 1;
            break;
        }
    }
   
    if (u8TimeOut) {
        return 0;
    }
   
    if (u8Count < 9) {
        return 0;
    }
   
    u8Count = 0;
    u32Result = 0;
    while (1) {
        Tim0SetValue(0);
        u8TimeOut = 0;
        while (1) {
            if (!RF_PIN) {
                break;
            }
            if (Tim0GetValue() > 20000) {
                u8TimeOut = 1;
                break;
            }
        }
        if (u8TimeOut) {
            return 0;
        }
        if (Tim0GetValue() > 8000) {
            u32Result <<= 1;
            u32Result |= 0x01;
        } else {
            u32Result <<= 1;
        }
       
        Tim0SetValue(0);
        u8TimeOut = 0;
        while (1) {
            if (RF_PIN) {
                break;
            }
            if (Tim0GetValue() > 20000) {
                u8TimeOut = 1;
                break;
            }
        }
        if (u8TimeOut) {
            return 0;
        }
        ++u8Count;
        if (u8Count == 24) {
            break;
        }
    }
   
    return u32Result;
}

Chương trình chính

#include "ms51.h"
#include "myDelay.h"
#include "myRF.h"

uint8_t u8Led = 0;

void main(void)
{
    P1M1 &= ~(1 << 4);
    P1M2 |= (1 << 4);
   
    DelayInit();
    RfInit();
   
    P14 = 0;
   
    while (1) {
        if (RfDecode() == CMD_A) {
            if (u8Led) {
                u8Led = 0;
                P14 = 0;
            } else {
                u8Led = 1;
                P14 = 1;
            }
            DelayMs(500);
        }
    }
}

Project
http://vidieukhien.org/rf433