Phased array siêu âm 40 kHz với ESP32 (phần 2): mạch đệm 12 V, đầu thu và quét búp sóng

Phần 2 của loạt phased array siêu âm: thêm mạch đệm 12 V bằng hai module L298N, lắp mạch thu dùng LM358, đo biên độ 40 kHz bằng ADC của ESP32 và chạy chương trình tự quét góc lái để xem búp sóng.

Phần 1 đã dùng ESP32 tạo tám kênh xung 40 kHz lệch pha cho một mảng tám đầu phát siêu âm. Phần 2 hoàn thiện hệ thống để nhìn thấy kết quả: thêm mạch đệm 12 V cho mảng phát, lắp một mạch thu đơn giản và để chính ESP32 quét góc lái, đo biên độ ở từng góc rồi in ra giản đồ hướng của mảng.

Bài dùng lại mảng tám đầu phát, thứ tự chân và cách tính pha của phần 1. Nếu chưa lắp mảng phát, nên làm phần 1 trước.

1. Hệ thống gồm những gì?

Sơ đồ khối hệ thống phased array siêu âm với ESP32: ESP32 tạo tám kênh xung, mạch đệm L298N, mảng tám đầu phát, đầu thu, mạch khuếch đại LM358 và chân ADC D34
Một mạch ESP32 vừa tạo xung cho mảng phát, vừa đo biên độ tại đầu thu (hình vẽ minh họa).
  • Phát: ESP32 tạo tám kênh xung 3,3 V; hai module L298N đệm lên 12 V để đầu phát phát mạnh hơn.
  • Thu: một đầu thu siêu âm 40 kHz đặt cách mảng 1,5 đến 2 m. Tín hiệu thu chỉ cỡ vài chục mV nên cần một tầng khuếch đại dùng LM358.
  • Đo: ngõ ra mạch khuếch đại nối vào chân ADC D34. ESP32 đổi góc lái từng bước và đo biên độ ở mỗi bước.

2. Chuẩn bị

  • Mảng tám đầu phát và mạch ESP32 DevKit V1 30 chân của phần 1.
  • Hai module L298N (loại có cọc vít 12V, GND, 5V và hàng chân IN1 đến IN4).
  • Nguồn 12 V một chiều, từ 0,5 A. Có thể tạo 12 V từ một nguồn 5 V riêng bằng module tăng áp XL6009E1; không lấy nguồn cho mạch đệm từ chân VIN của ESP32.
  • Một đầu thu siêu âm 40 kHz (trên thân thường in chữ R).
  • Một IC LM358, điện trở 10 kΩ (3 chiếc), 100 kΩ (2 chiếc), 4,7 kΩ (1 chiếc), tụ 10 µF và tụ 100 nF.
  • Breadboard và dây cắm.

3. Mạch đệm 12 V với hai module L298N

Sơ đồ nối ESP32 DevKit V1 với hai module L298N và mảng tám đầu phát siêu âm: D23, D22, D21, D19 vào IN1 đến IN4 của module A, D18, TX2, RX2, D4 vào module B, nguồn 12 V và GND chung
Mỗi module L298N đệm bốn kênh; mọi điểm GND nối chung với GND của ESP32.
  • L298N vốn là mạch điều khiển động cơ có bốn ngõ ra. Ở đây mỗi ngõ ra dùng như một tầng đệm độc lập: ngõ vào ở mức cao thì ngõ ra lên gần bằng điện áp nguồn, ở mức thấp thì ngõ ra xuống gần 0 V.
  • Ngõ vào của L298N nhận được mức 3,3 V của ESP32, nên nối thẳng tám chân GPIO vào IN1 đến IN4 của hai module.
  • Mỗi đầu phát nối giữa một ngõ ra OUT và GND, cùng chiều cực tính như ở phần 1.
  • Giữ nguyên hai jumper ENA, ENB (cho phép ngõ ra) và jumper 5V-EN (module tự tạo 5 V cho phần logic).
  • GND của nguồn 12 V, của hai module và của ESP32 phải nối chung. Không nối cọc 5V của module vào ESP32 khi ESP32 đang cắm USB.
  • Mạch đệm làm mọi kênh trễ thêm một khoảng nhỏ. Hai module cùng loại nên các kênh trễ gần như nhau, độ lệch pha giữa các kênh hầu như giữ nguyên.

Do sụt áp bên trong L298N, xung trên đầu phát có biên độ khoảng 10 V. Phần lớn đầu phát 40 kHz chịu được mức này; nên xem thông số của loại đang dùng và không cấp nguồn cao hơn 12 V.

4. Mạch thu: đầu thu và LM358

Sơ đồ nguyên lý mạch thu siêu âm: đầu thu 40 kHz, LM358 mắc khuếch đại không đảo, cầu phân áp tạo điểm 1,65 V, ngõ ra qua điện trở bảo vệ vào chân D34 của ESP32
Mạch khuếch đại không đảo dùng một nửa LM358, tín hiệu ra dao động quanh mức 1,65 V.
  • Điểm 1,65 V: R1, R2 chia đôi điện áp 3,3 V, tụ C1 giữ cho điểm này ổn định. Tín hiệu sau khuếch đại dao động quanh mức 1,65 V, nằm giữa dải đo của ADC.
  • Khuếch đại: hệ số danh định là 1 + R4/R5, khoảng 22 lần. Ở 40 kHz hệ số thực tế thấp hơn vì băng thông của LM358 có hạn. Tụ C2 làm cho mạch chỉ khuếch đại phần xoay chiều.
  • Nguồn: LM358 lấy 5 V từ chân VIN của ESP32 (chân 8) và GND (chân 4).
  • Bảo vệ: R6 hạn dòng vào chân D34 trong trường hợp ngõ ra LM358 vượt quá 3,3 V.
  • Nửa còn lại của LM358 không dùng: nối chân 6 với chân 7, chân 5 nối vào điểm 1,65 V.
  • Lắp mạch thu trên một breadboard riêng, dây nối đầu thu thật ngắn và đặt xa mạch đệm để xung 12 V không lọt thẳng vào mạch thu.

5. Đo biên độ 40 kHz bằng ADC chậm

  • Một chu kỳ sóng 40 kHz chỉ dài 25 µs, trong khi mỗi lần đọc ADC bằng analogReadMilliVolts() mất nhiều thời gian hơn thế. ESP32 không thể lấy đủ mẫu để vẽ lại từng chu kỳ.
  • Tuy vậy, sóng lặp lại đều đặn. Nếu lấy vài trăm mẫu ở các thời điểm ngẫu nhiên, các mẫu sẽ rơi đều vào mọi vị trí của chu kỳ.
  • Độ lệch chuẩn của các mẫu chính là giá trị hiệu dụng của phần xoay chiều; nhân với 1,414 ra biên độ đỉnh của sóng sin.
  • Chương trình chèn một khoảng trễ ngẫu nhiên giữa hai lần đọc để các mẫu không bị rơi mãi vào cùng một vị trí của chu kỳ.
  • Lúc khởi động, khi mảng chưa phát, chương trình đo nhiễu nền của mạch thu rồi trừ đi trong các phép đo sau.

Kết quả là một con số tỉ lệ với áp suất âm tại đầu thu. Con số này dùng để so sánh giữa các góc lái, không phải phép đo áp suất âm tuyệt đối. Kiến thức nền về ADC có trong bài đo điện áp bằng ADC của ESP32.

6. Chương trình 1: đo biên độ, đổi góc bằng tay

Chương trình phát ở góc lái 0° và in biên độ bốn lần mỗi giây. Dùng chương trình này để kiểm tra mạch thu và căn chỉnh vị trí đầu thu trước khi quét.

