Điều khiển hồng ngoại hoạt động thế nào: sóng mang 38 kHz, giao thức NEC và ESP32

Giải thích điều khiển hồng ngoại: sóng mang 38 kHz, mắt thu và giao thức NEC với khung 32 bit, mã lặp. Hướng dẫn tự giải mã phím điều khiển và tự phát lệnh bằng ESP32, không dùng thư viện ngoài.

Điều khiển tivi, quạt, máy lạnh, đầu thu đều dùng chung một kỹ thuật: một LED hồng ngoại nhấp nháy theo quy luật, và một mắt thu ở thiết bị đọc lại quy luật đó. Đây là kiểu giao tiếp không dây một chiều đơn giản và rẻ nhất, vẫn rất hữu ích cho các dự án điều khiển trong phòng. Bài viết giải thích vì sao phải có sóng mang 38 kHz, giao thức NEC mã hóa địa chỉ và lệnh thế nào, rồi tự viết chương trình giải mã và chương trình phát trên ESP32 mà không dùng thư viện ngoài.

1. Sóng mang 38 kHz và mắt thu hồng ngoại

Sóng mang hồng ngoại 38 kHz: LED hồng ngoại nhấp nháy 38 kHz trong mỗi xung và tắt trong khoảng nghỉ; ngõ ra mắt thu ở mức thấp khi có tín hiệu, mức cao khi nghỉ; một chu kỳ sóng mang dài 26,3 micro giây
LED chỉ nhấp nháy 38 kHz trong các đoạn xung; mắt thu trả về đường bao của tín hiệu, đã đảo mức.
  • Vì sao cần sóng mang? Ánh nắng, bóng đèn và cả cơ thể người đều phát hồng ngoại. Nếu chỉ bật, tắt LED đơn thuần, mắt thu không phân biệt được tín hiệu với ánh sáng nền. Cho LED nhấp nháy ở đúng 38 kHz, mắt thu chỉ cần lọc lấy thành phần 38 kHz.
  • Xung và nghỉ: một xung (mark) là khoảng thời gian LED nhấp nháy 38 kHz; một khoảng nghỉ (space) là lúc LED tắt hẳn.
  • Mắt thu hồng ngoại loại ba chân có sẵn đi-ốt thu, mạch khuếch đại tự chỉnh độ nhạy, bộ lọc 38 kHz và mạch tách sóng. Ngõ ra chỉ còn hai mức và đảo ngược: mức thấp khi có xung, mức cao khi nghỉ.
  • Dữ liệu không nằm ở mức cao hay thấp mà nằm ở độ dài của từng xung và từng khoảng nghỉ. Mỗi hãng quy định các độ dài đó theo một giao thức riêng; NEC là giao thức phổ biến nhất.

2. Giao thức NEC

Giao thức NEC: xung mở đầu 9 ms và nghỉ 4,5 ms; bit 0 gồm xung 1T và nghỉ 1T; bit 1 gồm xung 1T và nghỉ 3T; mã lặp gồm xung 9 ms, nghỉ 2,25 ms và một xung ngắn; một khung gồm địa chỉ, địa chỉ đảo, lệnh, lệnh đảo; khi giữ phím cứ 110 ms có một mã lặp
Bốn kiểu tín hiệu của NEC, một khung đầy đủ và chuỗi mã lặp khi giữ phím.

Đơn vị thời gian của NEC là T = 562,5 µs.

