Hướng dẫn dùng màn hình OLED 0.96 inch SSD1306 với Arduino Nano

Hướng dẫn nối màn hình OLED 0.96 inch SSD1306 (I2C) với Arduino Nano, cài thư viện Adafruit, hiện chữ nhiều cỡ, vẽ thanh mức theo điện áp và lưu ý về bộ nhớ RAM.

Màn hình OLED 0.96 inch nhỏ gọn, chữ sắc nét, chỉ cần bốn dây nối và rất hợp với Arduino Nano trên breadboard. Bài viết hướng dẫn nối màn hình OLED SSD1306 giao tiếp I2C với Arduino Nano, cài thư viện, hiện chữ với nhiều cỡ, vẽ thanh mức theo điện áp đo được và những lưu ý về bộ nhớ RAM, vốn là chỗ người mới hay vướng nhất khi dùng màn hình này với Nano.

1. Tìm hiểu màn hình OLED 0.96 inch

Thông số cơ bản của màn hình OLED 0.96 inch I2C
Thông sốGiá trị
Kích thước, độ phân giải0.96 inch, 128 x 64 điểm ảnh
Chip điều khiểnSSD1306
Giao tiếpI2C, bốn chân GND, VCC, SCL, SDA
Địa chỉ I2C0x3C (một số màn hình dùng 0x3D)
Nguồn cấp3,3–5 V
Màu hiển thịHai vùng màu: 16 hàng trên màu vàng, phần còn lại màu xanh

Mỗi điểm ảnh OLED tự phát sáng nên màn hình không cần đèn nền, nền đen sâu và nhìn rõ từ nhiều góc. Màu của từng vùng do tấm nền quyết định, chương trình chỉ bật hoặc tắt điểm ảnh chứ không chọn được màu.

2. Linh kiện cần chuẩn bị

3. Sơ đồ nối màn hình với Arduino Nano

Đấu nối màn hình OLED 0.96 inch với Arduino Nano
OLED 0.96 inchArduino NanoGhi chú
VCC5VMàn hình nhận nguồn 3,3–5 V.
GNDGNDMass chung.
SCLA5Xung clock I2C.
SDAA4Dữ liệu I2C.
Sơ đồ nối Arduino Nano với màn hình OLED 0.96 inch SSD1306 qua I2C: VCC vào 5V, GND vào GND, SCL vào A5, SDA vào A4
Sơ đồ nối Arduino Nano với màn hình OLED 0.96 inch (hình vẽ minh họa): VCC – 5V, GND – GND, SCL – A5, SDA – A4.

Trên Arduino Nano, bus I2C cố định ở hai chân A4 (SDA) và A5 (SCL), không đổi sang chân khác được. Thứ tự bốn chân trên màn hình có thể khác nhau theo lô hàng, vì vậy luôn nối theo tên chân in trên mạch; cắm ngược VCC và GND có thể làm hỏng màn hình.

4. Cài thư viện

  1. Mở Tools > Manage Libraries, tìm Adafruit SSD1306 và bấm Install.
  2. Khi IDE hỏi cài thêm thư viện phụ thuộc, chọn Install All để cài kèm Adafruit GFX Library và Adafruit BusIO.
  3. Chọn Tools > Board > Arduino AVR Boards > Arduino Nano, chọn đúng Processor và cổng COM như đã làm trong bài bắt đầu với Nano.

Bài dùng Adafruit SSD1306 phiên bản 2.5.17, Adafruit GFX Library 1.12.6 và Adafruit BusIO 1.17.4.

5. Chương trình 1: hiện chữ với ba cỡ chữ

/*
  PYWORLD.VN - Arduino Nano + màn hình OLED 0.96 inch SSD1306 (I2C): hiện chữ với ba cỡ chữ
  OLED: VCC = 5V, GND = GND, SCL = A5, SDA = A4, địa chỉ 0x3C
  Thư viện: Adafruit SSD1306, Adafruit GFX
*/

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

#define OLED_ADDR 0x3C