/*
  PYWORLD.VN - Phased array siêu âm 40 kHz: đo biên độ tại đầu thu khi đổi góc lái bằng tay
  ESP32 phát 8 kênh lệch pha qua mạch đệm; đầu thu siêu âm qua mạch khuếch đại nối vào D34
  In "bien_do_mV:..,goc:.." bốn lần mỗi giây để xem bằng Serial Monitor hoặc Serial Plotter
*/

#include <driver/ledc.h>

#define CHAN_THU 34                           // Ngõ ra mạch khuếch đại của đầu thu

const int SO_KENH = 8;
const int CHAN_PHAT[SO_KENH] = {23, 22, 21, 19, 18, 17, 16, 4};   // Kênh 0 đến kênh 7

const uint32_t TAN_SO_HZ = 40000;
const uint32_t SO_BUOC = 1024;
const uint32_t NUA_CHU_KY = SO_BUOC / 2;

const float KHOANG_CACH_MM = 10.16;           // Khoảng cách tâm hai đầu phát kề nhau
const float NHIET_DO_C = 30.0;
const float GOC_TOI_DA = 60.0;

float nenMv = 0;                              // Nhiễu nền đo lúc chưa phát
float gocHienTai = 0;

void datKenh(int kenh, uint32_t hpoint) {
  bool dao = hpoint >= NUA_CHU_KY;            // Nửa chu kỳ sau: lùi nửa chu kỳ rồi đảo tín hiệu ra

  ledc_channel_config_t cauHinh = {};
  cauHinh.gpio_num = CHAN_PHAT[kenh];
  cauHinh.speed_mode = LEDC_HIGH_SPEED_MODE;
  cauHinh.channel = (ledc_channel_t)kenh;
  cauHinh.intr_type = LEDC_INTR_DISABLE;
  cauHinh.timer_sel = LEDC_TIMER_0;
  cauHinh.duty = NUA_CHU_KY;
  cauHinh.hpoint = dao ? hpoint - NUA_CHU_KY : hpoint;
  cauHinh.flags.output_invert = dao ? 1 : 0;
  ledc_channel_config(&cauHinh);
}

void laiBupSong(float gocDo) {
  float vanTocAm = 331.3f + 0.606f * NHIET_DO_C;
  float buocSongMm = vanTocAm * 1000.0f / TAN_SO_HZ;
  float lechMoiKenh = KHOANG_CACH_MM * sinf(gocDo * DEG_TO_RAD) / buocSongMm;
  for (int i = 0; i < SO_KENH; i++) {
    float soChuKy = i * lechMoiKenh;
    float phanLe = soChuKy - floorf(soChuKy);
    datKenh(i, (uint32_t)lroundf(phanLe * SO_BUOC) % SO_BUOC);
  }
  gocHienTai = gocDo;
}

// Đo giá trị hiệu dụng của phần xoay chiều tại chân thu, đơn vị mV.
// analogReadMilliVolts chậm hơn chu kỳ 25 micro giây của sóng, nhưng sóng lặp lại đều nên các mẫu
// lấy ở thời điểm ngẫu nhiên vẫn trải đều trên một chu kỳ: độ lệch chuẩn của chúng là giá trị hiệu dụng.
float doHieuDungMv(float *mucMotChieu) {
  const int SO_MAU = 500;
  double tong = 0, tongBinhPhuong = 0;
  for (int i = 0; i < SO_MAU; i++) {
    double mv = analogReadMilliVolts(CHAN_THU);
    tong += mv;
    tongBinhPhuong += mv * mv;
    delayMicroseconds(random(0, 30));
  }
  double trungBinh = tong / SO_MAU;
  double phuongSai = tongBinhPhuong / SO_MAU - trungBinh * trungBinh;
  if (mucMotChieu != NULL) {
    *mucMotChieu = trungBinh;
  }
  return phuongSai > 0 ? sqrt(phuongSai) : 0;
}