Thành phầnXungNghỉÝ nghĩa
Mở đầu9 ms (16T)4,5 ms (8T)Báo hiệu bắt đầu khung, giúp mắt thu ổn định độ nhạy
Bit 0562,5 µs (1T)562,5 µs (1T)Tổng 1,125 ms
Bit 1562,5 µs (1T)1687,5 µs (3T)Tổng 2,25 ms
Kết thúc562,5 µs (1T)không cóĐánh dấu hết khoảng nghỉ của bit cuối
Mã lặp9 ms, rồi 1T sau khoảng nghỉ2,25 ms (4T)Phím vẫn đang được giữ
  • Khung 32 bit gồm bốn byte: địa chỉ, địa chỉ đảo, lệnh, lệnh đảo. Mỗi byte gửi bit thấp trước.
  • Địa chỉ cho biết lệnh dành cho thiết bị nào, nhờ vậy điều khiển tivi không làm quạt đổi tốc độ. Lệnh là mã của phím.
  • Byte đảo là byte liền trước với mọi bit lật lại. Bên thu kiểm tra: lệnh XOR lệnh đảo phải bằng 0xFF, sai thì bỏ khung. Đây là cách kiểm tra lỗi của NEC.
  • Nhờ byte đảo, khung nào cũng có đúng 16 bit 0 và 16 bit 1 nên luôn dài như nhau, khoảng 68 ms.
  • Mã lặp: khi giữ phím, điều khiển chỉ gửi khung đầy đủ một lần; sau đó cứ 110 ms gửi một mã lặp ngắn. Thiết bị dùng mã lặp để tăng âm lượng liên tục, còn phím nguồn thì bỏ qua mã lặp để không bật tắt liên hồi.
  • NEC mở rộng: nhiều điều khiển dùng cả hai byte đầu làm địa chỉ 16 bit, không còn byte địa chỉ đảo; phần lệnh và lệnh đảo giữ nguyên.

3. Chuẩn bị

  • Một hoặc hai mạch ESP32 DevKit V1 30 chân (hoặc bản dùng chip CH340).
  • Một mắt thu hồng ngoại 38 kHz loại ba chân (dạng linh kiện rời hoặc module).
  • Một LED hồng ngoại 940 nm và một điện trở 100 Ω.
  • Một điều khiển hồng ngoại bất kỳ trong nhà để thử chương trình thu.
  • Breadboard, dây cắm và cáp USB.
  • Arduino IDE 2.x với gói esp32 by Espressif Systems (bài dùng phiên bản 3.3.10). Không cần cài thêm thư viện.

4. Sơ đồ nối

Sơ đồ nối ESP32 DevKit V1 với mắt thu hồng ngoại 38 kHz và LED hồng ngoại: chân OUT của mắt thu nối D18, VCC nối 3V3, GND nối GND; cực dương LED hồng ngoại nối D4 qua điện trở 100 ôm, cực âm nối GND
Mắt thu nối D18 và nguồn 3,3 V; LED hồng ngoại nối D4 qua điện trở 100 Ω.
  • Phần lớn mắt thu 38 kHz chạy được ở 3,3 V, nên cấp nguồn từ chân 3V3 và nối thẳng ngõ ra vào D18.
  • Thứ tự chân của mắt thu không giống nhau giữa các loại. Xem ký hiệu trên module hoặc tài liệu của linh kiện; nối ngược nguồn làm hỏng mắt thu.
  • Điện trở 100 Ω giới hạn dòng qua LED hồng ngoại ở khoảng 15 đến 20 mA, mức một chân ESP32 cấp trực tiếp được. Cách nối này đủ để thử ở khoảng cách gần.
  • Muốn phát xa hơn, dùng một transistor NPN để đóng cắt LED từ nguồn 5 V, chân D4 chỉ điều khiển cực nền của transistor qua một điện trở.
  • Mắt người không thấy LED hồng ngoại sáng. Camera điện thoại thường thấy được: LED hiện thành một đốm tím nhạt khi đang phát.

5. Chương trình 1: giải mã điều khiển

/*
  PYWORLD.VN - Hồng ngoại NEC với ESP32: mạch thu, giải mã khung 32 bit bằng cách đo thời gian trong hàm ngắt
  In địa chỉ và lệnh của phím vừa nhấn, nhận biết mã lặp khi giữ phím; lệnh 0x45 đổi trạng thái LED GPIO2
  Mắt thu hồng ngoại 38 kHz: OUT = D18, VCC = 3V3, GND = GND (ngõ ra ở mức thấp khi có tín hiệu)
*/

#define IR_RX_PIN 18
#define LED_PIN 2

const uint8_t LENH_DOI_DEN = 0x45;       // Sửa theo lệnh của phím muốn dùng