Adafruit_SSD1306 oled(128, 64, &Wire, -1);

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

  // Lệnh begin() xin 1024 byte RAM làm bộ đệm hình; trả về false nếu không đủ RAM
  if (!oled.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(F("Khong khoi tao duoc OLED!"));
    while (true) {}
  }

  oled.clearDisplay();                  // Xóa bộ đệm
  oled.setTextColor(SSD1306_WHITE);

  oled.setTextSize(1);                  // Cỡ 1: mỗi ký tự 6 x 8 điểm ảnh
  oled.setCursor(0, 4);
  oled.print(F("Co chu 1 - 6x8 diem"));

  oled.setTextSize(2);                  // Cỡ 2: lớn gấp đôi
  oled.setCursor(0, 20);
  oled.print(F("Co chu 2"));

  oled.setTextSize(3);                  // Cỡ 3: lớn gấp ba
  oled.setCursor(0, 40);
  oled.print(F("Co 3"));

  oled.display();                       // Gửi bộ đệm ra màn hình
}

void loop() {
}

Sau khi nạp, màn hình hiện ba dòng chữ với ba cỡ khác nhau:

Hình mô phỏng màn hình OLED 128 x 64 hiện ba cỡ chữ 1, 2, 3 kèm trục toạ độ x từ 0 đến 127 và y từ 0 đến 63
Ba cỡ chữ và hệ toạ độ của màn hình (hình mô phỏng theo toạ độ và bộ chữ của chương trình).
  • Toạ độ: gốc (0, 0) ở góc trên bên trái; x tăng sang phải đến 127, y tăng xuống dưới đến 63. setCursor(x, y) đặt góc trên bên trái của ký tự tiếp theo.
  • Cỡ chữ: ở cỡ 1 mỗi ký tự chiếm 6 x 8 điểm ảnh, nên một dòng chứa được 21 ký tự và màn hình chứa được 8 dòng. Cỡ 2 và cỡ 3 lớn gấp đôi và gấp ba.
  • Bộ đệm: các lệnh print() và lệnh vẽ chỉ ghi vào bộ đệm trong RAM. Hình chỉ xuất hiện khi gọi oled.display().
  • Chữ không dấu: bộ chữ mặc định của thư viện không có dấu tiếng Việt.
  • F("..."): giữ chuỗi trong bộ nhớ flash thay vì chép vào RAM. Với Nano nên dùng cho mọi chuỗi cố định.

6. Lưu ý quan trọng: bộ nhớ RAM của Nano

Vi điều khiển ATmega328P trên Arduino Nano chỉ có 2048 byte RAM. Bộ đệm hình của màn hình 128 x 64 cần 128 × 64 / 8 = 1024 byte, tức một nửa số RAM đó.

  • Bộ đệm được cấp phát khi chương trình chạy đến lệnh oled.begin(). Dòng Global variables use... mà Arduino IDE in ra sau khi kiểm tra chương trình chưa tính 1024 byte này.
  • Nếu không đủ RAM, oled.begin() trả về false và màn hình không hiện gì. Vì vậy chương trình luôn kiểm tra giá trị trả về của lệnh này.
  • Để dành RAM cho màn hình: dùng F() cho chuỗi cố định, tránh kiểu String, tránh khai báo mảng lớn.
  • Màn hình loại 128 x 32 chỉ cần bộ đệm 512 byte, phù hợp khi chương trình cần nhiều RAM cho việc khác.

7. Chương trình 2: hiện điện áp và thanh mức

Nối thêm biến trở 10 kΩ: hai chân ngoài vào 5V và GND, chân giữa vào A0. Chương trình đọc điện áp ở A0, hiện số đo cỡ lớn và vẽ một thanh mức dài theo điện áp:

/*
  PYWORLD.VN - Arduino Nano + OLED 0.96 inch: đọc điện áp ở chân A0, hiện số và thanh mức
  OLED: VCC = 5V, GND = GND, SCL = A5, SDA = A4, địa chỉ 0x3C
  Biến trở 10 kΩ: hai chân ngoài nối 5V và GND, chân giữa nối A0
  Thư viện: Adafruit SSD1306, Adafruit GFX
*/

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

#define OLED_ADDR   0x3C
#define ANALOG_PIN  A0