// Biên độ đỉnh của sóng 40 kHz sau khi trừ nhiễu nền
float doBienDoMv() {
  float hieuDung = doHieuDungMv(NULL);
  float daTruNen = hieuDung * hieuDung - nenMv * nenMv;
  return daTruNen > 0 ? sqrtf(daTruNen) * 1.4142f : 0;
}

void setup() {
  Serial.begin(115200);
  analogSetPinAttenuation(CHAN_THU, ADC_11db);

  // Đo nhiễu nền trước khi phát: lúc này tám kênh chưa có xung
  delay(500);
  float mucMotChieu = 0;
  nenMv = doHieuDungMv(&mucMotChieu);
  Serial.printf("\nMuc mot chieu %.0f mV, nhieu nen %.1f mV\n", mucMotChieu, nenMv);

  ledc_timer_config_t boDem = {};
  boDem.speed_mode = LEDC_HIGH_SPEED_MODE;
  boDem.duty_resolution = LEDC_TIMER_10_BIT;
  boDem.timer_num = LEDC_TIMER_0;
  boDem.freq_hz = TAN_SO_HZ;
  boDem.clk_cfg = LEDC_AUTO_CLK;
  if (ledc_timer_config(&boDem) != ESP_OK) {
    Serial.println("Khong cau hinh duoc bo dem LEDC");
    while (true) {
      delay(1000);
    }
  }

  laiBupSong(0);
  Serial.println("Go goc lai tu -60 den 60 roi nhan Enter");
}

void loop() {
  if (Serial.available()) {
    String dong = Serial.readStringUntil('\n');
    dong.trim();
    if (dong.length() > 0) {
      float gocDo = dong.toFloat();
      if (gocDo >= -GOC_TOI_DA && gocDo <= GOC_TOI_DA) {
        laiBupSong(gocDo);
      } else {
        Serial.println("Goc phai tu -60 den 60");
      }
    }
  }

  Serial.printf("bien_do_mV:%.1f,goc:%.1f\n", doBienDoMv(), gocHienTai);
  delay(250);
}
  1. Dòng đầu tiên cho biết mạch thu có ổn không: Muc mot chieu nên ở quanh 1650 mV, nhieu nen chỉ nên vài mV.
  2. Xoay nhẹ đầu thu và mảng phát đến khi biên độ lớn nhất.
  3. Gõ 10 rồi Enter: búp sóng lệch khỏi đầu thu, biên độ giảm mạnh. Gõ 0 để quay lại.
  4. Nên giữ biên độ lớn nhất dưới khoảng 800 mV. LM358 không cho ra được sóng 40 kHz lớn hơn nhiều mức đó mà không méo; nếu vượt, đặt đầu thu xa hơn hoặc giảm R4 xuống 47 kΩ.

7. Bố trí đo

Bố trí đo búp sóng nhìn từ trên xuống: mảng tám đầu phát đứng yên, đầu thu đặt cách 1,5 đến 2 m ở vị trí 0 độ hoặc 20 độ so với pháp tuyến
Mảng phát đứng yên; đầu thu đặt cố định ở một góc đã biết, cách mảng 1,5 đến 2 m.
  • Khoảng cách: công thức lái búp sóng giả định đầu thu ở đủ xa để sóng từ tám đầu phát gần như song song. Với mảng dài khoảng 8 cm ở 40 kHz, khoảng cách đó là từ 1,5 m trở lên.
  • Độ cao: tâm đầu thu ngang với tâm hàng đầu phát, cả hai cao hơn mặt bàn ít nhất 20 cm.
  • Phản xạ: hướng mảng ra khoảng trống, tránh tường và vật cứng ở gần đường truyền. Phủ khăn hoặc mút lên mặt bàn giữa mảng và đầu thu.
  • Đứng yên khi đo: người di chuyển gần đường truyền và gió quạt đều làm biên độ thay đổi.

8. Chương trình 2: tự quét góc lái

Mỗi lượt quét, chương trình lái búp sóng từ -40° đến 40° theo bước 2°, chờ 30 ms cho sóng ổn định rồi đo biên độ. Kết quả in thành bảng 41 dòng, mỗi dòng kèm một thanh ngang tỉ lệ với biên độ.

