Bật tắt đèn 12V bằng remote hồng ngoại, tự học nút trên điều khiển cũ

Dùng bất kỳ điều khiển hồng ngoại nào còn pin (remote tivi, quạt, máy lạnh cũ) để bật tắt đèn hay quạt 12V qua rơ-le có opto. Bấm nút học rồi bấm nút trên remote là mạch nhớ luôn mã đó vào bộ nhớ, mất điện không quên. Đèn báo cho biết đang bật hay tắt.

⏱ 80 phút🔧 Biết hàn💰 Linh kiện ~106.000đ🧠 Arduino Nano⚡ Nguồn USB 5V

✅ Đã kiểm thử

Luật điệnKhông lỗiSai chân, chập nguồn, quá áp 5V vào chân 3,3V, thiếu đi-ốt, thiếu trở kéo…
Mô phỏng SPICE3/3 kịch bản · 18 phép đo đạtDòng/áp từng linh kiện ở trường hợp xấu nhất (ngspice)
Biên dịch codeĐạt · dùng 18% bộ nhớarduino:avr:nano
Xem chi tiết 18 phép đo

Đèn đang bật (rơ-le đóng) và vừa nhận lệnh từ remote

  • D1: dòng 8.2mA (cho phép 20.0mA).
  • Chân D7 cấp 3.7mA (an toàn ≤ 20.0mA).
  • Chân D9 cấp 8.2mA (an toàn ≤ 20.0mA).
  • Tổng dòng đỉnh từ USB 118.0mA (đủ với cục sạc 5V 1A).
  • Mức kích rơ-le (jumper ở H, cần ≥ 2V): 4.91V ✓
  • Dòng chân D7 kích rơ-le: 3.7mA ✓
  • Dòng LED báo trạng thái: 8.2mA ✓
  • Chân mắt thu kéo xuống thấp khi có chùm 38kHz: 0.00V ✓
  • Tổng dòng từ cổng USB (rơ-le hút khoảng 75mA): 118.0mA ✓

Đèn tắt, mạch đang chờ lệnh

  • Tổng dòng đỉnh từ USB 106.1mA (đủ với cục sạc 5V 1A).
  • Rơ-le phải nhả: 0.00V ✓
  • LED báo phải tắt: 0.0mA ✓
  • Mắt thu nghỉ ở mức cao: 5.00V ✓

Đang bấm nút học lệnh

  • D1: dòng 8.2mA (cho phép 20.0mA).
  • Chân D9 cấp 8.2mA (an toàn ≤ 20.0mA).
  • Tổng dòng đỉnh từ USB 114.3mA (đủ với cục sạc 5V 1A).
  • Áp chân nút khi nhấn: 0.00V ✓
  • LED nháy báo đang chờ học: 8.2mA ✓
Kiểm lần cuối: 08:49:38 13/11/2026

Nguyên lý hoạt động

Mắt thu VS1838B đã gồm sẵn mạch lọc 38kHz và khuếch đại: lúc không có tín hiệu chân OUT nghỉ ở mức cao, khi remote chiếu tới nó kéo chân này xuống thấp theo đúng nhịp mã lệnh. Thư viện IRremote trên Nano đo độ dài các nhịp đó rồi dịch ra mã NEC 32 bit (hoặc Sony, RC5…). Mạch so mã vừa nhận với mã đã lưu trong EEPROM: trùng thì đảo trạng thái rơ-le. Bấm nút ở D3 là vào chế độ học trong 10 giây — mã của nút remote bấm tiếp theo sẽ được ghi vào EEPROM nên mất điện vẫn nhớ. Chân D7 kích module rơ-le qua opto (jumper chọn mức cao), dòng kích chỉ vài miliampe nên chân Nano không bị quá tải, còn cuộn hút 75mA do nguồn 5V gánh. LED xanh ở D9 sáng khi đèn đang bật và nháy khi đang chờ học lệnh.

Sơ đồ đấu dây

Mỗi màu là một dây. Chấm tròn là điểm hàn. Chạm vào tên dây trong bảng để làm nổi bật.

⚡ Mô phỏng tương tácBấm thử — mạch được giải ngay trên máy bạn, điện áp và dòng hiện lên sơ đồ bên dưới.
Tình huống mẫu
Chân D7điều khiển K1
Chân D9điều khiển R1
U2 · OUTVS1838B nghỉ ở mức cao, bị kéo xuống 0V khi có chùm hồng ngoại 38kHz.
Nút SW1