// Giới hạn thời gian, micro giây (giá trị chuẩn ghi trong ngoặc)
const uint32_t XUNG_DAU_MIN = 7000, XUNG_DAU_MAX = 11000;    // Xung mở đầu (9000)
const uint32_t NGHI_DAU_MIN = 3500, NGHI_DAU_MAX = 5500;     // Khoảng nghỉ sau xung mở đầu (4500)
const uint32_t NGHI_LAP_MIN = 1700, NGHI_LAP_MAX = 2800;     // Khoảng nghỉ của mã lặp (2250)
const uint32_t XUNG_BIT_MIN = 300, XUNG_BIT_MAX = 900;       // Xung của mỗi bit (562)
const uint32_t NGHI_BIT0_MIN = 300, NGHI_BIT0_MAX = 900;     // Khoảng nghỉ của bit 0 (562)
const uint32_t NGHI_BIT1_MIN = 1200, NGHI_BIT1_MAX = 2100;   // Khoảng nghỉ của bit 1 (1687)

enum TrangThai : uint8_t { CHO_XUNG_DAU, CHO_NGHI_DAU, NHAN_BIT };

volatile uint32_t khungVuaNhan = 0;
volatile bool coKhungMoi = false;
volatile bool coMaLap = false;

// Chạy mỗi khi ngõ ra của mắt thu đổi mức
void IRAM_ATTR khiDoiMuc() {
  static unsigned long lucTruoc = 0;
  static TrangThai trangThai = CHO_XUNG_DAU;
  static uint8_t soBit = 0;
  static uint32_t duLieu = 0;

  unsigned long bayGio = micros();
  uint32_t doDai = bayGio - lucTruoc;
  lucTruoc = bayGio;

  if (digitalRead(IR_RX_PIN) == HIGH) {
    // Sườn lên: vừa hết một đoạn mức thấp, tức một xung hồng ngoại
    if (doDai > XUNG_DAU_MIN && doDai < XUNG_DAU_MAX) {
      trangThai = CHO_NGHI_DAU;
    } else if (trangThai == NHAN_BIT && (doDai < XUNG_BIT_MIN || doDai > XUNG_BIT_MAX)) {
      trangThai = CHO_XUNG_DAU;                    // Xung sai độ dài: bỏ khung
    }
    return;
  }

  // Sườn xuống: vừa hết một khoảng nghỉ
  if (trangThai == CHO_NGHI_DAU) {
    if (doDai > NGHI_DAU_MIN && doDai < NGHI_DAU_MAX) {
      trangThai = NHAN_BIT;                        // Khung đầy đủ: 32 bit theo sau
      soBit = 0;
      duLieu = 0;
    } else {
      if (doDai > NGHI_LAP_MIN && doDai < NGHI_LAP_MAX) {
        coMaLap = true;                            // Mã lặp: phím vẫn đang được giữ
      }
      trangThai = CHO_XUNG_DAU;
    }
    return;
  }
  if (trangThai != NHAN_BIT) {
    return;
  }
  if (doDai > NGHI_BIT1_MIN && doDai < NGHI_BIT1_MAX) {
    duLieu |= (1UL << soBit);                      // Bit thấp tới trước
  } else if (doDai < NGHI_BIT0_MIN || doDai > NGHI_BIT0_MAX) {
    trangThai = CHO_XUNG_DAU;                      // Khoảng nghỉ sai độ dài: bỏ khung
    return;
  }
  soBit++;
  if (soBit == 32) {
    khungVuaNhan = duLieu;
    coKhungMoi = true;
    trangThai = CHO_XUNG_DAU;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(IR_RX_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(IR_RX_PIN), khiDoiMuc, CHANGE);
  Serial.printf("\nMach thu hong ngoai NEC tren D%d. Huong dieu khien vao mat thu roi nhan phim\n", IR_RX_PIN);
}

void loop() {
  static bool denDangSang = false;

  if (coKhungMoi) {
    noInterrupts();
    uint32_t khung = khungVuaNhan;
    coKhungMoi = false;
    coMaLap = false;
    interrupts();

    uint8_t diaChi = khung & 0xFF;
    uint8_t diaChiDao = (khung >> 8) & 0xFF;
    uint8_t lenh = (khung >> 16) & 0xFF;
    uint8_t lenhDao = (khung >> 24) & 0xFF;

    if ((uint8_t)(lenh ^ lenhDao) != 0xFF) {
      Serial.printf("Khung 0x%08X: lenh va byte dao khong khop, bo qua\n", (unsigned)khung);
      return;
    }
    if ((uint8_t)(diaChi ^ diaChiDao) == 0xFF) {
      Serial.printf("NEC: dia chi 0x%02X, lenh 0x%02X", diaChi, lenh);
    } else {
      Serial.printf("NEC mo rong: dia chi 0x%04X, lenh 0x%02X", (unsigned)(khung & 0xFFFF), lenh);
    }
    if (lenh == LENH_DOI_DEN) {
      denDangSang = !denDangSang;
      digitalWrite(LED_PIN, denDangSang ? HIGH : LOW);
      Serial.print(denDangSang ? " -> BAT LED" : " -> TAT LED");
    }
    Serial.println();
  } else if (coMaLap) {
    coMaLap = false;
    Serial.println("Ma lap: phim dang duoc giu");
  }
}

Hàm ngắt khiDoiMuc() chạy ở mỗi lần ngõ ra của mắt thu đổi mức và đo thời gian từ lần đổi mức trước. Vì ngõ ra đảo mức, sườn lên nghĩa là một xung vừa kết thúc, sườn xuống nghĩa là một khoảng nghỉ vừa kết thúc.

  1. Gặp một xung dài khoảng 9 ms: đó là xung mở đầu, chuyển sang chờ khoảng nghỉ theo sau.
  2. Khoảng nghỉ đó dài khoảng 4,5 ms thì bắt đầu nhận 32 bit; dài khoảng 2,25 ms thì đây là mã lặp.
  3. Với mỗi bit, xung phải dài khoảng 1T; khoảng nghỉ khoảng 1T là bit 0, khoảng 3T là bit 1. Bit tới trước được ghi vào vị trí thấp trước.
  4. Bất kỳ độ dài nào nằm ngoài khoảng cho phép đều làm khung bị bỏ; hàm quay về chờ xung mở đầu.
  5. Đủ 32 bit thì chuyển cho loop(), ở đó chương trình kiểm tra byte đảo rồi in địa chỉ và lệnh.

Các giới hạn thời gian để rộng vì mắt thu thường kéo dài xung và rút ngắn khoảng nghỉ một chút. Nhấn lần lượt các phím của điều khiển và ghi lại lệnh của từng phím; sửa LENH_DOI_DEN thành lệnh của phím muốn dùng để bật tắt đèn LED trên mạch.

6. Chương trình 2: phát lệnh NEC

/*
  PYWORLD.VN - Hồng ngoại NEC với ESP32: mạch phát, tạo sóng mang 38 kHz bằng LEDC và tự dựng khung 32 bit
  Nhấn nút BOOT (GPIO0) để gửi một khung; giữ nút thì cứ 110 ms gửi thêm một mã lặp, đúng như điều khiển thật
  LED hồng ngoại: cực dương nối D4 qua điện trở 100 ôm, cực âm nối GND
*/

#define IR_TX_PIN 4
#define NUT_PIN 0                          // Nút BOOT trên mạch, nhấn là mức thấp

const uint32_t TAN_SO_SONG_MANG = 38000;   // Hz
const uint8_t DO_PHAN_GIAI_BIT = 8;        // Độ rộng xung tính trên thang 0 đến 255
const uint32_t DO_RONG_KHI_PHAT = 85;      // Khoảng 33 %: LED sáng một phần ba mỗi chu kỳ sóng mang

const uint8_t DIA_CHI = 0x00;
const uint8_t LENH = 0x45;

// Thời gian của giao thức NEC, micro giây
const unsigned int XUNG_DAU_US = 9000;
const unsigned int NGHI_DAU_US = 4500;
const unsigned int NGHI_LAP_US = 2250;
const unsigned int XUNG_BIT_US = 563;
const unsigned int NGHI_BIT0_US = 562;
const unsigned int NGHI_BIT1_US = 1687;
const unsigned long CHU_KY_LAP_MS = 110;

// Xung: bật sóng mang 38 kHz trong khoảng thời gian cho trước
void phatXung(unsigned int thoiGianUs) {
  ledcWrite(IR_TX_PIN, DO_RONG_KHI_PHAT);
  delayMicroseconds(thoiGianUs);
}

// Nghỉ: tắt hẳn LED
void nghi(unsigned int thoiGianUs) {
  ledcWrite(IR_TX_PIN, 0);
  delayMicroseconds(thoiGianUs);
}

void guiKhungNec(uint8_t diaChi, uint8_t lenh) {
  // Thứ tự trên đường truyền: địa chỉ, địa chỉ đảo, lệnh, lệnh đảo; mỗi byte gửi bit thấp trước
  uint32_t duLieu = (uint32_t)diaChi | ((uint32_t)(uint8_t)~diaChi << 8)
                    | ((uint32_t)lenh << 16) | ((uint32_t)(uint8_t)~lenh << 24);
  phatXung(XUNG_DAU_US);
  nghi(NGHI_DAU_US);
  for (int i = 0; i < 32; i++) {
    phatXung(XUNG_BIT_US);
    nghi(((duLieu >> i) & 1) ? NGHI_BIT1_US : NGHI_BIT0_US);
  }
  phatXung(XUNG_BIT_US);                   // Xung kết thúc: đánh dấu hết khoảng nghỉ của bit cuối
  nghi(0);
}

void guiMaLap() {
  phatXung(XUNG_DAU_US);
  nghi(NGHI_LAP_US);
  phatXung(XUNG_BIT_US);
  nghi(0);
}

void setup() {
  Serial.begin(115200);
  pinMode(NUT_PIN, INPUT_PULLUP);
  ledcAttach(IR_TX_PIN, TAN_SO_SONG_MANG, DO_PHAN_GIAI_BIT);
  ledcWrite(IR_TX_PIN, 0);
  Serial.printf("\nMach phat hong ngoai NEC: song mang %u Hz tren D%d. Nhan nut BOOT de gui\n",
                (unsigned)TAN_SO_SONG_MANG, IR_TX_PIN);
}

void loop() {
  if (digitalRead(NUT_PIN) != LOW) {
    return;
  }
  delay(30);                               // Chống dội nút nhấn
  if (digitalRead(NUT_PIN) != LOW) {
    return;
  }

  unsigned long lucBatDau = millis();
  guiKhungNec(DIA_CHI, LENH);
  Serial.printf("Da gui khung NEC: dia chi 0x%02X, lenh 0x%02X\n", DIA_CHI, LENH);

  int soMaLap = 0;
  while (digitalRead(NUT_PIN) == LOW) {    // Còn giữ nút: gửi mã lặp theo chu kỳ 110 ms
    if (millis() - lucBatDau >= CHU_KY_LAP_MS) {
      lucBatDau = millis();
      guiMaLap();
      soMaLap++;
    }
    delay(1);
  }
  if (soMaLap > 0) {
    Serial.printf("Da gui them %d ma lap\n", soMaLap);
  }
}
  • Sóng mang do bộ LEDC của ESP32 tạo ra: ledcAttach() đặt tần số 38 kHz với độ phân giải 8 bit. Ghi giá trị 85 (khoảng 33 %) là bật sóng mang, ghi 0 là tắt.
  • LED chỉ sáng một phần ba mỗi chu kỳ: đủ cho mắt thu nhận, lại giảm dòng trung bình qua LED.
  • guiKhungNec() ghép bốn byte thành một số 32 bit rồi gửi từ bit 0 đến bit 31, đúng thứ tự bit thấp trước của NEC.
  • Khi còn giữ nút, vòng while gửi mã lặp mỗi 110 ms tính từ lúc bắt đầu lần gửi trước.

Để điều khiển một thiết bị có sẵn, dùng chương trình 1 đọc địa chỉ và lệnh của phím trên điều khiển gốc, rồi điền hai giá trị đó vào DIA_CHI và LENH. Điều khiển dùng NEC mở rộng có địa chỉ 16 bit; khi đó cần sửa guiKhungNec() để gửi hai byte địa chỉ thay cho địa chỉ và địa chỉ đảo. Nền tảng về LEDC có trong bài PWM trên ESP32.

7. Kết quả mong đợi

Hình minh họa Serial Monitor của mạch phát và mạch thu hồng ngoại NEC: mạch phát in địa chỉ, lệnh đã gửi và số mã lặp; mạch thu in địa chỉ, lệnh nhận được, việc bật tắt LED và các dòng mã lặp khi giữ phím
Kết quả mong đợi trên Serial Monitor của hai mạch (hình minh họa).
  1. Nạp chương trình 1, mở Tools > Serial Monitor ở 115200 baud. Hướng một điều khiển trong nhà vào mắt thu và nhấn phím: mỗi phím cho một dòng địa chỉ và lệnh.
  2. Giữ phím: sau dòng đầu tiên là các dòng báo mã lặp.
  3. Nạp chương trình 2 cho mạch thứ hai, hướng LED hồng ngoại vào mắt thu của mạch thứ nhất rồi nhấn nút BOOT: mạch thu in địa chỉ 0x00, lệnh 0x45 và đèn LED trên mạch đổi trạng thái.
  4. Giữ nút BOOT: mạch thu in thêm các dòng mã lặp, đèn không đổi trạng thái thêm.

8. Giới hạn và hướng mở rộng

  • Không phải điều khiển nào cũng dùng NEC. Một số hãng dùng sóng mang 36 kHz hoặc 40 kHz và cách mã hóa bit khác; điều khiển máy lạnh thường gửi khung rất dài chứa toàn bộ trạng thái. Chương trình 1 không in gì với các điều khiển đó.
  • Truyền một chiều, cần nhìn thấy nhau: hồng ngoại không xuyên tường, mạch phát không biết lệnh đã tới nơi chưa.
  • Ánh nắng trực tiếp và một số loại đèn làm giảm tầm thu. Đặt mắt thu khuất nắng.
  • Thời gian chính xác: chương trình phát dùng delayMicroseconds() nên chiếm trọn vi điều khiển trong khoảng 68 ms mỗi khung. Dự án lớn có thể chuyển sang bộ RMT của ESP32, phần cứng chuyên tạo và đo chuỗi xung.

9. Xử lý lỗi thường gặp

Hiện tượngNguyên nhân thường gặpCách xử lý
Nhấn phím điều khiển mà không in gìNối sai thứ tự chân mắt thu, hoặc điều khiển không dùng NECKiểm tra lại ba chân; thử một điều khiển khác
Báo lệnh và byte đảo không khớpNhiễu ánh sáng hoặc điều khiển ở quá xa làm sai một vài bitĐưa điều khiển lại gần, che nắng cho mắt thu
Chỉ thấy mã lặp, không thấy khung đầy đủKhung đầu tiên bị lỗi, các mã lặp theo sau vẫn nhận đượcNhả phím rồi nhấn lại; hướng điều khiển thẳng vào mắt thu
Mạch thu không nhận được mạch phátLED hồng ngoại cắm ngược, sai chân, hoặc đặt quá xaNhìn LED qua camera điện thoại khi nhấn nút; đổi chiều LED; đưa hai mạch lại gần
Thiết bị thật không phản ứng với lệnh đã chépĐiều khiển gốc dùng NEC mở rộng, hoặc sai địa chỉXem chương trình 1 in "NEC mo rong" hay không; gửi đúng hai byte địa chỉ
Tầm phát quá ngắnDòng qua LED nhỏ, góc phát hẹpDùng transistor để tăng dòng xung; hướng LED thẳng vào mắt thu

10. Xem thêm


Tin tức liên quan

Bluetooth Low Energy (BLE) là gì: quảng bá, GATT, dịch vụ, đặc tính và ESP32
Bluetooth Low Energy (BLE) là gì: quảng bá, GATT, dịch vụ, đặc tính và ESP32

Giải thích Bluetooth Low Energy: quảng bá và kết nối, cấu trúc GATT gồm dịch vụ, đặc tính, mô tả, UUID. Hướng dẫn cho ESP32 làm thiết bị BLE có đặc tính đọc, ghi, thông báo và thử bằng điện thoại.

RF 433 MHz là gì: điều chế ASK/OOK và tự viết giao thức phát, thu bằng ESP32
RF 433 MHz là gì: điều chế ASK/OOK và tự viết giao thức phát, thu bằng ESP32

Giải thích sóng RF 433 MHz và điều chế ASK/OOK, cách mã hóa bit bằng độ rộng xung và khung tin 24 bit. Hướng dẫn tự viết chương trình phát và thu trên hai mạch ESP32, không dùng thư viện ngoài.

Vòng dòng 4-20 mA là gì và cách đọc cảm biến 4-20 mA bằng ESP32
Vòng dòng 4-20 mA là gì và cách đọc cảm biến 4-20 mA bằng ESP32

Giải thích vòng dòng 4-20 mA: vì sao dùng dòng điện, vì sao bắt đầu từ 4 mA, cách đổi ra giá trị đo và ngưỡng báo lỗi. Hướng dẫn đọc bằng ESP32 qua điện trở shunt 120 Ω, với ADC có sẵn và với ADS1115.

CAN bus (phần 2): bộ lọc nhận, tốc độ bit và xử lý lỗi bus-off trên ESP32
CAN bus (phần 2): bộ lọc nhận, tốc độ bit và xử lý lỗi bus-off trên ESP32

Phần 2 về CAN bus với ESP32: đặt bộ lọc nhận theo mã lọc và mặt nạ, chọn tốc độ bit theo chiều dài dây, hiểu ba trạng thái lỗi của nút và viết chương trình theo dõi bộ đếm lỗi, tự hồi phục sau bus-off.

CAN bus (phần 1): tín hiệu, khung tin, phân xử ưu tiên và gửi nhận bằng ESP32
CAN bus (phần 1): tín hiệu, khung tin, phân xử ưu tiên và gửi nhận bằng ESP32

Giải thích CAN bus: hai dây CAN_H, CAN_L, mức trội và mức lặn, khung tin có ID 11 bit, phân xử ưu tiên, CRC và ACK. Kèm hai chương trình ESP32 dùng bộ điều khiển TWAI: tự kiểm tra và hai nút gửi nhận.

Modbus TCP/IP (phần 2): ESP32 làm máy khách và cổng chuyển đổi Modbus TCP sang RTU
Modbus TCP/IP (phần 2): ESP32 làm máy khách và cổng chuyển đổi Modbus TCP sang RTU

Hướng dẫn dùng ESP32 làm máy khách Modbus TCP đọc thanh ghi của một thiết bị trong mạng, và làm cổng chuyển đổi Modbus TCP sang Modbus RTU qua RS-485: cách đổi khung, mã thiết bị, thời gian chờ, mã lỗi 0x0B.

Modbus TCP/IP (phần 1): phần đầu MBAP và ESP32 làm máy chủ qua Wi-Fi
Modbus TCP/IP (phần 1): phần đầu MBAP và ESP32 làm máy chủ qua Wi-Fi

Giải thích Modbus TCP/IP: phần đầu MBAP, cổng 502, điểm khác với Modbus RTU. Kèm chương trình ESP32 làm máy chủ Modbus TCP qua Wi-Fi với 10 thanh ghi giữ và 8 cuộn, tự phân tích khung, không dùng thư viện.

TCP và UDP là gì: địa chỉ IP, cổng, kết nối và cách dùng trên ESP32
TCP và UDP là gì: địa chỉ IP, cổng, kết nối và cách dùng trên ESP32

Giải thích TCP và UDP cho người làm vi điều khiển: địa chỉ IP, cổng, kết nối, xác nhận, vì sao TCP là dòng byte. Kèm hai chương trình ESP32: máy chủ TCP nhận lệnh và phát, nhận gói UDP trong mạng Wi-Fi.


Bình luận
Đã thêm vào giỏ hàng