/*
  PYWORLD.VN - Phased array siêu âm 40 kHz: tự quét góc lái và vẽ giản đồ hướng trên Serial Monitor
  Mỗi lượt quét từ -40 đến 40 độ, đo biên độ tại đầu thu (D34) ở từng góc rồi in bảng kèm thanh ngang
  Nhấn Enter trong Serial Monitor để quét lượt mới
*/

#include <driver/ledc.h>

#define CHAN_THU 34                           // Ngõ ra mạch khuếch đại của đầu thu

const int SO_KENH = 8;
const int CHAN_PHAT[SO_KENH] = {23, 22, 21, 19, 18, 17, 16, 4};   // Kênh 0 đến kênh 7

const uint32_t TAN_SO_HZ = 40000;
const uint32_t SO_BUOC = 1024;
const uint32_t NUA_CHU_KY = SO_BUOC / 2;

const float KHOANG_CACH_MM = 10.16;           // Khoảng cách tâm hai đầu phát kề nhau
const float NHIET_DO_C = 30.0;

const int GOC_QUET = 40;                      // Quét từ -GOC_QUET đến +GOC_QUET
const int BUOC_GOC = 2;
const int THOI_GIAN_ON_DINH_MS = 30;          // Chờ sóng mới truyền tới đầu thu và ổn định
const int DO_DAI_THANH = 40;                  // Số ký tự của thanh dài nhất

const int SO_DIEM = 2 * GOC_QUET / BUOC_GOC + 1;
float bienDo[SO_DIEM];
float nenMv = 0;

void datKenh(int kenh, uint32_t hpoint) {
  bool dao = hpoint >= NUA_CHU_KY;            // Nửa chu kỳ sau: lùi nửa chu kỳ rồi đảo tín hiệu ra

  ledc_channel_config_t cauHinh = {};
  cauHinh.gpio_num = CHAN_PHAT[kenh];
  cauHinh.speed_mode = LEDC_HIGH_SPEED_MODE;
  cauHinh.channel = (ledc_channel_t)kenh;
  cauHinh.intr_type = LEDC_INTR_DISABLE;
  cauHinh.timer_sel = LEDC_TIMER_0;
  cauHinh.duty = NUA_CHU_KY;
  cauHinh.hpoint = dao ? hpoint - NUA_CHU_KY : hpoint;
  cauHinh.flags.output_invert = dao ? 1 : 0;
  ledc_channel_config(&cauHinh);
}

void laiBupSong(float gocDo) {
  float vanTocAm = 331.3f + 0.606f * NHIET_DO_C;
  float buocSongMm = vanTocAm * 1000.0f / TAN_SO_HZ;
  float lechMoiKenh = KHOANG_CACH_MM * sinf(gocDo * DEG_TO_RAD) / buocSongMm;
  for (int i = 0; i < SO_KENH; i++) {
    float soChuKy = i * lechMoiKenh;
    float phanLe = soChuKy - floorf(soChuKy);
    datKenh(i, (uint32_t)lroundf(phanLe * SO_BUOC) % SO_BUOC);
  }
}

// Giá trị hiệu dụng của phần xoay chiều tại chân thu (mV): độ lệch chuẩn của các mẫu lấy ở thời điểm ngẫu nhiên
float doHieuDungMv() {
  const int SO_MAU = 500;
  double tong = 0, tongBinhPhuong = 0;
  for (int i = 0; i < SO_MAU; i++) {
    double mv = analogReadMilliVolts(CHAN_THU);
    tong += mv;
    tongBinhPhuong += mv * mv;
    delayMicroseconds(random(0, 30));
  }
  double trungBinh = tong / SO_MAU;
  double phuongSai = tongBinhPhuong / SO_MAU - trungBinh * trungBinh;
  return phuongSai > 0 ? sqrt(phuongSai) : 0;
}