Adafruit_SSD1306 oled(128, 64, &Wire, -1);

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

  if (!oled.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(F("Khong khoi tao duoc OLED!"));
    while (true) {}
  }
  oled.setTextColor(SSD1306_WHITE);
}

void loop() {
  int giaTri = analogRead(ANALOG_PIN);            // 0-1023
  float volt = giaTri * 5.0 / 1023.0;             // Đổi sang vôn theo nguồn 5 V
  int rongThanh = map(giaTri, 0, 1023, 0, 124);   // Bề rộng phần tô của thanh mức

  oled.clearDisplay();

  oled.setTextSize(1);
  oled.setCursor(0, 4);
  oled.print(F("Dien ap chan A0"));

  oled.setTextSize(3);
  oled.setCursor(0, 20);
  oled.print(volt, 2);
  oled.setTextSize(2);
  oled.setCursor(84, 28);
  oled.print(F("V"));

  oled.drawRect(0, 50, 128, 12, SSD1306_WHITE);         // Khung của thanh mức
  oled.fillRect(2, 52, rongThanh, 8, SSD1306_WHITE);    // Phần tô theo điện áp

  oled.display();
  delay(200);
}
Hình mô phỏng màn hình OLED hiện điện áp chân A0 là 2.50 V kèm thanh mức tô khoảng một nửa
Màn hình của chương trình đo điện áp khi chân A0 ở khoảng 2,5 V (hình mô phỏng theo toạ độ và bộ chữ của chương trình).
  • analogRead(A0) trả về 0–1023 ứng với 0–5 V; chương trình nhân với 5,0 / 1023 để đổi sang vôn.
  • map(giaTri, 0, 1023, 0, 124) đổi giá trị đọc được thành bề rộng phần tô, tính bằng điểm ảnh.
  • drawRect(x, y, rộng, cao, màu) vẽ khung; fillRect() vẽ hình chữ nhật tô kín. Thư viện còn có drawLine(), drawCircle(), drawBitmap() và nhiều lệnh vẽ khác.
  • Mỗi vòng lặp chương trình xóa bộ đệm, vẽ lại toàn bộ rồi mới gọi display(), nên hình không bị chồng lên nhau.

Số đo dựa vào nguồn 5 V của Nano làm chuẩn. Khi cấp nguồn qua cổng USB, điện áp này thường thấp hơn 5 V một chút nên số đo có sai lệch nhỏ; chỉ đưa vào A0 điện áp trong khoảng 0–5 V.

8. Xử lý lỗi thường gặp

  • Màn hình không hiện gì, Serial Monitor báo "Khong khoi tao duoc OLED!": thiếu RAM cho bộ đệm (mục 6). Bỏ bớt biến và chuỗi trong chương trình rồi thử lại.
  • Màn hình không hiện gì và không có thông báo: kiểm tra bốn dây, nhất là SDA vào A4 và SCL vào A5. Nếu dây đúng, màn hình có thể dùng địa chỉ 0x3D; chạy chương trình quét I2C trong bài bắt đầu với Arduino Nano CH340 để biết địa chỉ.
  • Hình bị lệch, có dải nhiễu ở mép: màn hình dùng chip SH1106 (thường gặp ở loại 1.3 inch) chứ không phải SSD1306, cần thư viện khác. Xem bài dùng màn hình OLED 1.3 inch SH1106 với ESP32.
  • Hình cũ không mất, chữ chồng lên nhau: thiếu lệnh clearDisplay() trước khi vẽ khung hình mới.
  • Đã gọi lệnh vẽ mà màn hình không đổi: thiếu lệnh display().
  • Chương trình chạy một lúc rồi treo hoặc hiện ký tự lạ: RAM bị tràn do dùng String hoặc mảng lớn. Giảm lượng RAM sử dụng theo mục 6.
  • Không nạp được chương trình: chọn lại Processor (thử ATmega328P (Old Bootloader)) và cổng COM theo bài bắt đầu với Arduino Nano.

Xem thêm: dùng màn hình LCD 1602 I2C với Arduino Uno, dùng màn hình OLED SSD1306 với ESP8266 và dùng màn hình OLED 1.3 inch SH1106 với ESP32.


