Đã được đăng vào 22/12/2020 @ 15:40
Giải mã Remote hồng ngoại với Arduino
Giao tiếp hồng ngoại (IR) là một công nghệ điều khiển từ xa được sử dụng rộng rãi, rẻ tiền và thực sự hữu dụng.
Chúng ta thường thấy phương thức điều khiển này qua remote TV, đầu đĩa, cảm biến chuyển động hoặc nhiệt kế hồng ngoại.
Hiện nay có rất nhiều ứng dụng Arduino có thể sử dụng phương thức giao tiếp hồng ngoại để điều khiển như: robot điều khiển từ xa, cảm biến khoảng cách, cảm biến nhịp tim, điều khiển từ xa máy ảnh DSLR, điều khiển từ xa TV, máy lạnh,…
Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu hồng ngoại là gì?
Và làm thế nào để điều khiển Arduino từ remote hồng ngoại?
Xem thêm:
- Mạch thu phát hồng ngoại
- Các mạch điện tử lý thú by minhdt
- Sơ đồ mạch thu phát âm thanh không dây bằng sóng hồng ngoại cho tai nghe
HỒNG NGOẠI LÀ GÌ?
Ánh sáng hồng ngoại là một dạng ánh sáng tương tự như ánh sáng chúng ta nhìn thấy xung quanh mình.
Sự khác biệt duy nhất giữa ánh sáng hồng ngoại và ánh sáng khả kiến (ánh sáng mà chúng ta có thể nhìn thấy được) là tần số và bước sóng.
Bức xạ hồng ngoại có bước sóng nằm ngoài phạm vi ánh sáng khả kiến, vì vậy con người không thể nhìn thấy nó.

Bởi vì hồng ngoại là một loại ánh sáng, vậy nên việc điều khiển hồng ngoại phải được truyền trực tiếp từ nguồn phát đến cảm biến thu.
Do đó, nó không thể truyền xuyên qua các vật cản như sóng RF, Wifi, Bluetooth.
REMOTE HỒNG NGOẠI VÀ CẢM BIẾN THU HOẠT ĐỘNG NHƯ THẾ NÀO?
Để có thể giao tiếp bằng hồng ngoại ta cần một bộ phát và một bộ thu.
LED phát hồng ngoại tương tự như LED bình thường ngoại trừ nó phát ra ánh sáng mà mắt thường không thể nhìn thấy được, ánh sáng hồng ngoại.
Bạn có thể thấy chúng trong các remote TV, máy lạnh thường dùng.

Đối với Arduino, bạn có thể sử dụng LED phát hồng ngoại đã được gắn với điện trở để hạn dòng.
Điện trở thường dùng là từ 100 đến 470 ohm.

Bộ thu hồng ngoại là một photodiode và bộ tiền khuếch đại (pre-amplifier) để chuyển đổi tín hiệu ánh sáng thành tín hiệu điện.

Trong bộ 37 cảm biến có mắt thu hồng ngoại như thế này:

TRUYỀN DỮ LIỆU THÔNG QUA ÁNH SÁNG HỒNG NGOẠI
Ánh sáng hồng ngoại được phát ra từ mọi vật liệu có nhiệt độ, từ mặt trời, bóng đèn cho đến các vật dụng trong phòng.
Điều đó có nghĩa là có rất nhiều ánh sáng hồng ngoại gây nhiễu xung quanh chúng ta.
Để ngăn tín hiệu nhiễu này ảnh hưởng đến tín hiệu IR (hồng ngoại), kỹ thuật điều chế tín hiệu được sử dụng.
Trong điều chế tín hiệu IR, bộ mã hóa trên bộ phát IR chuyển đổi tín hiệu nhị phân thành tín hiệu điện.
Tín hiệu điện này được gửi đến đèn LED truyền. Đèn LED truyền sẽ chuyển đổi tín hiệu điện được điều chế thành ánh sáng hồng ngoại.
Sau đó, bộ thu IR giải mã tín hiệu ánh sáng hồng ngoại và chuyển đổi trở lại thành nhị phân trước khi truyền thông tin đến Arduino.