// Biên độ đỉnh của sóng 40 kHz sau khi trừ nhiễu nền
float doBienDoMv() {
  float hieuDung = doHieuDungMv();
  float daTruNen = hieuDung * hieuDung - nenMv * nenMv;
  return daTruNen > 0 ? sqrtf(daTruNen) * 1.4142f : 0;
}

void quetMotLuot() {
  float lonNhat = 0;
  int gocLonNhat = 0;
  for (int i = 0; i < SO_DIEM; i++) {
    int gocDo = -GOC_QUET + i * BUOC_GOC;
    laiBupSong(gocDo);
    delay(THOI_GIAN_ON_DINH_MS);
    bienDo[i] = doBienDoMv();
    if (bienDo[i] > lonNhat) {
      lonNhat = bienDo[i];
      gocLonNhat = gocDo;
    }
  }
  laiBupSong(0);

  Serial.println("\nGoc(do)  Bien do(mV)");
  for (int i = 0; i < SO_DIEM; i++) {
    int soKyTu = lonNhat > 0 ? (int)lroundf(bienDo[i] / lonNhat * DO_DAI_THANH) : 0;
    Serial.printf("%6d  %10.1f  ", -GOC_QUET + i * BUOC_GOC, bienDo[i]);
    for (int k = 0; k < soKyTu; k++) {
      Serial.print('#');
    }
    Serial.println();
  }
  Serial.printf("Lon nhat %.1f mV tai goc lai %d do\n", lonNhat, gocLonNhat);
  Serial.println("Nhan Enter de quet lai");
}

void setup() {
  Serial.begin(115200);
  analogSetPinAttenuation(CHAN_THU, ADC_11db);

  // Đo nhiễu nền trước khi phát: lúc này tám kênh chưa có xung
  delay(500);
  nenMv = doHieuDungMv();
  Serial.printf("\nNhieu nen %.1f mV\n", nenMv);

  ledc_timer_config_t boDem = {};
  boDem.speed_mode = LEDC_HIGH_SPEED_MODE;
  boDem.duty_resolution = LEDC_TIMER_10_BIT;
  boDem.timer_num = LEDC_TIMER_0;
  boDem.freq_hz = TAN_SO_HZ;
  boDem.clk_cfg = LEDC_AUTO_CLK;
  if (ledc_timer_config(&boDem) != ESP_OK) {
    Serial.println("Khong cau hinh duoc bo dem LEDC");
    while (true) {
      delay(1000);
    }
  }

  quetMotLuot();
}

void loop() {
  if (!Serial.available()) {
    return;
  }
  while (Serial.available()) {
    Serial.read();
    delay(2);
  }
  quetMotLuot();
}

9. Kết quả mong đợi

Đồ thị tính toán biên độ tại đầu thu khi quét góc lái từ âm 40 đến 40 độ: một đỉnh ở 0 độ khi đầu thu đặt ở 0 độ, hai đỉnh ở 20 độ và âm 31 độ khi đầu thu đặt ở 20 độ
Biên độ tại đầu thu theo góc lái, tính theo công thức (không phải số đo).
Hình minh họa Serial Monitor của hai chương trình: mức một chiều, nhiễu nền và biên độ theo góc lái, bảng quét góc lái kèm thanh ngang với đỉnh ở 0 độ
Kết quả mong đợi trên Serial Monitor (hình minh họa, biên độ là số ví dụ tính theo công thức).
  1. Đầu thu ở chính diện (0°): bảng có một đỉnh rõ ở góc lái 0°. Biên độ giảm nhanh khi lái lệch vài độ, rồi lên xuống nhẹ theo các búp phụ.
  2. Dời đầu thu sang 20°: quét lại, đỉnh dời theo tới khoảng 20°. Đây là bằng chứng búp sóng được lái bằng pha: mảng phát không hề xoay.
  3. Đỉnh thứ hai: khi đầu thu ở 20°, bảng còn một đỉnh nữa ở khoảng -31°. Đó là lúc búp lặp của mảng quét qua đầu thu, đúng như tính toán ở phần 1.
  4. Vì đầu thu đứng yên trong suốt lượt quét, hướng tính riêng của đầu thu và của từng đầu phát không làm đổi hình dạng đường cong.

