
ESP32 + OLED SSD1306 (I2C): Hiển thị dữ liệu cảm biến cơ bản
Hướng dẫn kết nối màn hình OLED 0.96" I2C SSD1306 với ESP32 DevKit và hiển thị dữ liệu cảm biến (nhiệt độ, độ ẩm) theo thời gian thực bằng thư viện Adafruit_SSD1306.
Màn hình OLED 0.96" 128x64 giao tiếp I2C (driver SSD1306) là lựa chọn phổ biến nhất để hiển thị dữ liệu cảm biến trên các dự án ESP32 nhờ giá rẻ, tiêu thụ điện thấp (~20mA), và chỉ cần 2 dây tín hiệu (SDA/SCL) ngoài nguồn.
Bài viết này hướng dẫn đấu nối ESP32 DevKit với OLED SSD1306 qua I2C và viết chương trình đọc dữ liệu cảm biến rồi hiển thị lên màn hình bằng thư viện Adafruit_SSD1306 + Adafruit_GFX.
Hướng dẫn chi tiết
Kết nối ESP32 DevKit với OLED 0.96" SSD1306 qua I2C, đọc dữ liệu cảm biến và hiển thị realtime bằng Adafruit_SSD1306. Code đã compile pass arduino-cli.
1. Giới thiệu
Màn hình OLED 0.96" 128x64 giao tiếp I2C (driver SSD1306) là lựa chọn phổ biến nhất để hiển thị dữ liệu cảm biến trên các dự án ESP32 nhờ giá rẻ, tiêu thụ điện thấp (~20mA), và chỉ cần 2 dây tín hiệu (SDA/SCL) ngoài nguồn. Bài viết này hướng dẫn đấu nối ESP32 DevKit với OLED SSD1306 qua I2C và viết chương trình đọc dữ liệu cảm biến rồi hiển thị lên màn hình bằng thư viện Adafruit_SSD1306 + Adafruit_GFX.
OLED không cần đèn nền (mỗi điểm ảnh tự phát sáng) nên độ tương phản rất cao, phù hợp hiển thị số liệu nhiệt độ, độ ẩm, trạng thái kết nối WiFi/MQTT trên các thiết bị IoT nhỏ gọn.
2. Linh kiện cần có
Linh kiện | Số lượng | Giá tham khảo |
|---|---|---|
ESP32 DevKit V4 (30/38 pin) | 1 | ~75.000 - 120.000đ |
OLED 0.96" 128x64 I2C (SSD1306) | 1 | ~35.000 - 60.000đ |
Dây jumper cái-cái (4 sợi) | 1 bộ | ~10.000đ |
3. Sơ đồ kết nối
Chỉ 4 dây: 2 dây nguồn + 2 dây tín hiệu I2C. OLED SSD1306 hoạt động tốt ở cả 3.3V và 5V nhưng nên cấp 3.3V trực tiếp từ ESP32 để bus I2C giữ mức điện áp logic đồng nhất 3.3V, an toàn tuyệt đối cho GPIO ESP32 (không chịu được 5V ở chân input).
OLED SSD1306 | ESP32 DevKit | Ghi chú |
|---|---|---|
VCC | 3V3 | Nguồn 3.3V |
GND | GND | Mass chung |
SCL | GPIO22 | I2C Clock (chuẩn ESP32) |
SDA | GPIO21 | I2C Data (chuẩn ESP32) |
An toàn điện áp: Module OLED SSD1306 trong bài dùng driver on-board 3.3V-5V nhưng ta cấp thẳng 3V3 để tránh mọi rủi ro mức logic — không cần level shifter.
4. Code mẫu đầy đủ
Chương trình khởi tạo I2C trên đúng 2 chân GPIO21/GPIO22, kiểm tra OLED có phản hồi ở địa chỉ 0x3C hay không (in log rõ ràng nếu không tìm thấy), sau đó mỗi 2 giây đọc dữ liệu cảm biến (mô phỏng, thay bằng cảm biến thật khi triển khai) và vẽ lại lên màn hình.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
#define I2C_SDA 21
#define I2C_SCL 22
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned long lastRead = 0;
const unsigned long READ_INTERVAL_MS = 2000;
bool sensorOk = false;
float readTemperatureC() {
// Khong co cam bien vat ly trong demo nay: gia lap gia tri hop le.
// Thay bang dht.readTemperature() / bme.readTemperature() khi co cam bien that.
float simulated = 26.5f + (float)((millis() / 2000) % 5);
return simulated;
}
float readHumidityPct() {
float simulated = 55.0f + (float)((millis() / 3000) % 10);
return simulated;
}
void setup() {
Serial.begin(115200);
delay(200);
Serial.println(F("[BOOT] ESP32 OLED SSD1306 demo starting..."));
Wire.begin(I2C_SDA, I2C_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("[ERROR] SSD1306 khong tim thay tren I2C bus (0x3C). Kiem tra day SDA/SCL."));
sensorOk = false;
} else {
sensorOk = true;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("IoTLabs Maker"));
display.println(F("OLED SSD1306 Demo"));
display.display();
Serial.println(F("[OK] OLED SSD1306 khoi tao thanh cong."));
}
}
void loop() {
unsigned long now = millis();
if (now - lastRead >= READ_INTERVAL_MS) {
lastRead = now;
float t = readTemperatureC();
float h = readHumidityPct();
Serial.printf("[DATA] temp=%.1fC hum=%.1f%%\n", t, h);
if (sensorOk) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Cam bien moi truong"));
display.drawLine(0, 10, 128, 10, SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 16);
display.printf("T:%.1fC", t);
display.setCursor(0, 40);
display.printf("H:%.0f%%", h);
display.display();
} else {
Serial.println(F("[WARN] Display khong san sang, chi in Serial."));
}
}
}
Kết quả compile: Sketch uses 339368 bytes (25%) of program storage space. Global variables use 23652 bytes (7%) of dynamic memory. FQBN: esp32:esp32:esp32.
5. Giải thích code chi tiết
Wire.begin(I2C_SDA, I2C_SCL)— ESP32 cho phép chỉ định lại chân I2C tuỳ ý (khác AVR cố định), ở đây chọn đúng cặp GPIO21/GPIO22 đã đấu dây.display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)trả vềfalsenếu không có phản hồi ACK từ địa chỉ 0x3C trên bus — dùng để phát hiện lỗi dây/địa chỉ ngay khi boot thay vì crash ngầm.readTemperatureC()/readHumidityPct()mô phỏng dữ liệu cảm biến bằng hàm biến thiên theomillis()— khi triển khai thật, thay bằng lời gọi thư viện cảm biến (DHT22, BME280...).Vòng lặp
loop()chỉ redraw màn hình mỗiREAD_INTERVAL_MS(2 giây) thay vì mỗi lần lặp — tránh nháy màn hình và giảm tải I2C bus.
6. Ứng dụng thực tế / hướng mở rộng
Có thể mở rộng dự án này bằng cách: (1) thay hàm đọc giả lập bằng cảm biến DHT22/BME280 thật qua thư viện DHT sensor library hoặc Adafruit_BMP280; (2) thêm icon WiFi/MQTT trạng thái kết nối bằng drawBitmap(); (3) dùng U8g2 thay Adafruit_SSD1306 nếu cần nhiều font chữ tiếng Việt có dấu hơn.
7. Lỗi thường gặp
Lỗi | Nguyên nhân | Cách sửa |
|---|---|---|
Màn hình không sáng, Serial in "[ERROR] SSD1306 khong tim thay" | Sai dây SDA/SCL hoặc module lỗi | Kiểm tra lại 4 dây, dùng I2C scanner để xác nhận địa chỉ 0x3C |
Compile lỗi "Adafruit_SSD1306.h: No such file" | Chưa cài thư viện |
|
Màn hình hiển thị nhiễu/ô vuông trắng | Sai địa chỉ I2C (0x3D thay vì 0x3C) hoặc thiếu | Đổi |
8. Tổng kết
Chỉ với 4 dây và thư viện Adafruit_SSD1306, ESP32 đã có thể hiển thị dữ liệu cảm biến realtime trên OLED 0.96" I2C, nền tảng cho hầu hết các dự án IoT hiển thị nhỏ gọn: trạm đo môi trường, đồng hồ thông minh, dashboard mini.