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 độ và độ ẩ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ện | Số lượng | Ghi chú |
|---|---|---|
| Arduino Uno | 1 | Hoặc board tương thích |
| Cảm biến DHT11 | 1 | Hoặc DHT22 (chính xác hơn) |
| LCD 16×2 + I2C adapter | 1 | Module 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ấn | 1 | |
| Điện trở 220Ω | 2 | Cho 2 LED |
| Điện trở 10kΩ | 2 | Cho LDR + pull-up nút |
| Breadboard | 1 | 830 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ấp | Hướng thực hiện |
|---|---|
| Lưu data vào SD card | Module SD card + thư viện SD.h |
| Đồng hồ thực | Module DS3231 RTC qua I2C |
| Gửi data lên WiFi | Thay Arduino bằng ESP32/NodeMCU |
| Cảnh báo còi | Thêm buzzer vào D8 + tone() |
| Màn hình OLED | SSD1306 128×64 qua I2C — rõ và tiết kiệm điện hơn LCD |
| App điện thoại | ESP32 + 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ài | Kiến thức |
|---|---|
| 1 | Giới thiệu phần cứng Arduino Uno |
| 2 | Cài đặt IDE và upload sketch đầu tiên |
| 3 | Digital output — LED Blink |
| 4 | Digital input — nút nhấn và debounce |
| 5 | PWM — điều chỉnh độ sáng liên tục |
| 6 | Analog input — ADC và cảm biến LDR |
| 7 | Serial UART — debug và giao tiếp |
| 8 | Servo motor — điều khiển góc quay |
| 9 | LCD 16×2 I2C — hiển thị thông tin |
| 10 | Dự á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