Đây là mô phỏng một chiều (DC) ở trạng thái tĩnh: dùng để kiểm tra mức áp, dòng và công suất. Hiệu ứng nhấp nháy, PWM hay giao tiếp số do code quyết định nên không chạy ở đây.

5V5VGNDGNDIR_OUTIR_OUTRELAY_INRELAY_INLED_DRVLED_DRVLED_ALED_ABTNBTNU1 · Arduino Nano5VD2D3D7D9GNDU2 · Mắt thu hồng ngoại VS1838B 38kHzVCC · chân 3 VCCOUT · chân 1 OUTGND · chân 2 GNDSW1 · Nút nhấn12K1 · rơ-le 1 kênh 5V có optoVCCINGNDR1 · Điện trở 330Ω12D1 · Đèn LED 5mmA · chân dài (+)K · chân ngắn (−)
#DâyNối các điểmÁp mô phỏng
1đỏ
5V
U1 5V ⟷ U2 VCC · chân 3 VCC ⟷ K1 VCC—
2đen
GND
U1 GND ⟷ U2 GND · chân 2 GND ⟷ K1 GND ⟷ D1 K · chân ngắn (−) ⟷ SW1 2—
3vàng
IR_OUT
U2 OUT · chân 1 OUT ⟷ U1 D2—
4xanh lá
RELAY_IN
U1 D7 ⟷ K1 IN—
5xanh dương
LED_DRV
U1 D9 ⟷ R1 1—
6tím
LED_A
R1 2 ⟷ D1 A · chân dài (+)—
7xanh ngọc
BTN
SW1 1 ⟷ U1 D3—

Danh sách linh kiện

Ký hiệuLinh kiệnGiá tham khảo
U1Arduino Nano (chip nạp CH340)75.000đTìm mua
U2Mắt thu hồng ngoại VS1838B 38kHz4.000đTìm mua
K1Module rơ-le 1 kênh 5V có opto (jumper chọn kích mức cao)25.000đTìm mua
D1LED xanh lá 5mm (green)300đTìm mua
R1Điện trở 330Ω 1/4W (cam-cam-nâu)200đTìm mua
SW1Nút nhấn 4 chân 6×6mm1.500đTìm mua
Tổng (chưa gồm board hàn, dây, thiếc)106.000đ

Các bước làm

Code nạp cho mạch

Cài thư viện: IRremote (Arduino IDE → Library Manager). Chọn board Arduino Nano.

/*
  Mạch Gọn — Bật tắt đèn 12V bằng remote hồng ngoại (Arduino Nano + VS1838B + rơ-le)
  Thư viện: IRremote (bản 4.x)
  Chân : D2 <- OUT mắt thu ; D7 -> IN module rơ-le ; D9 -> 330Ω -> LED xanh
         D3 nút học lệnh, nối GND (INPUT_PULLUP)
*/
#include <Arduino.h>
#include <EEPROM.h>

#define DECODE_NEC
#define DECODE_SONY
#define DECODE_RC5
#define NO_LED_FEEDBACK_CODE
#include <IRremote.hpp>

// ---------- Cấu hình ----------
const uint8_t PIN_IR = 2, PIN_NUT = 3, PIN_RELAY = 7, PIN_LED = 9;
const bool KICH_MUC_CAO   = true;     // đổi thành false nếu module rơ-le kích mức thấp
const uint32_t THOI_GIAN_HOC_MS = 10000;
const uint32_t CHONG_DOI_MS     = 400;   // bỏ qua lệnh trùng trong khoảng này
const uint16_t EE_MAGIC_ADDR = 0, EE_MA_ADDR = 2;
const uint16_t EE_MAGIC = 0x4D47;        // "MG"

uint32_t maDaHoc = 0;
bool dangBat = false, dangHoc = false, nutDangNhan = false;
uint32_t mocHetHan = 0, mocLenhTruoc = 0, mocNhayLed = 0;

void datRelay(bool bat) {
  dangBat = bat;
  digitalWrite(PIN_RELAY, (bat == KICH_MUC_CAO) ? HIGH : LOW);
  digitalWrite(PIN_LED, bat ? HIGH : LOW);
  Serial.print(F("Den: ")); Serial.println(bat ? F("BAT") : F("TAT"));
}

