IoTLabs

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

Dự Án Tổng Kết: Trạm Đo Nhiệt Độ và Ánh Sáng với Arduino Uno

Tổng Quan Dự Án

Sau 9 bài học, bạn đã nắm được: digital I/O, PWM, analog input, Serial, servo, và LCD. Bài tổng kết này kết hợp tất cả để xây dựng một Trạm Đo Môi Trường thực sự hữu ích.

Chức năng của trạm:

  • Đo nhiệt độđộ ẩm với cảm biến DHT11
  • Đo cường độ ánh sáng với LDR
  • Hiển thị tất cả dữ liệu trên LCD 16×2 I2C
  • LED đỏ cảnh báo khi nhiệt độ vượt ngưỡng
  • LED xanh nháy đều cho biết trạm đang hoạt động
  • Gửi dữ liệu qua Serial để ghi log trên máy tính
  • Nút nhấn để chuyển màn hình giữa các thông số

Danh Sách Linh Kiện

Linh kiệnSố lượngGhi chú
Arduino Uno1Hoặc board tương thích
Cảm biến DHT111Hoặc DHT22 (chính xác hơn)
LCD 16×2 + I2C adapter1Module all-in-one dễ dùng hơn
LDR (quang trở)1Đi kèm điện trở 10kΩ
LED đỏ1
LED xanh lá1
Nút nhấn1
Điện trở 220Ω2Cho 2 LED
Điện trở 10kΩ2Cho LDR + pull-up nút
Breadboard1830 lỗ
Dây cắm~20

Tổng chi phí: khoảng 150.000–200.000 VNĐ

📷 [Hình minh hoạ: Sơ đồ hệ thống trạm đo: Arduino Uno + DHT11 + LDR + LCD I2C + LED cảnh báo — khối chức năng teal, mũi tên kết nối, nền trắng, infographic kỹ thuật]

Sơ Đồ Kết Nối

Arduino Uno        Thiết bị
─────────────      ──────────────────────────────
D2            ──── Nút nhấn (1 đầu → GND)
D3            ──── LED xanh (anode) → 220Ω → GND
D4            ──── LED đỏ (anode) → 220Ω → GND
D7            ──── DHT11 (DATA) + 10kΩ pull-up → 5V
A0            ──── LDR + 10kΩ (voltage divider về GND)
A4 (SDA)      ──── SDA của module LCD I2C
A5 (SCL)      ──── SCL của module LCD I2C
5V            ──── VCC (DHT11, LCD I2C)
GND           ──── GND (tất cả)

Ghi nhớ: DHT11 cần thêm điện trở kéo lên 10kΩ từ chân DATA lên VCC.

Cài Thư Viện DHT

Trong Library Manager: tìm “DHT sensor library” của Adafruit → Install.

Cũng cần cài “Adafruit Unified Sensor” (dependency).

Code Hoàn Chỉnh

#include <DHT.h>
#include <LiquidCrystal_I2C.h>

// ─── Pin definitions ───────────────────────────────
#define DHT_PIN      7
#define DHT_TYPE     DHT11
#define BTN_PIN      2
#define LED_GREEN    3
#define LED_RED      4
#define LDR_PIN      A0

// ─── Ngưỡng cảnh báo ───────────────────────────────
#define TEMP_HIGH    30.0  // °C — cảnh báo đỏ
#define LIGHT_LOW    200   // LDR < 200 → tối

// ─── Khởi tạo đối tượng ────────────────────────────
DHT dht(DHT_PIN, DHT_TYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);

// ─── Biến trạng thái ───────────────────────────────
int displayMode = 0;            // 0: nhiệt độ/độ ẩm, 1: ánh sáng
bool lastBtnState = HIGH;
unsigned long lastBlink = 0;
unsigned long lastRead = 0;
unsigned long lastLog = 0;
bool greenState = false;

float temperature = 0;
float humidity = 0;
int lightLevel = 0;

// ─── Custom LCD characters ─────────────────────────
byte degSymbol[] = {
  0b00110, 0b01001, 0b01001, 0b00110,
  0b00000, 0b00000, 0b00000, 0b00000
};

byte lightIcon[] = {
  0b00100, 0b10101, 0b01110, 0b11111,
  0b01110, 0b10101, 0b00100, 0b00000
};

void setup() {
  // Serial
  Serial.begin(9600);
  Serial.println("IoTLabs Weather Station v1.0");
  Serial.println("timestamp,temp,humidity,light");

  // Pins
  pinMode(BTN_PIN, INPUT_PULLUP);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_RED, OUTPUT);

  // DHT
  dht.begin();

  // LCD
  lcd.init();
  lcd.backlight();
  lcd.createChar(0, degSymbol);
  lcd.createChar(1, lightIcon);

  // Màn hình chào
  lcd.setCursor(0, 0);
  lcd.print("  IoTLabs.vn  ");
  lcd.setCursor(0, 1);
  lcd.print(" Weather v1.0 ");
  delay(2000);
  lcd.clear();
}

