ArduinoVN
Đăng nhập Tham gia
Thư viện Code /u/linucat /22/05/2026

Thư viện U8g2: vẽ OLED đẹp hơn Adafruit_SSD1306

Thảo luận

Adafruit_SSD1306 là thư viện OLED phổ biến nhất nhưng U8g2 (Olikraus) đẹp hơn, mạnh hơn, và hỗ trợ vô số font + screen khác. Bài này hướng dẫn dùng U8g2 cho SSD1306 0.96", SSD1309 2.42", và các màn hình monochrome khác.

1. U8g2 vs U8x8 — chọn cái nào?

Tiêu chíU8g2U8x8
APIFull graphics (vẽ pixel, line, circle, font)Chỉ text 8×8
RAM~1 KB (full buffer) hoặc ~150 byte (page mode)~0 byte
Tốc độTrung bìnhNhanh nhất
Font500+ font đẹpChỉ font 8×8 sẵn

Mặc định dùng U8g2. Chỉ chuyển sang U8x8 khi RAM cực hạn chế (Uno chật).

2. Cài đặt

Library Manager → "U8g2" by oliver. Khoảng 5MB sau khi cài.

3. Chọn constructor đúng — quan trọng

U8g2 có hàng trăm constructor cho từng screen + bus. Pattern:

U8G2_<controller>_<resolution>_<buffer_mode>_<bus>

Ví dụ phổ biến:

// SSD1306 128x64 I2C, full buffer (1KB RAM)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);

// Page mode (ít RAM, vẽ nhiều lần)
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);

// SH1106 128x64 I2C (chip khác SSD1306 nhưng giống nhau bề ngoài)
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);

// SSD1309 2.42" SPI
U8G2_SSD1309_128X64_NONAME0_F_4W_HW_SPI u8g2(U8G2_R0, CS, DC, RST);

U8G2_R0 = không xoay; R1/R2/R3 = xoay 90/180/270°.

4. Setup và clear

void setup() {
  u8g2.begin();
}

void loop() {
  u8g2.clearBuffer();      // xoá buffer RAM
  u8g2.setFont(u8g2_font_ncenB14_tr);
  u8g2.drawStr(0, 20, "Hello!");
  u8g2.sendBuffer();       // gửi lên screen
  delay(1000);
}

5. Font — kho hơn 500 mẫu

Format: u8g2_font_<tên>_<weight><ký_tự_set>. Ví dụ:

  • u8g2_font_5x7_tr — 5×7 pixel, transparent, ASCII reduced.
  • u8g2_font_ncenB14_tr — New Century 14 bold.
  • u8g2_font_logisoso24_tn — Logisoso 24, chỉ số (cho đồng hồ).
  • u8g2_font_unifont_t_vietnamese1 — hỗ trợ Tiếng Việt!

Browse tất cả: github.com/olikraus/u8g2 fntlistall.

6. API vẽ chính

u8g2.drawPixel(x, y);
u8g2.drawLine(x0, y0, x1, y1);
u8g2.drawHLine(x, y, w);
u8g2.drawVLine(x, y, h);
u8g2.drawFrame(x, y, w, h);          // khung rỗng
u8g2.drawBox(x, y, w, h);            // hộp đặc
u8g2.drawCircle(x, y, r);
u8g2.drawDisc(x, y, r);              // đĩa đặc
u8g2.drawTriangle(x0, y0, x1, y1, x2, y2);
u8g2.drawRFrame(x, y, w, h, r);      // bo góc
u8g2.drawXBM(x, y, w, h, bitmap);    // bitmap đen trắng

7. Text với canh giữa

u8g2.setFont(u8g2_font_ncenB14_tr);
const char* msg = "OK";
uint8_t w = u8g2.getStrWidth(msg);
u8g2.drawStr((128 - w) / 2, 40, msg);

drawStr(x, y, ...) — y là baseline (đáy chữ, không phải đỉnh).

8. Page mode — RAM thấp

SSD1306 128×64 cần 1024 byte buffer. Uno chỉ 2KB RAM — chật. Page mode dùng 128 byte (1/8 màn hình), vẽ 8 lần:

U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);

void loop() {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0, 20, "Hi");
  } while (u8g2.nextPage());
}

Chậm hơn full buffer ~8 lần nhưng tiết kiệm 880 byte RAM.

9. Bitmap — ảnh icon

Convert ảnh PNG → XBM bằng online tool, paste array vào code:

const uint8_t icon_wifi[] PROGMEM = {
  0x00, 0x00, 0x3E, 0x00, /* ... */
};
u8g2.drawXBMP(0, 0, 16, 16, icon_wifi);

10. Update screen — đừng quá nhanh

SSD1306 I2C tốc độ tối đa ~30 fps. Update mỗi 16ms là dư cho UI. Update quá nhanh (mỗi loop) = ngốn CPU vô ích.

uint32_t lastDraw = 0;
void loop() {
  if (millis() - lastDraw > 100) {
    lastDraw = millis();
    u8g2.clearBuffer();
    // draw...
    u8g2.sendBuffer();
  }
}

11. Tiếng Việt

U8g2 hỗ trợ Unicode qua drawUTF8():

u8g2.setFont(u8g2_font_unifont_t_vietnamese1);
u8g2.drawUTF8(0, 20, "Xin chào Việt Nam");

Font Vietnamese chiếm flash ~6KB — tốt với ESP32, nặng cho Uno.

12. So sánh API với Adafruit

Adafruit dùng display.print() giống Serial. U8g2 dùng drawStr(x, y, ...). U8g2 yêu cầu nghĩ trước layout, nhưng kết quả đẹp và precise hơn.

Liên quan

Đối chiếu với Adafruit SSD1306: vẽ pixel, text, hình. Áp dụng vào dự án Đồng hồ báo thức OLED + DS3231.

Thảo luận (0)

Đăng nhập để tham gia thảo luận.
Chưa có bình luận nào. Hãy là người đầu tiên!