Tín hiệu IR được điều chế thành một chuỗi các xung ánh sáng được bật và tắt ở tần số cao được gọi là tần số sóng mang.
Tần số sóng mang được sử dụng bởi hầu hết các remote phát hồng ngoại là 38 kHz, vì nó rất hiếm trong tự nhiên và do đó có thể loại bỏ được nhiễu từ môi trường xung quanh.
Bằng cách này, bộ thu IR sẽ biết rằng tín hiệu 38 kHz được gửi từ máy phát mà không phải là từ môi trường xung quanh.
Diode thu nhận được tất cả các tần số của ánh sáng hồng ngoại, nhưng thông qua bộ lọc thông dải nó chỉ cho phép bước sóng có tần số 38 kHz đi qua.
Sau đó, tín hiệu này được khuếch đại bởi bộ tiền khuếch đại và chuyển đổi nó thành tín hiệu nhị phân trước khi gửi nó đến Arduino.
PHƯƠNG THỨC GIAO TIẾP HỒNG NGOẠI
Cách chuyển đổi dữ liệu nhị phân kết hợp với sóng mang được xác định bởi giao thức truyền tín hiệu tiêu chuẩn.
Có nhiều giao thức truyền dữ liệu IR. Trong đó: Sony, Matsushita, NEC và RC5 là những giao thức tương đối phổ biến.
Giao thức NEC cũng là loại phổ biến và thường được dùng nhất trong các dự án Arduino, vì vậy trong bài viết này chúng ta sẽ tìm hiểu cách điều chế tín hiệu nhị phân thông qua giao thức NEC.
2 mức logic 0 và 1 trong giao thức NEC được định nghĩa như sau:
- Mức logic 1: là một xung CAO có chu kỳ 562,5 us và một mức THẤP có chu kỳ 1.687,5 us.
- Mức logic 0: là một xung CAO có chu kỳ 562,5 us và một mức THẤP có chu kỳ 562,5 us.
Khi xung ở mức cao, chúng được chia ra thành các xung nhỏ hơn có chu kỳ 26,3 us (38kHz).

Đây chính là cách mà giao thức NEC mã hóa tín hiệu 0 và 1. Các giao thức khác chỉ khác về chu kỳ giữa các xung CAO và xung THẤP.
MÃ CODE HỒNG NGOẠI
Mỗi lần bạn nhấn một nút trên điều khiển từ xa, một mã HEX (Thập lục phân) duy nhất sẽ được truyền đi.
Thông tin này sẽ được điều chế và gửi qua ánh sáng hồng ngoại đến bộ phận thu tín hiệu.
Để giải mã phím nào được nhấn, Arduino sẽ cần biết mã nào tương ứng với từng phím trên điều khiển từ xa.
Các điều khiển từ xa khác nhau gửi các mã khác nhau cho các phím bấm, do đó, bạn sẽ cần xác định mã tương ứng cho mỗi nút nhấn trên điều khiển từ xa cụ thể của bạn.
Nếu bạn đã có datasheet của remote hồng ngoại, bạn chỉ cần lưu chúng vào bên trong con Arduino.
Nếu không, chúng ta sẽ viết 1 đoạn code Arduino đơn giản để đọc tín hiệu điều khiển từ remote và gửi chúng qua cổng Serial mỗi khi bạn nhấn 1 phím.
Chúng ta sẽ tìm hiểu chúng ở phần sau.
KẾT NỐI CẢM BIẾN HỒNG NGOẠI VỚI ARDUINO
Có rất nhiều loại cảm biến hồng ngoại khác nhau từ linh kiện rời đến loại đã được gắn lên board nhưng thông thường chúng có 3 chân: VCC, GND, DATA.
HX1838 là loại thu hồng ngoại tương đối phổ biến – tên thường gọi là mắt thu hồng ngoại vỏ sắt.

