Lập trình ESP32 – Bài 15: Màn hình OLED SSD1306 (I2C)

Hướng dẫn kết nối và lập trình I2C cho OLED với ESP32: khởi tạo, hiển thị chữ nhiều dòng trên màn hình đơn sắc 128×64.

Mục lục

  1. Giới thiệu nhanh SSD1306
  2. Chuẩn bị phần cứng
  3. Cài thư viện
  4. Ví dụ 1 — Simple working with OLED
  5. Ví dụ 2 — Hiển thị nhiều dòng text
  6. Ví dụ 3 — Hiển thị hình Icon Robot
  7. Lỗi thường gặp & cách khắc phục
  8. Gợi ý mở rộng

1) Giới thiệu nhanh OLED SSD1306

  • OLED SSD1306 là màn hình đơn sắc, phổ biến kích thước 0.96″ 128×64.
  • Giao tiếp I2C giúp dây gọn: SDA/SCL.
  • Phù hợp hiển thị text, icon, đồ họa đơn giản.

2) Chuẩn bị phần cứng

Thiết bịSLGhi chú
ESP32 DevKit V11
OLED SSD1306 0.96″ I2C1128×64, addr 0x3C
Dây nối dupontVài sợi

3) Cài thư viện (Arduino IDE)

  • Adafruit SSD1306
  • Adafruit GFX Library
    Vào Tools → Manage Libraries… và cài hai thư viện trên.

4) Ví dụ 1 — Simple working with OLED

Khởi tạo OLED, hiển thị chuỗi “Hello OLED”.

/*
 * ESP32 + OLED SSD1306
 * Ví dụ 1: Khởi tạo và in chuỗi đơn giản
 */

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Kích thước màn hình
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Reset = -1 nếu không dùng chân reset cứng
#define OLED_RESET -1

// Tạo đối tượng màn hình
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  // Khởi tạo Serial để debug
  Serial.begin(115200);

  // Khởi tạo OLED tại địa chỉ 0x3C
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("Không tìm thấy OLED! Kiểm tra dây SDA/SCL và địa chỉ (0x3C/0x3D)"));
    for(;;); // kẹt lại nếu lỗi
  }

  // Xóa màn hình
  display.clearDisplay();

  // Thiết lập cỡ chữ và màu
  display.setTextSize(2);                 // cỡ chữ 2x
  display.setTextColor(SSD1306_WHITE);    // màu trắng (đơn sắc)
  display.setCursor(0, 16);               // vị trí con trỏ
  display.println(F("Hello OLED"));
  display.display();                      // đẩy buffer ra màn hình
}

void loop() {
  // Không làm gì thêm trong ví dụ 1
}

5) Ví dụ 2 — Hiển thị nhiều dòng text

/*
 * ESP32 + OLED SSD1306
 * Ví dụ 2: Hiển thị nhiều dòng văn bản
 */

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  Serial.begin(115200);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED init failed!"));
    for(;;);
  }

  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);

  // Dòng 1
  display.setTextSize(1);        // cỡ chữ nhỏ để vừa 3 dòng
  display.setCursor(0, 0);
  display.println(F("Project: Demo OLED"));

  // Dòng 2
  display.setCursor(0, 20);
  display.println(F("Message: Xin chao!"));

  // Dòng 3
  display.setCursor(0, 40);
  display.println(F("Website:"));
  display.setCursor(0, 52);
  display.println(F("https://hoclaptrinhrobot.com"));

  display.display();             // Cập nhật lên màn hình
}

void loop() {
  // Ví dụ tĩnh, không cần cập nhật liên tục
}

6) Ví dụ 3 — Hiển thị hình icon Robot đơn giản

Ta vẽ mặt robot (đầu tròn, mắt, miệng) + thân/ tay bằng primitive của GFX.

/*
 * ESP32 + OLED SSD1306
 * Ví dụ 3: Vẽ hình "Robot" đơn giản bằng primitive (circle, rect, line)
 */

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void drawRobotFace(int x, int y) {
  // Đầu robot (hình tròn)
  display.drawCircle(x, y, 18, SSD1306_WHITE);

  // Mắt (hai hình tròn nhỏ)
  display.fillCircle(x - 7, y - 4, 3, SSD1306_WHITE);
  display.fillCircle(x + 7, y - 4, 3, SSD1306_WHITE);

  // Miệng (đường thẳng)
  display.drawLine(x - 8, y + 7, x + 8, y + 7, SSD1306_WHITE);

  // Ăng-ten (thân + chấm tròn)
  display.drawLine(x, y - 18, x, y - 26, SSD1306_WHITE);
  display.fillCircle(x, y - 29, 2, SSD1306_WHITE);
}

void drawRobotBody(int x, int y) {
  // Thân (hình chữ nhật)
  display.drawRect(x - 14, y, 28, 18, SSD1306_WHITE);

  // Tay trái/phải (đường chéo)
  display.drawLine(x - 14, y + 4, x - 26, y + 12, SSD1306_WHITE);
  display.drawLine(x + 14, y + 4, x + 26, y + 12, SSD1306_WHITE);

  // Chân (đường thẳng)
  display.drawLine(x - 6, y + 18, x - 6, y + 30, SSD1306_WHITE);
  display.drawLine(x + 6, y + 18, x + 6, y + 30, SSD1306_WHITE);
}

void setup() {
  Serial.begin(115200);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED init failed!"));
    for(;;);
  }

  display.clearDisplay();

  // Tiêu đề
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println(F("Robot on OLED"));

  // Vẽ robot 1 (trung tâm lệch trái)
  drawRobotFace(40, 28);
  drawRobotBody(40, 46);

  // Vẽ robot 2 (trung tâm lệch phải)
  drawRobotFace(92, 26);
  drawRobotBody(92, 44);

  display.display();
}

void loop() {
  // Có thể thêm animation nếu muốn (di chuyển tay/chân)
}

7) Lỗi thường gặp & cách khắc phục

LỗiNguyên nhânCách xử lý
Màn hình không hiệnSai địa chỉ I2CThử 0x3D; kiểm tra SDA/SCL
Nhấp nháy, nhiễuDây I2C quá dài hoặc nguồn yếuDây ngắn, thêm tụ, dùng nguồn ổn định
Compile lỗiThiếu thư việnCài Adafruit SSD1306Adafruit GFX

8) Gợi ý mở rộng

  • Vẽ icon trạng thái (WiFi/Battery), progress bar, đồng hồ.
  • Tạo menu điều hướng bằng nút nhấn hoặc encoder.
  • Hiển thị dữ liệu cảm biến (MQ-2, DHT, HC-SR04, …).

Comments

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *