IoTLabs

Nghiên cứu, Sáng tạo và Thử nghiệm

Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động Rain Sensor FC-37: Phát Hiện Mưa, LM393 Comparator & Ứng Dụng Thực Tế

Rain Sensor FC-37 (còn gọi là YL-83) là sensor phát hiện mưa bằng cách đo điện trở giữa các răng điện cực đồng song song trên tấm PCB. Khi có nước mưa → tạo cầu dẫn điện → điện trở giảm → MCU phát hiện. Bài này phân tích nguyên lý hoạt động, so sánh ngõ ra analog/digital, và hướng dẫn sử dụng đúng cách để tránh ăn mòn điện cực.

Nguyên Lý Hoạt Động

1. Tấm Cảm Biến — Cầu Điện Trở Nước Mưa

Tấm cảm biến (sensing pad) của FC-37 là một miếng PCB FR4 với các răng điện cực đồng song song, xen kẽ nhau:

Tấm cảm biến mưa (nhìn từ trên):

+───────┬───────┬───────┬───────+
│ (+)   │  (-)  │  (+)  │  (-)  │  ← Răng điện cực xen kẽ
│ ↕ 2mm │ ↕ 2mm │ ↕ 2mm │ ↕ 2mm │     khoảng cách nhỏ giữa các răng
+───────┴───────┴───────┴───────+
         Bề mặt PCB trống (FR4, cách điện)

Khi không có mưa: khoảng cách giữa răng là không khí → cách điện → R = ∞
Khi có mưa:       giọt nước bắc cầu qua khoảng cách → R giảm xuống kΩ

Độ dẫn điện của nước mưa:

  • Nước mưa không phải nước cất — chứa CO₂ hòa tan (tạo axit cacbonic H₂CO₃), các khoáng nhỏ từ không khí
  • Điện trở nước mưa thực tế: khoảng 10kΩ – 100kΩ tùy mật độ mưa và ô nhiễm không khí
  • Mưa lớn (nhiều giọt) → nhiều cầu song song → điện trở tổng thấp hơn → dễ phát hiện hơn

2. Mạch Module — LM393 Comparator

Module FC-37 gồm 2 phần tách rời:

  • Tấm cảm biến (sensing pad, thường 54mm × 40mm): cắm ra ngoài trời
  • Board xử lý (control board): ở trong nhà/hộp, kết nối với MCU

Mạch trong board xử lý:

VCC
 │
 R (10kΩ, cố định)
 │
 ├──── Chân AOUT (điện áp tỷ lệ với độ ẩm tấm)
 │
 R_sensor (thay đổi theo lượng nước trên tấm)
 │
GND

Đồng thời:
AOUT ──→ LM393 (+IN)
             LM393 (-IN) ──→ Triết áp (điều chỉnh ngưỡng)
             LM393 OUT   ──→ DOUT

AOUT (Analog Output):

  • Khô: R_sensor = ∞ → AOUT ≈ VCC → ADC đọc cao (Arduino ~1023, ESP32 ~4095)
  • Ướt: R_sensor giảm → AOUT giảm → ADC đọc thấp

DOUT (Digital Output) qua LM393:

  • Khô: AOUT > ngưỡng (triết áp) → DOUT = HIGH (không mưa)
  • Ướt: AOUT < ngưỡng → DOUT = LOW (có mưa, đèn LED trên module sáng)

LED indicator trên module: Sáng khi DOUT = LOW (phát hiện mưa). Hữu ích để debug nhanh mà không cần Serial Monitor.

3. Ăn Mòn Điện Cực — Cùng Vấn Đề Với Soil Moisture

Rain Sensor dùng cùng nguyên lý điện trở với Soil Moisture → cùng vấn đề điện phân. Dòng DC chạy qua nước → điện phân → ăn mòn điện cực đồng.

Biểu hiện:

  • Điện cực đổi màu (xanh lục/đen): muối đồng tích tụ
  • Tấm PCB có váng/mảng trắng: khoáng tủa
  • Đọc sai ngay cả khi mưa lớn: bề mặt bị phủ lớp cách điện

Giải pháp thực tế:

  1. Cấp nguồn xung: GPIO cấp VCC cho module, chỉ bật khi cần kiểm tra
  2. Vệ sinh định kỳ: Dùng khăn mềm và isopropyl alcohol lau tấm cảm biến
  3. Không dùng module làm moisture meter liên tục — rain sensor chỉ phù hợp phát hiện mưa ngắt quãng, không đo liên tục như soil moisture

Thông Số Kỹ Thuật

