Trong dự án này, chúng tôi sẽ sử dụng vi điều khiển PIC để điều khiển từ xa một số tải AC bằng cách chỉ sử dụng điều khiển từ xa IR. Một dự án tương tự Tự động hóa nhà điều khiển từ xa bằng IR cũng đã được thực hiện với Arduino, nhưng ở đây chúng tôi đã thiết kế nó trên PCB bằng cách sử dụng trình mô phỏng và thiết kế PCB trực tuyến của EasyEDA, đồng thời sử dụng các dịch vụ thiết kế PCB của họ để đặt hàng các bảng PCB như được hiển thị trong phần tiếp theo của bài báo.
Khi kết thúc dự án này, bạn sẽ có thể bật / tắt (BẬT / TẮT) bất kỳ tải AC nào bằng Điều khiển từ xa thông thường từ sự thoải mái của Ghế / Giường của bạn. Để làm cho dự án này thú vị hơn, chúng tôi cũng đã kích hoạt tính năng điều khiển tốc độ của quạt với sự trợ giúp của Triac. Tất cả những điều này có thể được thực hiện bằng những cú nhấp chuột đơn giản trên điều khiển từ xa IR của bạn. Bạn có thể sử dụng bất kỳ điều khiển từ xa TV / DVD / MP3 nào cho dự án này. Các tín hiệu IR khác nhau từ điều khiển từ xa được nhận bởi bộ vi điều khiển, sau đó sẽ điều khiển các rơ le tương ứng thông qua một mạch điều khiển rơ le. Các rơ le này được sử dụng để kết nối và ngắt kết nối các Tải AC (Đèn / Quạt).
Working Explanation:
Components
The components required to build this project is given below:
- PIC18f2520 Microcontroller -1
- TSOP1738 -1
- IR TV/DVD Remote -1
- Transistor BC547 -4
- Relays 12 volt -4
- Bulb with holder -5
- Connecting wires -
- EasyEda PCB -1
- 16x2 LCD
- Power supply 12v
- Terminal connector 2 pin ` -8
- Terminal Connector 3 pin -1
- Transformer 12-0-12 -1 -
- Voltage Regulator 7805 -1
- Voltage Regulator 7812 -1
- Capacitor 1000uf -1
- Capacitor 10uf -1
- Capacitor 0.1uf -1
- Capacitor 0.01uf 400V ` -1
- 10k -5
- 1k -5
- 100ohm -7
- Common cathode segment -1
- 1n4007 diode -10
- BT136 triac -1
- Male/female header -
- LEDs -6
- Opto-coupler moc3021 -1
- Opto-coupler mtc2e or 4n35 -1
- 20Mhz crystal -1
- 33pf capacitor -2
- 5.1v zener diode -1
- 47 ohm 2 watt resistor -1
Tất cả các thành phần này đều được sử dụng phổ biến và có thể dễ dàng mua được. Tuy nhiên, nếu bạn đang tìm kiếm cách mua hàng trực tuyến tốt nhất thì chúng tôi khuyên bạn nên sử dụng LCSC.
LCSC là một cửa hàng trực tuyến tuyệt vời để mua các linh kiện điện tử của bạn cho tất cả các loại dự án. Họ có khoảng 25.000 loại linh kiện và điều tốt nhất là họ bán các mặt hàng số lượng ít cho các dự án nhỏ và họ cũng có Vận chuyển toàn cầu.
Giải mã điều khiển từ xa IR:
Như đã nói trước đó, bạn có thể sử dụng bất kỳ loại điều khiển từ xa nào cho dự án của mình. Nhưng chúng ta phải biết loại tín hiệu được tạo ra từ điều khiển từ xa cụ thể đó. Đối với mỗi khóa riêng lẻ trên điều khiển từ xa sẽ có một giá trị HEX tương đương cho khóa đó. Sử dụng giá trị HEX này, chúng tôi có thể phân biệt giữa từng khóa ở phía bộ vi điều khiển của chúng tôi. Vì vậy, trước khi quyết định sử dụng một điều khiển từ xa, chúng ta nên biết giá trị HEX cho các phím được cài đặt trước trong điều khiển từ xa cụ thể đó. Trong dự án này, chúng tôi đã sử dụng điều khiển từ xa NEC. Các giá trị HEX cho các khóa trên điều khiển từ xa NEC được đưa ra bên dưới.
Như bạn có thể nhận thấy giá trị HEX có 7 ký tự, trong đó chỉ có hai ký tự cuối cùng khác nhau, do đó chúng ta chỉ có thể xem xét hai chữ số cuối cùng để phân biệt giữa mỗi khóa.
Circuit Diagram:
The schematic for the project is shown below.
Programming:
Chương trình cho dự án này được thực hiện bằng MPLABX, mã cũng khá đơn giản và dễ hiểu. Mã hoàn chỉnh sẽ được đưa ra ở cuối hướng dẫn này, một số phần quan trọng khác của chương trình được giải thích bên dưới.
Trong phần đầu của mã, chúng ta nên bao gồm các thư viện bắt buộc, xác định các chân và khai báo các biến.
#include <xc.h> #include<string.h> #include<stdlib.h> #include "config.h" #define tric RB1 #define ir RB2 #define relay1 RC2 #define relay2 RC3 #define relay3 RC4 #define relay4 RC5 #define rly1LED RB3 #define rly2LED RB4 #define rly3LED RB5 #define rly4LED RC1 #define fanLED RC0 int flag=0; int cmd=0; int speed=5; unsigned int dat[100]; int i=0; char result[10]; int j=0;
Sau đó, chúng ta đã tạo một hàm trì hoãn đơn giản bằng cách sử dụng vòng lặp “for”.
void delay(int time) { for(int i=0;i<time;i++) for(int j=0;j<800;j++); }
Sau đó, chúng tôi đã khởi tạo bộ đếm thời gian bằng cách sử dụng chức năng sau
void timer() // 10 -> 1us { T0PS0=0; T0PS1=0; T0PS2=0; PSA=0; //Timer Clock Source is from Prescaler T0CS=0; //Prescaler gets clock from FCPU (5MHz) T08BIT=0; //16 BIT MODE TMR0IE=1; //Enable TIMER0 Interrupt PEIE=1; //Enable Peripheral Interrupt GIE=1; //Enable INTs globally TMR0ON=1; //Now start the timer! }
Bây giờ trong chức năng chính, chúng ta đã đưa ra hướng cho các chân đã chọn và khởi tạo bộ định thời và ngắt bên ngoài int0 để phát hiện giao nhau bằng không.
ADCON1=0b00001111; TRISB1=0; TRISB2=1; TRISB3=0; TRISB4=0; TRISB5=0; TRISC=0x00; TRISA=0x00; PORTA=0xc0; TRISB6=0; RB6=1; relay1=0; relay2=0; relay3=0; relay4=0; rly1LED=0; rly3LED=0; rly2LED=0; rly4LED=0; fanLED=0; i=0; ir=0; tric=0; timer(); INTEDG0 = 0; // Interrupt on falling edge INT0IE = 1; // Enable the INT0 external interrupt (RB0) INT0IF = 0; // Clears INT0 External Interrupt Flag bit PEIE=1; //Enable Peripheral Interrupt GIE=1; //Enable INTs globally
Bây giờ, ở đây chúng tôi không sử dụng bất kỳ chế độ ngắt hoặc chụp và so sánh nào để phát hiện tín hiệu IR. Ở đây chúng ta vừa sử dụng chốt kỹ thuật số để đọc dữ liệu giống như đọc nút nhấn. Bất cứ khi nào tín hiệu tăng cao hoặc thấp, chúng tôi chỉ cần đặt phương pháp gỡ lỗi và chạy bộ đếm thời gian. Bất cứ khi nào pin thay đổi trạng thái của nó sang trạng thái khác thì các giá trị thời gian sẽ được lưu trong một mảng.
IR từ xa gửi logic 0 là 562,5us và logic 1 là 2250us. Bất cứ khi nào bộ đếm thời gian đọc khoảng 562,5us thì chúng tôi giả sử nó là 0 và khi bộ đếm thời gian đọc khoảng 2250us thì chúng tôi giả định nó là 1. Sau đó, chúng tôi chuyển đổi nó thành hex.
Tín hiệu đến từ điều khiển từ xa chứa 34 bit. Chúng tôi lưu trữ tất cả các byte trong mảng và sau đó giải mã byte cuối cùng để sử dụng.
while(ir == 1); INT0IE = 0; while(ir == 0); TMR0=0; while(ir == 1); i++; dat[i]=TMR0; if(dat[1] > 5000 && dat[1]<12000) { } else { i=0; INT0IE = 1; } if(i>=33) { GIE=0; delay(50); cmd=0; for(j=26;j<34;j++) { if(dat[j]>1000 && dat[j]<2000) cmd<<=1; else if(dat[j]>3500 && dat[j]<4500) { cmd|=0x01; cmd<<=1; } } cmd>>=1;
Đoạn mã trên nhận và giải mã tín hiệu IR bằng cách sử dụng ngắt bộ định thời và lưu giá trị HEX tương ứng trong biến cmd. Bây giờ chúng ta có thể so sánh giá trị HEX này (biến cmd) với các giá trị HEX được xác định trước của chúng ta và chuyển đổi rơ le như hình dưới đây
if(cmd == 0xAF) { relay1=~relay1; rly1LED=~rly1LED; } else if(cmd == 0x27) { relay2=~relay2; rly2LED=~rly2LED; } else if(cmd == 0x07) { relay3=~relay3; rly3LED=~rly3LED; } else if(cmd == 0xCF) { relay4=~relay4; rly4LED=~rly4LED; } else if(cmd == 0x5f) { speed++; if(speed>5) { speed=5; } } else if(cmd == 0x9f) { speed--; if(speed<=0) { speed=0; } }
Bây giờ để biết quạt của chúng ta hiện đang hoạt động, chúng ta nên sử dụng màn hình 7 đoạn. Các dòng sau đây được sử dụng để hướng dẫn các chân của màn hình 7 đoạn.
if(speed == 5) // turned off 5x2= 10ms triger //speed 0 { PORTA=0xC0; // display 0 RB6=1; fanLED=0; } else if(speed == 4 ) // 8 ms trigger //speed 1 { PORTA=0xfc; // displaying 1 RB6=1; fanLED=1; } else if(speed == 3) // 6 ms trigger // speed 2 { PORTA=0xE4; // displaying 2 RB6=0; fanLED=1; } else if(speed == 2) // 4ms trigger // speed 3 { PORTA=0xF0; // displaying 3 RB6=0; fanLED=1; } else if(speed == 1) // 2ms trigger // speed 4 { PORTA=0xD9; // displaying 4 RB6=0; fanLED=1; } else if(speed == 0) // 0ms trigger // speed 5 full power { PORTA=0xD2; // displaying 5 RB6=0; fanLED=1; }
Hàm dưới đây dành cho ngắt ngoài và tràn thời gian. Chức năng này có nhiệm vụ phát hiện đường cắt ngang và lái xe Triac.
void interrupt isr() { if(INT0IF) { delay(speed); tric=1; for(int t=0;t<100;t++); tric=0; INT0IF=0; } if(TMR0IF) //Check if it is TMR0 Overflow ISR { TMR0IF=0; } }
CODE
#include <xc.h>
#include<string.h>
#include<stdlib.h>
#include "config.h"
#define tric RB1
#define ir RB2
#define relay1 RC2
#define relay2 RC3
#define relay3 RC4
#define relay4 RC5
#define rly1LED RB3
#define rly2LED RB4
#define rly3LED RB5
#define rly4LED RC1
#define fanLED RC0
int flag=0;
int cmd=0;
int speed=5;
unsigned int dat[100];
int i=0;
char result[10];
int j=0;
void delay(int time)
{
for(int i=0;i<time;i++)
for(int j=0;j<800;j++);
}
void timer() // 10 -> 1us
{
T0PS0=0;
T0PS1=0;
T0PS2=0;
PSA=0; //Timer Clock Source is from Prescaler
T0CS=0; //Prescaler gets clock from FCPU (5MHz)
T08BIT=0; //16 BIT MODE
TMR0IE=1; //Enable TIMER0 Interrupt
PEIE=1; //Enable Peripheral Interrupt
GIE=1; //Enable INTs globally
TMR0ON=1; //Now start the timer!
}
void main(void)
{
ADCON1=0b00001111;
TRISB1=0;
TRISB2=1;
TRISB3=0;
TRISB4=0;
TRISB5=0;
TRISC=0x00;
TRISA=0x00;
PORTA=0xc0;
TRISB6=0;
RB6=1;
relay1=0;
relay2=0;
relay3=0;
relay4=0;
rly1LED=0;
rly3LED=0;
rly2LED=0;
rly4LED=0;
fanLED=0;
i=0;
ir=0;
tric=0;
timer();
INTEDG0 = 0; // Interrupt on falling edge
INT0IE = 1; // Enable the INT0 external interrupt (RB0)
INT0IF = 0; // Clears INT0 External Interrupt Flag bit
PEIE=1; //Enable Peripheral Interrupt
GIE=1; //Enable INTs globally
while(1)
{
while(ir == 1);
INT0IE = 0;
while(ir == 0);
TMR0=0;
while(ir == 1);
i++;
dat[i]=TMR0;
if(dat[1] > 5000 && dat[1]<12000)
{
}
else
{
i=0;
INT0IE = 1;
}
if(i>=33)
{
GIE=0;
delay(50);
cmd=0;
for(j=26;j<34;j++)
{
if(dat[j]>1000 && dat[j]<2000)
cmd<<=1;
else if(dat[j]>3500 && dat[j]<4500)
{
cmd|=0x01;
cmd<<=1;
}
}
cmd>>=1;
if(cmd == 0xAF)
{
relay1=~relay1;
rly1LED=~rly1LED;
}
else if(cmd == 0x27)
{
relay2=~relay2;
rly2LED=~rly2LED;
}
else if(cmd == 0x07)
{
relay3=~relay3;
rly3LED=~rly3LED;
}
else if(cmd == 0xCF)
{
relay4=~relay4;
rly4LED=~rly4LED;
}
else if(cmd == 0x5f)
{
speed++;
if(speed>5)
{
speed=5;
}
}
else if(cmd == 0x9f)
{
speed--;
if(speed<=0)
{
speed=0;
}
}
if(speed == 5) // turned off 5x2= 10ms triger //speed 0
{
PORTA=0xC0; // display 0
RB6=1;
fanLED=0;
}
else if(speed == 4 ) // 8 ms trigger //speed 1
{
PORTA=0xfc; // displaying 1
RB6=1;
fanLED=1;
}
else if(speed == 3) // 6 ms trigger // speed 2
{
PORTA=0xE4; // displaying 2
RB6=0;
fanLED=1;
}
else if(speed == 2) // 4ms trigger // speed 3
{
PORTA=0xF0; // displaying 3
RB6=0;
fanLED=1;
}
else if(speed == 1) // 2ms trigger // speed 4
{
PORTA=0xD9; // displaying 4
RB6=0;
fanLED=1;
}
else if(speed == 0) // 0ms trigger // speed 5 full power
{
PORTA=0xD2; // displaying 5
RB6=0;
fanLED=1;
}
else
{
RB6=1;
PORTA=0xff; // display off
fanLED=0;
}
i=0;
INT0IE = 1;
GIE=1;
}
}
}
void interrupt isr()
{
if(INT0IF)
{
delay(speed);
tric=1;
for(int t=0;t<100;t++);
tric=0;
INT0IF=0;
}
if(TMR0IF) //Check if it is TMR0 Overflow ISR
{
TMR0IF=0;
}
}