void luuMa(uint32_t ma) {
  uint16_t magic = EE_MAGIC;
  EEPROM.put(EE_MAGIC_ADDR, magic);
  EEPROM.put(EE_MA_ADDR, ma);
  maDaHoc = ma;
  Serial.print(F("Da nho ma: 0x")); Serial.println(ma, HEX);
}

void docMa() {
  uint16_t magic = 0;
  EEPROM.get(EE_MAGIC_ADDR, magic);
  if (magic == EE_MAGIC) EEPROM.get(EE_MA_ADDR, maDaHoc);
  else maDaHoc = 0;
}

void nhayLed(uint8_t lan) {
  for (uint8_t i = 0; i < lan; i++) {
    digitalWrite(PIN_LED, HIGH); delay(120);
    digitalWrite(PIN_LED, LOW);  delay(120);
  }
  digitalWrite(PIN_LED, dangBat ? HIGH : LOW);
}

void setup() {
  pinMode(PIN_RELAY, OUTPUT);
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_NUT, INPUT_PULLUP);
  Serial.begin(115200);
  datRelay(false);                       // luôn khởi động ở trạng thái tắt
  docMa();
  IrReceiver.begin(PIN_IR, DISABLE_LED_FEEDBACK);
  Serial.println(F("Mach Gon - dieu khien den bang remote"));
  if (maDaHoc) { Serial.print(F("Ma da luu: 0x")); Serial.println(maDaHoc, HEX); }
  else Serial.println(F("Chua hoc ma nao - bam nut tren board roi bam remote"));
  nhayLed(3);
}

void loop() {
  uint32_t bayGio = millis();

  // 1. Nút học lệnh
  bool dangNhan = (digitalRead(PIN_NUT) == LOW);
  if (dangNhan && !nutDangNhan) {
    nutDangNhan = true;
    dangHoc = true;
    mocHetHan = bayGio + THOI_GIAN_HOC_MS;
    Serial.println(F("Che do hoc: chia remote vao mat thu va bam nut muon dung"));
  }
  if (!dangNhan) nutDangNhan = false;

  if (dangHoc) {
    if ((int32_t)(bayGio - mocHetHan) >= 0) {
      dangHoc = false;
      Serial.println(F("Het thoi gian hoc"));
      digitalWrite(PIN_LED, dangBat ? HIGH : LOW);
    } else if (bayGio - mocNhayLed >= 150) {           // nháy báo đang chờ
      mocNhayLed = bayGio;
      digitalWrite(PIN_LED, !digitalRead(PIN_LED));
    }
  }

  // 2. Nhận lệnh hồng ngoại
  if (IrReceiver.decode()) {
    uint32_t ma = IrReceiver.decodedIRData.decodedRawData;
    bool laMaLap = (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) != 0;
    if (ma != 0 && !laMaLap) {
      Serial.print(F("Nhan ma: 0x")); Serial.println(ma, HEX);
      if (dangHoc) {
        dangHoc = false;
        luuMa(ma);
        digitalWrite(PIN_LED, HIGH); delay(1000);
        digitalWrite(PIN_LED, dangBat ? HIGH : LOW);
      } else if (maDaHoc != 0 && ma == maDaHoc && bayGio - mocLenhTruoc > CHONG_DOI_MS) {
        mocLenhTruoc = bayGio;
        datRelay(!dangBat);
      }
    }
    IrReceiver.resume();
  }
}

🔌 Cắm thử trên breadboard

Cắm nháp trên board cắm trước cho chắc, chạy đúng rồi hãy làm mạch in. Sơ đồ này do máy tự xếp từ chính netlist ở trên và đã đối chiếu lại: hai chân cùng một cột (cùng nửa board) là thông nhau, không có net nào bị chập.

+−+−5510101515202025253030JIHGFEDCBAU1 · Arduino NanoGND5VD2D3D7D9U2K1D1 greenR1 330SW1
  • Mỗi cột 5 lỗ trong cùng một nửa board thông nhau; hai nửa cách nhau bởi rãnh giữa.
  • Hai đường kẻ dọc mép board là đường nguồn: hàng + (vạch đỏ) và hàng − (vạch xanh). Nhớ bắc dây nối đường nguồn trên với đường nguồn dưới nếu dùng cả hai nửa.
  • Màu dây trên hình trùng với màu trong bảng nối dây ở mục Sơ đồ, cắm theo màu cho dễ dò.

🧲 Mạch in để ủi (PCB 1 mặt)