void readSensors() {
  temperature = dht.readTemperature();
  humidity = dht.readHumidity();
  lightLevel = analogRead(LDR_PIN);

  // Kiểm tra lỗi DHT
  if (isnan(temperature)) temperature = -1;
  if (isnan(humidity)) humidity = -1;
}

void updateDisplay() {
  if (displayMode == 0) {
    // Màn hình 1: Nhiệt độ + độ ẩm
    lcd.setCursor(0, 0);
    lcd.print("Nhiet do:       ");
    lcd.setCursor(10, 0);
    if (temperature < 0) {
      lcd.print("ERR ");
    } else {
      lcd.print(temperature, 1);
      lcd.write(byte(0)); // ° symbol
      lcd.print("C");
    }

    lcd.setCursor(0, 1);
    lcd.print("Do am:          ");
    lcd.setCursor(10, 1);
    if (humidity < 0) {
      lcd.print("ERR ");
    } else {
      lcd.print(humidity, 1);
      lcd.print("%");
    }
  } else {
    // Màn hình 2: Ánh sáng
    lcd.setCursor(0, 0);
    lcd.write(byte(1)); // Light icon
    lcd.print(" Anh sang:      ");
    lcd.setCursor(11, 0);
    lcd.print(lightLevel);

    lcd.setCursor(0, 1);
    lcd.print("Muc: ");
    if (lightLevel < 200)       lcd.print("Toi       ");
    else if (lightLevel < 600)  lcd.print("Vua       ");
    else                        lcd.print("Sang      ");
  }
}

void updateLEDs() {
  // LED đỏ: cảnh báo nhiệt độ cao
  digitalWrite(LED_RED, (temperature >= TEMP_HIGH) ? HIGH : LOW);

  // LED xanh: nhấp nháy mỗi 1 giây
  unsigned long now = millis();
  if (now - lastBlink >= 1000) {
    lastBlink = now;
    greenState = !greenState;
    digitalWrite(LED_GREEN, greenState);
  }
}

void logSerial() {
  Serial.print(millis() / 1000);
  Serial.print(",");
  Serial.print(temperature, 1);
  Serial.print(",");
  Serial.print(humidity, 1);
  Serial.print(",");
  Serial.println(lightLevel);
}

void handleButton() {
  bool btnState = digitalRead(BTN_PIN);

  if (lastBtnState == HIGH && btnState == LOW) {
    // Chuyển màn hình
    displayMode = 1 - displayMode;
    lcd.clear();
    delay(50); // Debounce
  }

  lastBtnState = btnState;
}

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

  // Đọc cảm biến mỗi 2 giây (DHT11 chỉ đọc được 1 lần/giây)
  if (now - lastRead >= 2000) {
    lastRead = now;
    readSensors();
    updateDisplay();
  }

  // Log serial mỗi 10 giây
  if (now - lastLog >= 10000) {
    lastLog = now;
    logSerial();
  }

  updateLEDs();
  handleButton();
}

Chạy Thử và Kiểm Tra

Bước 1: Upload code, mở Serial Monitor ở 9600 baud.

Bước 2: Màn hình chào “IoTLabs.vn Weather v1.0” hiện 2 giây.

Bước 3: Màn hình chính hiển thị nhiệt độ và độ ẩm.

Bước 4: Nhấn nút → chuyển sang màn hình ánh sáng.

Bước 5: Che tay vào cảm biến DHT11 (hơi ấm) → nhiệt độ tăng → nếu vượt 30°C, LED đỏ bật.

Bước 6: Mở Serial Monitor → copy data vào Excel → vẽ đồ thị theo thời gian.

Hướng Phát Triển Tiếp Theo

Nâng cấpHướng thực hiện
Lưu data vào SD cardModule SD card + thư viện SD.h
Đồng hồ thựcModule DS3231 RTC qua I2C
Gửi data lên WiFiThay Arduino bằng ESP32/NodeMCU
Cảnh báo còiThêm buzzer vào D8 + tone()
Màn hình OLEDSSD1306 128×64 qua I2C — rõ và tiết kiệm điện hơn LCD
App điện thoạiESP32 + BLE (Bluetooth Low Energy)

Tổng Kết Series

Bạn đã hoàn thành 10 bài học Arduino Uno từ cơ bản đến nâng cao:

BàiKiến thức
1Giới thiệu phần cứng Arduino Uno
2Cài đặt IDE và upload sketch đầu tiên
3Digital output — LED Blink
4Digital input — nút nhấn và debounce
5PWM — điều chỉnh độ sáng liên tục
6Analog input — ADC và cảm biến LDR
7Serial UART — debug và giao tiếp
8Servo motor — điều khiển góc quay
9LCD 16×2 I2C — hiển thị thông tin
10Dự án tổng kết — Trạm Đo Môi Trường

Bước tiếp theo gợi ý: Chuyển sang ESP32 để thêm WiFi, MQTT, và kết nối cloud — bộ kỹ năng Arduino sẽ là nền tảng vững chắc cho hành trình đó.

Hẹn gặp lại trong Series ESP32 tại IoTLabs!


👉 Bài tiếp theo: Xem toàn bộ Series: Lập Trình Arduino Uno Từ Cơ Bản Đến Nâng Cao