Số đo thật không đẹp như hình tính toán: đỉnh thấp hơn, đáy không về 0 và vị trí đỉnh có thể lệch vài độ. Nguyên nhân là phản xạ trong phòng, dung sai giữa các đầu phát và khoảng cách đo hữu hạn.

10. Thử nghiệm thêm

  • Đổi BUOC_GOC thành 1 để thấy rõ hơn bề rộng búp chính, khoảng 5,5° ở mức nửa công suất.
  • Đổi SO_KENH thành 4, bớt bốn chân cuối trong CHAN_PHAT và rút dây bốn kênh đó: búp chính rộng ra gấp đôi.
  • Đảo cực một đầu phát rồi quét lại để thấy búp sóng xấu đi thế nào.
  • Đặt đầu thu lần lượt ở 10°, 20°, 30° và ghi lại góc lái có biên độ lớn nhất để so với góc đặt thật.

11. Lưu ý an toàn

  • Với mạch đệm 12 V, mảng phát mạnh hơn nhiều so với phần 1. Không áp sát mảng vào tai và không để mảng phát liên tục gần chó, mèo, vật nuôi.
  • Ngắt nguồn 12 V trước khi sửa dây. L298N ấm lên khi chạy là bình thường; nếu nóng nhanh, kiểm tra chạm chập ở ngõ ra.
  • Chân D34 chỉ chịu được điện áp trong khoảng 0 đến 3,3 V. Không bỏ điện trở R6 và không nối ngõ ra mạch đệm vào ESP32.

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

Hiện tượngNguyên nhân thường gặpCách xử lý
Muc mot chieu khác xa 1650 mVSai cầu phân áp R1, R2; chưa nối 3V3; LM358 cắm ngược hoặc chưa có nguồnĐo điểm 1,65 V bằng đồng hồ; kiểm tra chân 8 và chân 4 của LM358
nhieu nen lớn (hàng chục mV)Dây mạch thu dài, thiếu tụ C1, mạch thu đặt gần nguồn tăng ápRút ngắn dây, kiểm tra C1, đặt mạch thu xa nguồn và mạch đệm
Biên độ gần 0 ở mọi gócMạch đệm chưa có 12 V, jumper ENA hoặc ENB bị tháo, chưa nối GND chung, đầu thu nối saiKiểm tra nguồn 12 V, jumper, dây GND và hai chân đầu thu
Biên độ gần như không đổi khi láiXung 12 V lọt thẳng vào mạch thu qua dây dẫn, không qua không khíLấy tay che kín đầu thu: nếu biên độ không giảm thì là nhiễu điện; tách xa hai mạch, rút ngắn dây
Đầu thu ở chính diện nhưng đỉnh không ở 0°Một đầu phát ngược cực, sai thứ tự kênh, hoặc KHOANG_CACH_MM không đúng thực tếThử từng kênh riêng; đối chiếu thứ tự dây với phần 1; đo lại khoảng cách tâm đầu phát
Có hai đỉnh cao gần bằng nhauĐầu thu đang ở gần ±25°, nơi búp chính và búp lặp đối xứng nhauBình thường với mảng này; đặt đầu thu trong khoảng ±20° để có một đỉnh trội
Hai lượt quét cho kết quả khác nhau nhiềuCó người di chuyển, gió quạt, hoặc phản xạ mạnh từ vật ở gầnGiữ yên khi đo, tắt quạt, dọn vật cứng gần đường truyền

13. Xem thêm


Tin tức liên quan

Phased array siêu âm 40 kHz với ESP32 (phần 1): nguyên lý lái búp sóng và tạo 8 kênh lệch pha
Phased array siêu âm 40 kHz với ESP32 (phần 1): nguyên lý lái búp sóng và tạo 8 kênh lệch pha