Sau đây là sơ đồ nối dây của đầu thu hồng ngoại với Arduino:

LẬP TRÌNH ARDUINO VỚI CẢM BIẾN HỒNG NGOẠI
Để lập trình với cảm biến hồng ngoại, bạn cần cài đặt thư viện giao tiếp với cảm biến hồng ngoại với Arduino.
Trong bài viết này, bạn sẽ biết được cách hiển thị mã phím nhấn đọc được lên cổng Serial, LCD và điều khiển đèn LED.
DOWNLOAD VÀ CÀI ĐẶT THƯ VIỆN ARDUINO
Bạn cần download thư viện đọc và giải mã tín hiệu hồng ngoại tại đây:
https://github.com/ESPACE-HCM/IR-Remote
Để cài đặt thư viện từ ZIP file, bạn mở Arduino IDE, click vào Sketch > Include Library > Add .ZIP Library, sau đó chọn IRremote ZIP vừa download về.
MÃ HEX CHO TỪNG PHÍM BẤM
Để tìm mã HEX tương ứng cho từng phím bấm, ta cần sử dụng đoạn code Arduino sau để nhận tín hiệu từ remote hồng ngoại và hiện thị mã HEX lên cổng Serial:
#include <IRremote.h>
int RECV_PIN = 7;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
// In case the interrupt driver crashes on setup, give a clue
// to the user what’s going on.
Serial.println(“Enabling IRin”);
irrecv.enableIRIn(); // Start the receiver
Serial.println(“Enabled IRin”);
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
irrecv.resume(); // Receive the next value
}
delay(100);
}
TẢI VỀ:
Bây giờ, bạn nhấn từng phím nhấn trên remote, bạn sẽ nhận được mã HEX tương ứng với phím nhấn đó.