Tin tức liên quan

Hướng dẫn làm cân điện tử với ESP32, HX711 và load cell trên Arduino IDE
Hướng dẫn làm cân điện tử với ESP32, HX711 và load cell trên Arduino IDE

7 Lượt xem

Hướng dẫn nối load cell với module HX711 và ESP32 DevKit V1, gá load cell đúng cách, hiệu chuẩn bằng vật đã biết khối lượng và viết chương trình cân trên Arduino IDE.

Hướng dẫn làm đồng hồ Internet với ESP32, NTP và màn hình OLED 0.96 inch
Hướng dẫn làm đồng hồ Internet với ESP32, NTP và màn hình OLED 0.96 inch

5 Lượt xem

Hướng dẫn ESP32 lấy giờ Việt Nam từ Internet bằng NTP trên Arduino IDE, in ra Serial Monitor và làm đồng hồ hiển thị thứ, ngày, giờ trên màn hình OLED 0.96 inch SSD1306.

Hướng dẫn dùng MQTT với ESP32: gửi dữ liệu và điều khiển relay bằng PubSubClient
Hướng dẫn dùng MQTT với ESP32: gửi dữ liệu và điều khiển relay bằng PubSubClient

5 Lượt xem

Hướng dẫn dùng MQTT với ESP32 trên Arduino IDE: broker, topic, publish, subscribe, cài Mosquitto và PubSubClient, gửi dữ liệu và điều khiển module relay qua mạng nội bộ.

Hướng dẫn điều khiển relay bằng điện thoại qua Bluetooth với ESP32
Hướng dẫn điều khiển relay bằng điện thoại qua Bluetooth với ESP32

4 Lượt xem

Hướng dẫn dùng Bluetooth Classic của ESP32 trên Arduino IDE: ghép đôi với điện thoại Android, gửi nhận chữ bằng BluetoothSerial và điều khiển module relay bằng lệnh ON, OFF.

Hướng dẫn nạp chương trình cho ESP32 qua Wi-Fi (OTA) bằng Arduino IDE
Hướng dẫn nạp chương trình cho ESP32 qua Wi-Fi (OTA) bằng Arduino IDE

4 Lượt xem

Hướng dẫn bật OTA trên ESP32 bằng thư viện ArduinoOTA có sẵn, nạp chương trình qua Wi-Fi từ Arduino IDE 2.x, đặt mật khẩu và các quy tắc để không mất khả năng cập nhật từ xa.

Hướng dẫn đọc ADC trên ESP32 và đo điện áp pin 18650 bằng cầu phân áp
Hướng dẫn đọc ADC trên ESP32 và đo điện áp pin 18650 bằng cầu phân áp

5 Lượt xem

Hướng dẫn đọc điện áp analog bằng ADC của ESP32 trên Arduino IDE, dùng analogReadMilliVolts, làm cầu phân áp đo pin Li-ion 18650 và ước lượng phần trăm pin còn lại.

Hướng dẫn dùng Deep Sleep trên ESP32: tiết kiệm pin, đánh thức bằng timer và nút nhấn
Hướng dẫn dùng Deep Sleep trên ESP32: tiết kiệm pin, đánh thức bằng timer và nút nhấn

5 Lượt xem

Hướng dẫn đưa ESP32 vào Deep Sleep trên Arduino IDE để tiết kiệm pin: các chế độ nguồn, đánh thức bằng timer và nút nhấn, giữ biến trong bộ nhớ RTC và ước tính thời lượng pin.

Hướng dẫn kết nối Wi-Fi trên ESP32: quét mạng, tự kết nối lại, IP tĩnh và phát Wi-Fi riêng
Hướng dẫn kết nối Wi-Fi trên ESP32: quét mạng, tự kết nối lại, IP tĩnh và phát Wi-Fi riêng

4 Lượt xem

Hướng dẫn các thao tác Wi-Fi cần dùng nhất trên ESP32 với Arduino IDE: quét mạng, kết nối có thời gian chờ, xem IP và cường độ sóng, tự kết nối lại, đặt IP tĩnh, phát Wi-Fi riêng.


Bình luận
Đã thêm vào giỏ hàng