Nguyên lý phased array và cách dùng ESP32 tạo 8 kênh xung 40 kHz lệch pha để lái búp sóng siêu âm: công thức độ trễ, giới hạn do khoảng cách đầu phát, cấu hình LEDC với hpoint, sơ đồ nối và code.

Phát hiện chuyển động bằng sóng Wi-Fi (CSI) trên ESP32: không cần cảm biến
Phát hiện chuyển động bằng sóng Wi-Fi (CSI) trên ESP32: không cần cảm biến

Giải thích Wi-Fi CSI và hướng dẫn dùng ESP32 phát hiện người di chuyển trong phòng chỉ bằng sóng Wi-Fi từ router: lấy dữ liệu CSI, tính điểm chuyển động, đặt ngưỡng và xem trên Serial Plotter.

Phát hiện chuyển động bằng cảm biến PIR HC-SR501 với ESP32: tự bật đèn qua relay
Phát hiện chuyển động bằng cảm biến PIR HC-SR501 với ESP32: tự bật đèn qua relay

Hướng dẫn dùng cảm biến chuyển động PIR HC-SR501 với ESP32: nguyên lý, cách chỉnh module, đọc tín hiệu bằng ngắt và ghép relay làm đèn tự bật khi có người, tự tắt sau 60 giây.

Làm gateway LoRa sang MQTT bằng ESP32: node cảm biến chạy pin gửi dữ liệu về broker
Làm gateway LoRa sang MQTT bằng ESP32: node cảm biến chạy pin gửi dữ liệu về broker

Hướng dẫn làm hệ thống LoRa hoàn chỉnh với ESP32 và SX1278: node chạy pin đo điện áp, gửi gói rồi ngủ sâu; gateway nhận gói LoRa và publish dữ liệu JSON lên broker MQTT qua Wi-Fi.

Cấu hình LoRa trên ESP32: SF, băng thông, tỉ lệ mã, công suất và cách thử tầm xa
Cấu hình LoRa trên ESP32: SF, băng thông, tỉ lệ mã, công suất và cách thử tầm xa

Giải thích bốn tham số cấu hình LoRa (SF, băng thông, tỉ lệ mã, công suất), cách tính thời gian phát một gói và hướng dẫn làm bộ thử tầm xa bằng ESP32, SX1278 và màn hình OLED.

Hướng dẫn dùng LoRa SX1278 (Ra-02) với ESP32: nối dây SPI, gửi và nhận gói tin đầu tiên
Hướng dẫn dùng LoRa SX1278 (Ra-02) với ESP32: nối dây SPI, gửi và nhận gói tin đầu tiên

Hướng dẫn nối module LoRa SX1278 Ra-02 433 MHz với ESP32 qua SPI, cài thư viện LoRa trên Arduino IDE, viết chương trình gửi và nhận gói tin, đọc RSSI, SNR và xử lý lỗi thường gặp.

ESP-NOW nhiều node với ESP32: nhiều mạch gửi về một trạm thu, hiển thị trên OLED
ESP-NOW nhiều node với ESP32: nhiều mạch gửi về một trạm thu, hiển thị trên OLED

Hướng dẫn dựng mô hình ESP-NOW nhiều node: tối đa bốn ESP32 gửi số đo về một trạm thu, trạm thu hiện điện áp, RSSI và tình trạng từng node trên màn hình OLED 0.96 inch.

Điều khiển relay từ xa bằng ESP-NOW: remote ESP32 một nút nhấn có phản hồi trạng thái
Điều khiển relay từ xa bằng ESP-NOW: remote ESP32 một nút nhấn có phản hồi trạng thái

Hướng dẫn làm bộ điều khiển relay từ xa bằng hai mạch ESP32 và ESP-NOW hai chiều: remote gửi lệnh, mạch relay báo lại trạng thái, lọc theo địa chỉ MAC và bật mã hóa.


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