Hướng dẫn dùng màn hình OLED SSD1306 với ESP8266
Hướng dẫn nối OLED SSD1306 với ESP8266, quét địa chỉ I2C, cài thư viện và hiển thị thời gian bằng mã Arduino mẫu.
Màn hình OLED 0,96 inch giao tiếp I2C thường dùng bộ điều khiển SSD1306 và độ phân giải 128 × 64 pixel. Bài viết sử dụng ESP8266 NodeMCU, thư viện Adafruit SSD1306 và địa chỉ I2C được xác nhận bằng chương trình quét trước khi chạy ví dụ.
1. Phần cứng và đấu nối
| OLED I2C | ESP8266 NodeMCU | Ghi chú |
|---|---|---|
| GND | GND | Nối mass chung. |
| VCC | 3V3 | Dùng 3,3 V nếu module cho phép; kiểm tra thông số module trước khi cấp nguồn. |
| SDA | D2 / GPIO4 | D2 là nhãn trên bo NodeMCU, GPIO4 là số dùng trong code. |
| SCL | D1 / GPIO5 | D1 là nhãn trên bo NodeMCU, GPIO5 là số dùng trong code. |
Không suy ra điện áp cấp chỉ từ hình dáng module. Một số board có mạch hỗ trợ 5 V, nhưng GPIO của ESP8266 làm việc ở mức 3,3 V. Nếu màn hình hoặc điện trở kéo lên I2C dùng 5 V, cần giải pháp chuyển mức phù hợp.
2. Quét địa chỉ I2C
Địa chỉ thường gặp là 0x3C hoặc 0x3D. Chạy đoạn quét dưới đây trước để dùng đúng địa chỉ:
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(4, 5); // SDA = GPIO4, SCL = GPIO5
for (uint8_t address = 1; address < 127; ++address) {
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) {
Serial.printf("Found I2C device: 0x%02X
", static_cast<unsigned>(address));
}
}
}
void loop() {}
Nếu không tìm thấy thiết bị, kiểm tra nguồn, GND, SDA/SCL và dây nối. Nếu địa chỉ đúng nhưng hình ảnh sai hoặc không hiển thị, xác nhận controller thực tế là SSD1306 hay SH1106 để chọn đúng thư viện.
3. Cài thư viện và chọn bo
- Trong Arduino IDE, cài Adafruit SSD1306 và Adafruit GFX Library bằng Library Manager.
- Chọn đúng bo đang dùng, ví dụ NodeMCU 1.0 (ESP-12E Module) hoặc profile Wemos D1 mini tương ứng.
- Chọn đúng cổng COM và kiểm tra Serial Monitor ở 115200 baud.
4. Chương trình hiển thị thời gian hoạt động
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
constexpr uint8_t SDA_PIN = 4;
constexpr uint8_t SCL_PIN = 5;
constexpr uint8_t OLED_ADDRESS = 0x3C; // Đổi theo địa chỉ vừa quét
constexpr int SCREEN_WIDTH = 128;
constexpr int SCREEN_HEIGHT = 64;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
uint32_t previousMs = 0;
uint64_t uptimeMs = 0;
uint64_t lastShownSecond = UINT64_MAX;
void setup() {
Serial.begin(115200);
Wire.begin(SDA_PIN, SCL_PIN);
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
Serial.println("Khong khoi tao duoc OLED");
while (true) { delay(1000); }
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
previousMs = millis();
}
void loop() {
const uint32_t now = millis();
uptimeMs += static_cast<uint32_t>(now - previousMs);
previousMs = now;
const uint64_t totalSeconds = uptimeMs / 1000ULL;
if (totalSeconds == lastShownSecond) {
delay(20);
return;
}
lastShownSecond = totalSeconds;
const uint32_t days = totalSeconds / 86400ULL;
const uint8_t hours = (totalSeconds / 3600ULL) % 24;
const uint8_t minutes = (totalSeconds / 60ULL) % 60;
const uint8_t seconds = totalSeconds % 60;
display.clearDisplay();
display.setCursor(0, 0);
display.println("ESP8266 uptime");
display.printf("Day: %lu
", static_cast<unsigned long>(days));
display.printf(
"%02u:%02u:%02u",
static_cast<unsigned>(hours),
static_cast<unsigned>(minutes),
static_cast<unsigned>(seconds)
);
display.display();
}
Mã cộng dồn chênh lệch của millis() bằng số học không dấu, vì vậy vẫn xử lý được thời điểm bộ đếm 32-bit quay vòng. Màn hình chỉ cập nhật khi số giây thay đổi để giảm nhấp nháy và lưu lượng I2C.
5. Xử lý sự cố
- Màn hình đen: quét I2C và kiểm tra địa chỉ. Ví dụ dùng reset pin
-1; nếu module có chân RST riêng, hãy nối chân đó và truyền GPIO thật vào constructor. - Ký tự hoặc hình sai: kiểm tra controller SSD1306/SH1106 và kích thước 128 × 64 hay 128 × 32.
- ESP8266 reset: kiểm tra nguồn, dây nối và tránh vòng lặp lỗi quá chặt; ví dụ trên có delay khi khởi tạo thất bại.
- Không biên dịch: cập nhật đồng bộ Adafruit GFX và Adafruit SSD1306, sau đó kiểm tra đúng profile bo.
Xem thêm bài LCD 1602 I2C với Arduino Uno và ESP32 điều khiển relay 4 kênh.
Xem thêm