IoTLabs

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

Đọc Tín Hiệu Analog — ADC, Biến Trở và Cảm Biến Ánh Sáng LDR

Tín Hiệu Analog vs Digital

Thế giới thực là analog: nhiệt độ, ánh sáng, âm thanh thay đổi liên tục, không chỉ có 0 hoặc 1. Arduino cần ADC (Analog-to-Digital Converter) để đọc các tín hiệu này.

DigitalAnalog
Giá trị0 hoặc 1 (LOW/HIGH)Liên tục (0V → 5V)
Ví dụNút nhấn, switchNhiệt độ, ánh sáng, âm lượng
Hàm ArduinodigitalRead()analogRead()

ADC 10-bit Của Arduino Uno

Arduino Uno có ADC 10-bit: chuyển điện áp 0V–5V thành số nguyên 0–1023 (2¹⁰ = 1024 giá trị).

0V    → analogRead() = 0
2.5V  → analogRead() = 511
5V    → analogRead() = 1023

Độ phân giải: 5V / 1024 ≈ 4.9 mV mỗi đơn vị.

6 chân analog: A0, A1, A2, A3, A4, A5

Lưu ý: A4 (SDA) và A5 (SCL) thường dùng cho I2C — tránh dùng analog nếu có thiết bị I2C.

Hàm analogRead()

int value = analogRead(A0); // Trả về 0–1023

Mỗi lần đọc mất khoảng 100 µs (0.1 ms). Không cần pinMode() trước — chân analog mặc định là INPUT.

📷 [Hình minh hoạ: Sơ đồ Arduino Uno kết nối LDR và biến trở — voltage divider, chân A0, dây VCC đỏ, GND đen, signal xanh, nền trắng]

Thực Hành 1: Đọc Biến Trở

Linh kiện: Biến trở (potentiometer) 10kΩ.

Kết nối:

5V ──── chân trái biến trở
        chân giữa (wiper) ──── A0
GND ─── chân phải biến trở

Code:

void setup() {
  Serial.begin(9600);
}

void loop() {
  int raw = analogRead(A0);             // 0–1023
  float voltage = raw * (5.0 / 1023.0); // Chuyển về Volt

  Serial.print("Raw: ");    Serial.print(raw);
  Serial.print(" | V: ");   Serial.print(voltage, 2);
  Serial.println("V");
  delay(200);
}

Mở Serial Monitor, xoay biến trở — giá trị thay đổi từ 0 đến 1023.

Hàm map() — Chuyển Đổi Phạm Vi

map() chuyển một giá trị từ phạm vi này sang phạm vi khác:

long map(value, fromLow, fromHigh, toLow, toHigh)

Ví dụ:

int raw = analogRead(A0);              // 0–1023
int brightness = map(raw, 0, 1023, 0, 255); // Chuyển sang 0–255 cho PWM
int percentage = map(raw, 0, 1023, 0, 100); // Chuyển sang 0–100%

Kết hợp biến trở + LED PWM:

const int POT_PIN = A0;
const int LED_PIN = 9; // Chân PWM

void setup() {}

void loop() {
  int raw = analogRead(POT_PIN);
  int brightness = map(raw, 0, 1023, 0, 255);
  analogWrite(LED_PIN, brightness);
  delay(10);
}

Thực Hành 2: Cảm Biến Ánh Sáng LDR

LDR (Light Dependent Resistor) — điện trở quang — thay đổi điện trở theo cường độ ánh sáng:

  • Trời tối: điện trở cao (~1 MΩ)
  • Ánh sáng mạnh: điện trở thấp (~1 kΩ)

Mạch chia điện áp với LDR:

5V ──[LDR]──┬──[10kΩ]── GND
            │
           A0

Khi ánh sáng tăng → điện trở LDR giảm → điện áp tại A0 tăng → analogRead() tăng.

Code đọc LDR:

const int LDR_PIN = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int ldrValue = analogRead(LDR_PIN);

  Serial.print("Ánh sáng: ");
  Serial.print(ldrValue);

  if (ldrValue < 300) {
    Serial.println(" → Tối");
  } else if (ldrValue < 700) {
    Serial.println(" → Vừa");
  } else {
    Serial.println(" → Sáng");
  }

  delay(500);
}

Ứng Dụng: Đèn Tự Động Theo Ánh Sáng

Kết hợp LDR + LED: đèn tự bật khi tối, tắt khi sáng.

const int LDR_PIN = A0;
const int LED_PIN = 13;
const int THRESHOLD = 400; // Ngưỡng sáng/tối — chỉnh theo môi trường

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int ldrValue = analogRead(LDR_PIN);

  if (ldrValue < THRESHOLD) {
    // Tối → bật đèn
    digitalWrite(LED_PIN, HIGH);
    Serial.println("Đèn BẬT (tối)");
  } else {
    // Sáng → tắt đèn
    digitalWrite(LED_PIN, LOW);
    Serial.println("Đèn TẮT (sáng)");
  }

  delay(200);
}

Nâng cao: Điều chỉnh độ sáng theo ánh sáng môi trường (giảm chói)

const int LDR_PIN = A0;
const int LED_PIN = 9; // PWM

void setup() {}

void loop() {
  int ldrValue = analogRead(LDR_PIN);
  // Môi trường sáng → đèn tối hơn (tiết kiệm điện)
  // Môi trường tối → đèn sáng hơn
  int brightness = map(ldrValue, 0, 1023, 255, 0);
  analogWrite(LED_PIN, brightness);
  delay(50);
}

Ổn Định Kết Quả Đọc — Lấy Trung Bình

Tín hiệu analog thường có nhiễu nhỏ. Lấy trung bình nhiều lần đọc để ổn định:

int stableRead(int pin, int samples = 10) {
  long total = 0;
  for (int i = 0; i < samples; i++) {
    total += analogRead(pin);
    delay(2);
  }
  return total / samples;
}

void loop() {
  int stable = stableRead(A0, 10); // Trung bình 10 lần đọc
  Serial.println(stable);
  delay(100);
}

Tổng Kết

HàmChức năng
analogRead(A0)Đọc 0–1023 từ chân analog
map(v, 0,1023, 0,255)Chuyển phạm vi giá trị
analogWrite(pin, 0–255)Xuất PWM (kết hợp với analogRead)

Biến trở → nguồn tín hiệu analog điều khiển được LDR → cảm biến ánh sáng cơ bản, rẻ, dễ dùng

Bài tiếp theo: Serial UART — giao tiếp 2 chiều với máy tính, nhận lệnh từ terminal và gửi dữ liệu cảm biến.