Thông sốGiá trị
Điện áp hoạt động3.3V – 5V
Dòng tiêu thụ~15–30mA
Kích thước tấm cảm biến54mm × 40mm (thông dụng)
Khoảng cách điện cực1–2mm
Ngõ ra analog0V – VCC (đảo: cao = khô, thấp = ướt)
Ngõ ra digital0V / VCC (điều chỉnh bằng triết áp)
ComparatorLM393
Nhiệt độ hoạt động0°C – 50°C (tấm cảm biến)

Lưu ý nhiệt độ: Dưới 0°C nước đóng băng → điện trở tăng rất cao → sensor báo “không mưa” dù tuyết hoặc băng. Rain sensor này không phân biệt được tuyết.

Sơ Đồ Chân (Pinout)

Board Xử Lý FC-37 (Control Module — 4 chân)

   ┌──────────────────────────┐
   │  [LED]  [Triết áp]       │
   │  ┌──────────────────┐    │
   │  │  LM393 Comparator│    │
   │  └──────────────────┘    │
   │                          │
   │  [Kết nối tấm cảm biến]  │
   └──────────────────────────┘
   VCC  GND  DOUT  AOUT
ChânTênChức năng
VCCVCCNguồn 3.3V hoặc 5V
GNDGNDĐất
DOUTD0Digital: LOW = có mưa, HIGH = khô
AOUTA0Analog: điện áp thấp = nhiều nước, cao = khô

Tấm Cảm Biến (Sensing Pad — 2 chân)

Chỉ có 2 chân (+) và (-). Nối với board xử lý qua 2 dây đi kèm. Không phân cực — 2 chân đối xứng.

Phân Biệt FC-37 Và Các Biến Thể

ModelKích thước tấmGhi chú
FC-3754mm × 40mmPhổ biến nhất, tấm nhỏ
YL-8354mm × 40mmVề cơ bản giống FC-37
YL-38Tấm lớn hơnModule khác, nguyên lý như nhau
Không tênNhiều sizeCùng nguyên lý — chỉ khác kích thước tấm

Tất cả đều dùng cùng nguyên lý và cùng cách kết nối. Sự khác biệt chủ yếu là kích thước tấm cảm biến (lớn hơn = phát hiện mưa nhỏ hơn).

Kết Nối Phần Cứng

Kết Nối với ESP32 DevKit V1

ESP32 DevKit V1            Rain Sensor Module
─────────────────────      ─────────────────────
GPIO26 (Output) ────────→  VCC   ← Cấp nguồn xung qua GPIO
GND  ───────────────────→  GND
GPIO34 (ADC1_CH6) ──────→  AOUT  ← Đọc analog (chỉ input, GPIO34 không có OUTPUT)
GPIO25 (Input) ─────────→  DOUT  ← Đọc digital

Tại sao GPIO34 cho AOUT: GPIO34 là input-only, chỉ ADC1 → không bị ảnh hưởng WiFi. Phù hợp để đọc analog. GPIO34, 35, 36, 39 là input-only trên ESP32.

GPIO26 cấp nguồn: Cùng kỹ thuật như soil moisture — bật để đo, tắt để tiết kiệm và giảm ăn mòn.

Kết Nối với Arduino Uno

Arduino Uno               Rain Sensor Module
─────────────────────     ─────────────────────
Pin 8 (Output) ─────────→ VCC   ← Cấp nguồn xung
GND  ───────────────────→ GND
A0 (Analog Input) ──────→ AOUT
Pin 7 (Input) ──────────→ DOUT

Code Arduino IDE

Code Phát Hiện Mưa — Arduino Uno

/*
 * Rain Sensor FC-37/YL-83 — Phát hiện mưa analog + digital
 * Board: Arduino Uno
 * Kết nối: VCC→Pin8, GND→GND, AOUT→A0, DOUT→Pin7
 */

const int POWER_PIN  = 8;  // Cấp nguồn sensor qua GPIO
const int ANALOG_PIN = A0; // Đọc analog từ AOUT
const int DIGITAL_PIN = 7; // Đọc digital từ DOUT

// Ngưỡng phân loại độ mưa từ giá trị ADC analog (Arduino Uno, 10-bit)
// Cần hiệu chỉnh cho từng sensor — đây là ước tính ban đầu
const int THRESHOLD_DRY    = 900; // ADC > 900: không có nước (khô)
const int THRESHOLD_LIGHT  = 600; // ADC 600-900: mưa nhẹ
const int THRESHOLD_MEDIUM = 300; // ADC 300-600: mưa vừa
                                   // ADC < 300: mưa nặng