Bản mạch in một mặt đồng, tự xếp linh kiện và tự đi dây, đã kiểm quy tắc khoảng cách và đối chiếu đúng 100% với sơ đồ nguyên lý ở trên. In tỉ lệ 1:1 rồi ủi lên tấm đồng.

Kích thước board61,0×48,3 mm44 lỗ khoan · mũi 0,8 / 0,9 / 1mm
Đi dây 1 mặt15 đoạn · 361,2 mmKhông cần cầu nhảy nào
Kiểm tra bản mạchĐạt DRC · khớp 100% netlistĐường ≥0,8mm, khe ≥0,5mm; mọi net đối chiếu lại từ hình học thật
Mặt đồng — đã lật gương sẵn để in rồi ủi úp xuống tấm đồng
Mặt linh kiện — vị trí, chiều cắm và tên từng chân
U1U2K1D1R1SW1D1D0RSTGNDD2D3D4D5D6D7D8D9D10D11D12VINGND2RST25VA7A6A5A4A3A2A1A0AREF3V3D13VCCGNDIN
Hướng dẫn ủi – ăn mòn – khoan – hàn (đầy đủ)

Hướng dẫn làm mạch in bằng phương pháp ủi

Mạch: Bật tắt đèn 12V bằng remote hồng ngoại, tự học nút trên điều khiển cũ

Kích thước board: 61,0×48,3 mm · 44 lỗ khoan (mũi 0,8, 0,9 và 1 mm) · 15 đoạn mạch, tổng 361,2 mm · 0 cầu nhảy.

Quy tắc đã kiểm: đường mạch rộng 0,8mm (nguồn và GND 1mm), khe cách tối thiểu 0,5mm. Mạch in đã được máy đối chiếu đúng 100% với sơ đồ nguyên lý.

1. In đúng tỉ lệ 1:1

  • In trang "MẶT ĐỒNG" bằng máy in LASER, đặt tỉ lệ 100%, KHÔNG chọn "Fit to page" hay "Scale to fit".
  • Dùng thước trên bản in đo lại đoạn 100mm: phải đúng 100mm mới dùng được.
  • In trên giấy in ảnh bóng, giấy decal bóc, hoặc giấy tạp chí láng. Mực càng dày càng tốt.
  • Trang "MẶT ĐỒNG" đã được LẬT GƯƠNG sẵn: úp mặt có mực vào tấm đồng là đúng chiều.

2. Chuẩn bị tấm đồng

  • Cắt phíp đồng (board đồng một mặt) lớn hơn kích thước mạch mỗi bề khoảng 5mm.
  • Chà mặt đồng bằng giấy nhám mịn (P800–P1200) rồi rửa sạch, lau khô. Mặt đồng phải sáng, không vết dầu mỡ, không chạm tay vào.

3. Ủi mực sang đồng

  • Úp mặt có mực vào tấm đồng, dùng băng keo giấy dán cố định một cạnh.
  • Bàn ủi để mức nóng nhất (cotton/linen), KHÔNG dùng chế độ phun hơi nước.
  • Ủi đè mạnh và đều 3–5 phút, tập trung từng vùng nhỏ, chú ý các góc và mép.
  • Để nguội hẳn rồi ngâm cả tấm vào nước ấm 5–10 phút, bóc giấy thật nhẹ. Giấy decal thì bóc khi còn ấm.
  • Soi kỹ: chỗ nào mực bị thiếu hoặc đứt đường thì tô lại bằng bút lông dầu (bút CD) rồi để khô.

4. Ăn mòn (etching)

  • Pha dung dịch sắt(III) clorua FeCl3 theo hướng dẫn trên bao bì, hoặc dung dịch oxy già + muối ăn + a-xít; dùng hộp nhựa, KHÔNG dùng đồ kim loại.
  • Nhiệt độ dung dịch khoảng 40–50°C thì ăn nhanh hơn. Lắc nhẹ hộp cho đều, thường 10–25 phút là xong.
  • An toàn: đeo găng tay cao su và kính bảo hộ, làm ở nơi thoáng. Dung dịch ăn mòn làm hỏng quần áo, bồn rửa và gây bỏng rát da.
  • Xong thì rửa board bằng nước sạch, lau khô, dùng xăng thơm hoặc axeton lau sạch lớp mực.
  • Dung dịch đã dùng KHÔNG đổ xuống bồn rửa hay cống; đựng vào can kín và bỏ đúng nơi thu gom chất thải.