Lưu ý: khi bạn nhấn đè một phím trên remote, nó sẽ gửi mã 0XFFFFFFFF.
Dưới đây là bảng mã tương ứng trên remote hồng ngoại thường dùng với Arduino.
Key Code CH- 0xFFA25D CH 0xFF629D CH+ 0xFFE21D << 0xFF22DD >> 0xFF02FD >|| 0xFFC23D – 0xFFE01F + 0xFFA857 EQ 0xFF906F 100+ 0xFF9867 200+ 0xFFB04F 0 0XFF6897 1 0xFF30CF 2 0xFF18E7 3 0xFF7A85 4 0xFF10EF 5 0xFF38C7 6 0xFF5AA5 7 0xFF42BD 8 0xFF4AB5 9 0xFF52AD
PHƯƠNG THỨC TRUYỀN DỮ LIỆU MÀ REMOTE BẠN ĐANG DÙNG
Để biết remote bạn đang dùng truyền dữ liệu theo phương thức nào, bạn có thể sử dụng đoạn code dưới đây:
#include <IRremote.h> const int RECV_PIN = 7; IRrecv irrecv(RECV_PIN); decode_results results; void setup(){ Serial.begin(9600); irrecv.enableIRIn(); irrecv.blink13(true); } void loop(){ if (irrecv.decode(&results)){ Serial.println(results.value, HEX); switch (results.decode_type){ case NEC: Serial.println("NEC"); break ; case SONY: Serial.println("SONY"); break ; case RC5: Serial.println("RC5"); break ; case RC6: Serial.println("RC6"); break ; case DISH: Serial.println("DISH"); break ; case SHARP: Serial.println("SHARP"); break ; case JVC: Serial.println("JVC"); break ; case SANYO: Serial.println("SANYO"); break ; case MITSUBISHI: Serial.println("MITSUBISHI"); break ; case SAMSUNG: Serial.println("SAMSUNG"); break ; case LG: Serial.println("LG"); break ; case WHYNTER: Serial.println("WHYNTER"); break ; case AIWA_RC_T501: Serial.println("AIWA_RC_T501"); break ; case PANASONIC: Serial.println("PANASONIC"); break ; case DENON: Serial.println("DENON"); break ; default: case UNKNOWN: Serial.println("UNKNOWN"); break ; } irrecv.resume(); } }
GIẢI MÃ PHÍM NHẤN VÀ TRUYỀN CHÚNG LÊN SERIAL
Để biết được phím nào đang được nhấn trên remote, bạn cần phải so sánh mã HEX nhận được với bảng mã tiêu chuẩn mà bạn đã có.
Đoạn code dưới đây sẽ so sánh bằng lệnh Swtich() ……case để hiển thị lên cổng Serial.
#include <IRremote.h> const int RECV_PIN = 7; IRrecv irrecv(RECV_PIN); decode_results results; unsigned long key_value = 0; void setup(){ Serial.begin(9600); irrecv.enableIRIn(); irrecv.blink13(true); } void loop(){ if (irrecv.decode(&results)){ if (results.value == 0XFFFFFFFF) results.value = key_value; switch(results.value){ case 0xFFA25D: Serial.println("CH-"); break; case 0xFF629D: Serial.println("CH"); break; case 0xFFE21D: Serial.println("CH+"); break; case 0xFF22DD: Serial.println("|<<"); break; case 0xFF02FD: Serial.println(">>|"); break ; case 0xFFC23D: Serial.println(">|"); break ; case 0xFFE01F: Serial.println("-"); break ; case 0xFFA857: Serial.println("+"); break ; case 0xFF906F: Serial.println("EQ"); break ; case 0xFF6897: Serial.println("0"); break ; case 0xFF9867: Serial.println("100+"); break ; case 0xFFB04F: Serial.println("200+"); break ; case 0xFF30CF: Serial.println("1"); break ; case 0xFF18E7: Serial.println("2"); break ; case 0xFF7A85: Serial.println("3"); break ; case 0xFF10EF: Serial.println("4"); break ; case 0xFF38C7: Serial.println("5"); break ; case 0xFF5AA5: Serial.println("6"); break ; case 0xFF42BD: Serial.println("7"); break ; case 0xFF4AB5: Serial.println("8"); break ; case 0xFF52AD: Serial.println("9"); break ; } key_value = results.value; irrecv.resume(); } }
Nếu remote của bạn có mã khác với đoạn mã trong code mẫu, bạn chỉ cần thay thế mã HEX tương ứng là được. Ví dụ: 0xFFA25D tương ứng với CH-
GIẢI THÍCH CODE
Đối với bất kỳ giao thức IR nào sử dụng thư viện IRremote, trước tiên chúng ta cần tạo một đối tượng gọi là irrecv và chỉ định số pin tín hiệu IR được kết nối (dòng 3).
Đối tượng này sẽ giải mã giao thức và xử lý thông tin nhận được từ đầu thu hồng ngoại.
Bước tiếp theo là tạo đối tượng decode_results, kết quả của quá trình giải mã dữ liệu thông qua irrecv sẽ được lưu tại biến này (dòng 5).
Trong hàm void setup (), đầu tiên chúng ta cấu hình tốc độ baud của serial Arduino.
Tiếp theo, chúng khởi tạo hàm thu IR bằng cách gọi hàm con IRrecv enableIRIn () (dòng 10).
Chức năng irrecv.blink13 (true) trên dòng 11 sẽ làm nhấp nháy đèn LED 13 mỗi khi đầu thu hồng ngoại nhận được tín hiệu từ điều khiển từ xa.
Trong hàm void loop (), hàm irrecv.decode sẽ trả về true nếu nhận được mã và đoạn code phía trong hàm if sẽ được thực thi.
Mã nhận được được lưu trữ trong results.value.
Sau đó, hàm switch .. case sẽ được dùng để so sánh mã nhận được.
Trước khi bắt đầu so sánh với hàm swtich .. case ta có 1 điều kiện :
if (results.value == 0XFFFFFFFF) results.value = key_value;
Nếu như nhận được mã HEX 0xFFFFFFFF, chúng ta sẽ thực thi mã vừa được gửi trước đó được lưu trong biến key_value
key_value = results.value;
Ở cuối phần void loop (), chúng ta gọi irrecv.resume () để đặt lại bộ thu và chuẩn bị nhận mã tiếp theo.
HIỂN THỊ NÚT NHẤN REMOTE LÊN LCD
Để hiển thị nút đã được nhấn từ remote lên LCD ta nối sơ đồ mạch như sau:

Biến trở dùng để điều chỉnh độ tương phản của LCD, bạn có thể chọn biến trở có giá trị từ 200 ohm đến 2k.
#include <IRremote.h> #include <LiquidCrystal.h> const int RECV_PIN = 7; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); IRrecv irrecv(RECV_PIN); decode_results results; unsigned long key_value = 0; void setup(){ Serial.begin(9600); irrecv.enableIRIn(); irrecv.blink13(true); lcd.begin(16, 2); } void loop(){ if (irrecv.decode(&results)){ if (results.value == 0XFFFFFFFF) results.value = key_value; lcd.setCursor(0, 0); lcd.clear(); switch(results.value){ case 0xFFA25D: lcd.print("CH-"); break; case 0xFF629D: lcd.print("CH"); break; case 0xFFE21D: lcd.print("CH+"); break; case 0xFF22DD: lcd.print("|<<"); break; case 0xFF02FD: lcd.print(">>|"); break ; case 0xFFC23D: lcd.print(">|"); break ; case 0xFFE01F: lcd.print("-"); break ; case 0xFFA857: lcd.print("+"); break ; case 0xFF906F: lcd.print("EQ"); break ; case 0xFF6897: lcd.print("0"); break ; case 0xFF9867: lcd.print("100+"); break ; case 0xFFB04F: lcd.print("200+"); break ; case 0xFF30CF: lcd.print("1"); break ; case 0xFF18E7: lcd.print("2"); break ; case 0xFF7A85: lcd.print("3"); break ; case 0xFF10EF: lcd.print("4"); break ; case 0xFF38C7: lcd.print("5"); break ; case 0xFF5AA5: lcd.print("6"); break ; case 0xFF42BD: lcd.print("7"); break ; case 0xFF4AB5: lcd.print("8"); break ; case 0xFF52AD: lcd.print("9"); break ; } key_value = results.value; irrecv.resume(); } }
ĐIỀU KHIỂN ARDUINO VỚI REMOTE HỒNG NGOẠI
Trong ví dụ này, chúng ta sẽ điều khiển 2 LED đỏ và xanh được kết nối với chân 10, 11 tương ứng với 2 nút nhấn trên remote là phím “5” và phím “2”.

#include <IRremote.h> const int RECV_PIN = 7; IRrecv irrecv(RECV_PIN); decode_results results; const int redPin = 10; const int greenPin = 11; void setup(){ irrecv.enableIRIn(); irrecv.blink13(true); pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); } void loop(){ if (irrecv.decode(&results)){ switch(results.value){ case 0xFF38C7: //Keypad button "5" digitalWrite(redPin, HIGH); delay(2000); digitalWrite(redPin, LOW); } switch(results.value){ case 0xFF18E7: //Keypad button "2" digitalWrite(greenPin, HIGH); delay(2000); digitalWrite(greenPin, LOW); } irrecv.resume(); } }
Bài viết trên đây đã hướng dẫn các bạn các mã hóa và giải mã tín hiệu hồng ngoại theo tiêu chuẩn NEC để loại bỏ các nhiễu từ môi trường bên ngoài đồng thời đọc được mã HEX tương ứng với từng nút nhấn trên remote của bạn.
Hy vọng nó sẽ giúp ích cho các bạn trong các dự án Arduino tương lai.
Nguồn: espace.edu.vn
Để lại một bình luận