void setup() {
  Serial.begin(9600);
  pinMode(POWER_PIN, OUTPUT);
  pinMode(DIGITAL_PIN, INPUT);
  digitalWrite(POWER_PIN, LOW); // Tắt nguồn ban đầu

  Serial.println("=== Rain Sensor FC-37 - Arduino Uno ===");
}

// Phân loại mức độ mưa từ giá trị ADC
String getRainLevel(int analogValue) {
  if (analogValue > THRESHOLD_DRY)    return "Khô — Không mưa";
  if (analogValue > THRESHOLD_LIGHT)  return "Mưa nhỏ / Sương";
  if (analogValue > THRESHOLD_MEDIUM) return "Mưa vừa";
  return "Mưa lớn";
}

void loop() {
  // Bật nguồn sensor trước khi đọc
  digitalWrite(POWER_PIN, HIGH);
  delay(100); // Chờ ổn định

  // Đọc analog (5 lần lấy trung bình)
  int total = 0;
  for (int i = 0; i < 5; i++) {
    total += analogRead(ANALOG_PIN);
    delay(10);
  }
  int analogValue = total / 5;

  // Đọc digital (từ LM393 comparator)
  int digitalValue = digitalRead(DIGITAL_PIN);

  // Tắt nguồn sau khi đọc xong
  digitalWrite(POWER_PIN, LOW);

  // Hiển thị kết quả
  Serial.print("Analog raw: ");
  Serial.print(analogValue);
  Serial.print(" | Mức độ: ");
  Serial.print(getRainLevel(analogValue));
  Serial.print(" | Digital: ");
  // DOUT LOW = phát hiện mưa (logic đảo!)
  Serial.println(digitalValue == LOW ? "CÓ MƯA" : "KHÔNG MƯA");

  delay(3000); // Kiểm tra mỗi 3 giây
}

Code Phát Hiện Mưa + Cảnh Báo — ESP32

/*
 * Rain Sensor FC-37/YL-83 — Phát hiện mưa và cảnh báo qua Serial
 * Board: ESP32 DevKit V1
 * Kết nối:
 *   GPIO26 → VCC (cấp nguồn xung)
 *   GPIO34 → AOUT (analog, input-only pin)
 *   GPIO25 → DOUT (digital)
 *
 * ESP32 ADC 12-bit: 0-4095 (khác Arduino Uno 0-1023)
 * Ngưỡng cần hiệu chỉnh thực tế cho sensor cụ thể
 */

const int POWER_PIN   = 26; // Cấp nguồn qua GPIO
const int ANALOG_PIN  = 34; // ADC1_CH6 — input-only, ổn với WiFi
const int DIGITAL_PIN = 25; // DOUT từ LM393

// Ngưỡng ADC 12-bit (0-4095) — ước tính ban đầu, cần calibrate thực tế
const int THRESHOLD_DRY    = 3500; // ADC > 3500: khô
const int THRESHOLD_LIGHT  = 2500; // ADC 2500-3500: ẩm / mưa nhỏ
const int THRESHOLD_MEDIUM = 1500; // ADC 1500-2500: mưa vừa
                                    // ADC < 1500: mưa lớn

// Trạng thái mưa để phát hiện thay đổi (chỉ in khi thay đổi)
bool lastRainState = false;
unsigned long lastCheckTime = 0;
const unsigned long CHECK_INTERVAL = 3000; // Kiểm tra mỗi 3 giây

void setup() {
  Serial.begin(115200);
  pinMode(POWER_PIN, OUTPUT);
  pinMode(DIGITAL_PIN, INPUT);
  digitalWrite(POWER_PIN, LOW);

  // Cấu hình ADC ESP32
  analogSetAttenuation(ADC_11db); // Dải đọc 0-3.3V
  analogReadResolution(12);       // 12-bit: 0-4095

  Serial.println("=== Rain Sensor FC-37 - ESP32 ===");
}

String getRainLevel(int raw) {
  if (raw > THRESHOLD_DRY)    return "Khô";
  if (raw > THRESHOLD_LIGHT)  return "Mưa nhỏ/Sương";
  if (raw > THRESHOLD_MEDIUM) return "Mưa vừa";
  return "Mưa lớn";
}

int readAnalogAvg() {
  int total = 0;
  for (int i = 0; i < 10; i++) {
    total += analogRead(ANALOG_PIN);
    delay(5);
  }
  return total / 10;
}