5. Khoan lỗ

  • Đối chiếu trang "BẢN VẼ LỖ KHOAN" để biết lỗ nào dùng mũi nào.
  • Dùng mũi khoan 0,8mm, 0,9mm và 1mm, khoan từ MẶT ĐỒNG vào để mũi tự định tâm giữa pad.
  • Khoan tốc độ cao, đẩy nhẹ; mũi nhỏ rất dễ gãy. Khoan xong chà nhẹ bavia hai mặt.

6. Hàn linh kiện

  • Linh kiện cắm ở MẶT KHÔNG CÓ ĐỒNG, hàn ở mặt đồng. Theo trang "MẶT LINH KIỆN" để đặt đúng vị trí và đúng chiều.
  • Hàn linh kiện thấp trước (điện trở, đi-ốt), cao sau (tụ, hàng chân, board vi điều khiển).
  • Chú ý chiều: LED chân dài là (+); đi-ốt có vạch trắng là K; tụ hoá có vạch là (−); transistor theo mặt chữ như nét vẽ đỏ.
  • Trước khi cấp điện: đo thông mạch giữa chân nguồn và GND — KHÔNG được kêu (không được chập).

Lưu ý với board vi điều khiển

  • Board nhái có thể khác thứ tự chân. Đối chiếu tên chân in cạnh từng lỗ trên trang "MẶT LINH KIỆN" với chữ in trên board thật TRƯỚC KHI ăn mòn. Nếu khác, đừng hàn mà báo lại để sửa bản vẽ.
Bản vẽ lỗ khoan
BẢN VẼ LỖ KHOAN (nhìn từ mặt linh kiện)mũi khoan 0,8mm — 2 lỗmũi khoan 0,9mm — 9 lỗmũi khoan 1mm — 33 lỗ

Đo kiểm bằng đồng hồ vạn năng

Giữa VCC và GND của mắt thu4,7 – 5,1V
Giữa OUT của mắt thu và GND lúc không bấm remotekhoảng 5V
Giữa OUT và GND lúc bấm giữ nút remotesố nhảy xuống khoảng 4,2 – 4,8V (đang nháy rất nhanh)
Giữa D7 và GND khi đèn đang bậtkhoảng 5V, nghe tiếng rơ-le kêu tách
Serial Monitor 115200 khi bấm remoteDòng "Nhan ma: 0x…"

Sửa lỗi thường gặp

Bấm remote không ăn

Xem Serial Monitor: nếu không có dòng "Nhan ma" thì mắt thu sai chân (OUT – GND – VCC rất dễ cắm ngược) hoặc remote hết pin. Thử soi camera điện thoại vào đầu remote: bấm phím phải thấy đèn tím nháy.

Mã nhận được mỗi lần một khác

Giữ phím quá lâu khiến remote gửi mã lặp (0xFFFFFFFF). Bấm dứt khoát rồi thả. Code đã bỏ qua mã lặp nhưng remote rẻ tiền vẫn có thể nhiễu.

Rơ-le kêu tách liên tục

Nguồn USB yếu: cuộn hút 75mA làm sụt áp, Nano khởi động lại. Dùng cục sạc 5V ≥1A thay vì cổng USB máy tính.

Rơ-le đóng ngay khi vừa cấp điện

Module của bạn là loại kích mức thấp. Đặt lại jumper về H, hoặc sửa KICH_MUC_CAO = false trong code.

Tầm xa chỉ khoảng 1m

Mắt thu bị đèn LED chiếu thẳng hoặc nằm sau nhựa đục. Hướng mắt thu ra ngoài, tránh ánh nắng và đèn huỳnh quang chiếu trực tiếp.

⚠️ An toàn

  • Hướng dẫn này chỉ dành cho thiết bị điện một chiều 12–24V (đèn LED 12V, quạt 12V, bơm 12V…).
  • Nếu muốn bật tắt thiết bị 220V: phần đấu nối 220V bắt buộc nhờ thợ điện có chuyên môn thực hiện, có hộp nhựa cách điện và cầu chì/aptomat; hoặc dùng ổ cắm thông minh có chứng nhận an toàn. Không tự đấu điện lưới.
  • Phía Nano chỉ có 5V, an toàn khi chạm tay.
  • Không dùng mạch này cho thiết bị sưởi, bếp điện hay thiết bị phải canh chừng khi hoạt động.