void loop() {
  unsigned long now = millis();

  if (now - lastCheckTime >= CHECK_INTERVAL) {
    lastCheckTime = now;

    // Bật sensor
    digitalWrite(POWER_PIN, HIGH);
    delay(200); // Ổn định ADC (ESP32 cần lâu hơn Arduino)

    int analogValue  = readAnalogAvg();
    int digitalValue = digitalRead(DIGITAL_PIN);

    // Tắt sensor ngay
    digitalWrite(POWER_PIN, LOW);

    bool isRaining = (digitalValue == LOW); // DOUT LOW = có mưa

    // In kết quả chi tiết mỗi lần đo
    Serial.printf("ADC: %4d | Mức: %-15s | Digital: %s\n",
      analogValue,
      getRainLevel(analogValue).c_str(),
      isRaining ? "CÓ MƯA ☔" : "Không mưa"
    );

    // Phát hiện thay đổi trạng thái — in thông báo đặc biệt
    if (isRaining != lastRainState) {
      if (isRaining) {
        Serial.println(">>> BẮT ĐẦU MƯA! <<<");
        // Thêm: gửi MQTT, bật còi cảnh báo, đóng cửa mái nhà...
      } else {
        Serial.println(">>> MƯA ĐÃ TẠNHh <<<");
        // Thêm: gửi MQTT, tắt còi...
      }
      lastRainState = isRaining;
    }
  }

  // Loop không block — có thể thêm logic khác ở đây
}

Kết Quả Mong Đợi

=== Rain Sensor FC-37 - ESP32 ===
ADC: 3890 | Mức: Khô             | Digital: Không mưa
ADC: 3870 | Mức: Khô             | Digital: Không mưa
ADC: 2340 | Mức: Mưa nhỏ/Sương  | Digital: CÓ MƯA ☔
>>> BẮT ĐẦU MƯA! <<<
ADC: 1150 | Mức: Mưa lớn        | Digital: CÓ MƯA ☔
ADC: 3200 | Mức: Khô             | Digital: Không mưa
>>> MƯA ĐÃ TẠNH <<<

Ứng Dụng Thực Tế

Ứng dụngChi tiết
Tự động đóng cửa sổ / mái cheDOUT = LOW → đóng servo/motor
Tắt hệ thống tưới cây tự độngPhát hiện mưa → dừng máy bơm
Cảnh báo mưa qua điện thoạiESP32 WiFi → push notification
Trạm thời tiếtKết hợp BMP280 (áp suất) + DHT22 (độ ẩm) + rain sensor
Bãi đỗ xe thông minhCảnh báo thu dọn đồ khi mưa
Logger mưaGhi timestamp khi bắt đầu và kết thúc mưa

Lưu Ý Khi Sử Dụng

1. Logic DOUT đảo ngược — dễ nhầm

DOUT LOW = có mưa (phát hiện nước), DOUT HIGH = không mưa. Đây là logic âm, ngược với cảm giác thông thường. LED trên module sáng khi DOUT LOW (có mưa) — dùng LED để kiểm tra logic trước khi viết code.

2. Điều chỉnh ngưỡng bằng triết áp

Vặn triết áp trên module để chọn ngưỡng “đủ ướt” cho DOUT chuyển LOW. Vặn theo chiều kim đồng hồ = tăng ngưỡng (cần nhiều nước hơn mới báo), ngược chiều = giảm ngưỡng (ít nước cũng báo). Dùng AOUT + Serial Monitor để hiệu chỉnh trực quan.

3. Cấp nguồn xung để giảm ăn mòn

Tấm cảm biến bị ăn mòn theo thời gian nếu cấp điện liên tục. Với rain sensor, thường chỉ cần check mỗi vài giây một lần — cấp nguồn qua GPIO, bật khi check, tắt ngay sau.

4. Bảo vệ chống bụi và côn trùng

Tấm cảm biến đặt ngoài trời: bụi khô tích tụ → không dẫn điện → báo “khô” sai. Bọ/kiến đôi khi bò qua → báo “ướt” sai. Đặt tấm nghiêng ~45° để nước mưa chảy đi và bụi ít tích tụ hơn.

5. Phân biệt sương và mưa

Sensor có thể phát hiện cả sương mù dày (hơi nước tụ thành giọt trên tấm). Nếu ứng dụng cần phân biệt sương và mưa thật: dùng ngưỡng analog cao hơn cho “mưa”, hoặc thêm logic thời gian (mưa thật kéo dài liên tục > 30 giây).

6. GPIO34 là Input-Only trên ESP32

GPIO34, 35, 36, 39 của ESP32 chỉ là input — không thể dùng pinMode(34, OUTPUT). Phù hợp để đọc AOUT (analog). Không nhầm cắm nguồn vào GPIO34.

Bài tiếp theo: