Arduino: OLED displej 128×64 (SSD1306)
Serial Monitor je odličan dok je Arduino vezan za računar. Ali termometar, brojač ili igrica treba da rade i bez računara – za to služi mali OLED displej. Ima 128 × 64 tačke (piksela), dobro se vidi i u mraku, a sa Arduinom se povezuje sa samo četiri žice preko veze I2C.
Šta je OLED displej
- Najčešći je displej dijagonale 0,96 inča sa čipom SSD1306. Ima 128 tačaka u širinu i 64 u visinu.
- Svaka tačka sama svetli (kao mala LED dioda), pa displej nema pozadinsko osvetljenje i troši malo struje.
- Postoje jednobojni (beli, plavi) i dvobojni (gornjih 16 redova žuto, ostalo plavo) – programiraju se isto.
- Komunicira preko I2C veze: dve žice (SDA za podatke i SCL za takt) i svaki uređaj ima svoju adresu. Adresa ovog displeja je najčešće
0x3C.
Povezivanje
| Pin displeja | Arduino Uno | ESP32 |
|---|---|---|
| VCC | 5V (ili 3.3V) | 3V3 |
| GND | GND | GND |
| SDA | A4 | GPIO21 |
| SCL | A5 | GPIO22 |
Kod nekih modula redosled pinova je GND, VCC, SCL, SDA – uvek pročitaj natpise na pločici pre povezivanja.
U Arduino IDE-u instaliraj biblioteke Adafruit SSD1306 i Adafruit GFX Library (Sketch → Include Library → Manage Libraries). Kada te IDE pita da instalira i biblioteke koje su potrebne, izaberi „Install all“.
Provera: I2C skener
Pre prvog programa proveri da li Arduino „vidi“ displej. Ovaj kratki program ispisuje adrese svih uređaja na I2C vezi:
// I2C skener – ispisuje adrese svih uređaja na I2C vezi (radi i na Arduinu i na ESP32)
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin(); // na ESP32 možeš napisati Wire.begin(21, 22);
Serial.println("Trazim I2C uredjaje...");
int pronadjeno = 0;
for (int adresa = 1; adresa < 127; adresa++) {
Wire.beginTransmission(adresa);
if (Wire.endTransmission() == 0) { // 0 = uređaj se javio
Serial.print("Uredjaj na adresi 0x");
Serial.println(adresa, HEX);
pronadjeno++;
}
}
if (pronadjeno == 0) {
Serial.println("Nema uredjaja - proveri zice SDA, SCL, VCC i GND.");
}
}
void loop() {
}
Ako se ispiše 0x3C (ili 0x3D), sve je ispravno povezano. Ako nema uređaja, proveri žice SDA i SCL – najčešće su zamenjene.
Program 1: prvi tekst
// Arduino – OLED displej 128x64 (SSD1306, I2C): prvi tekst
// Biblioteke: „Adafruit SSD1306“ i „Adafruit GFX Library“ (Library Manager)
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
const int SIRINA = 128;
const int VISINA = 64;
// -1: displej nema poseban RESET pin
Adafruit_SSD1306 ekran(SIRINA, VISINA, &Wire, -1);
void setup() {
Serial.begin(9600);
// 0x3C je najčešća I2C adresa ovih displeja (ponekad 0x3D)
if (!ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Displej nije pronadjen!");
while (true) {
} // zaustavi program
}
ekran.clearDisplay(); // obriši sliku u memoriji
ekran.setTextColor(SSD1306_WHITE);
ekran.setTextSize(1); // mala slova: 21 znak u redu
ekran.setCursor(0, 0); // gornji levi ugao
ekran.println("Zdravo!");
ekran.setTextSize(2); // dvostruko veća slova
ekran.setCursor(0, 20);
ekran.println("Arduino");
ekran.display(); // tek sada se slika prenosi na displej
}
void loop() {
}
Kako se crta na displeju
- Tačka (0, 0) je u gornjem levom uglu. Broj x raste udesno (do 127), a y nadole (do 63).
- Sve naredbe crtaju u memoriju Arduina. Slika se prenosi na displej tek naredbom
display()– ako je zaboraviš, ekran ostaje prazan. clearDisplay()briše sliku u memoriji; pozivamo je pre crtanja novog sadržaja.
| setTextSize | Visina slova | Znakova u redu | Redova na ekranu |
|---|---|---|---|
| 1 | 8 tačaka | 21 | 8 |
| 2 | 16 tačaka | 10 | 4 |
| 3 | 24 tačke | 7 | 2 |
Program 2: brojač i oblici
// Arduino – OLED: vreme od uključenja i traka koja se puni
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 ekran(128, 64, &Wire, -1);
void setup() {
ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
ekran.setTextColor(SSD1306_WHITE);
}
void loop() {
unsigned long sekunde = millis() / 1000;
ekran.clearDisplay();
ekran.setTextSize(1);
ekran.setCursor(0, 0);
ekran.print("Vreme od ukljucenja:");
ekran.setTextSize(3);
ekran.setCursor(0, 16);
ekran.print(sekunde);
ekran.print(" s");
int duzina = map(sekunde % 10, 0, 9, 0, 124); // traka se puni svakih 10 s
ekran.drawRect(0, 52, 128, 12, SSD1306_WHITE); // okvir trake
ekran.fillRect(2, 54, duzina, 8, SSD1306_WHITE);
ekran.display();
delay(200);
}
| Naredba | Šta crta |
|---|---|
drawLine(x1, y1, x2, y2, boja) | liniju |
drawRect(x, y, širina, visina, boja) | okvir pravougaonika |
fillRect(x, y, širina, visina, boja) | popunjen pravougaonik |
drawCircle(x, y, r, boja) | krug |
fillCircle(x, y, r, boja) | popunjen krug |
drawPixel(x, y, boja) | jednu tačku |
Boja je SSD1306_WHITE (tačka svetli) ili SSD1306_BLACK (tačka ne svetli).
Program 3: termometar sa DHT11
Spajamo displej sa senzorom iz lekcije Senzor temperature: DATA pin senzora DHT11 je na pinu 3, a displej je i dalje na A4 i A5.
// Arduino – OLED termometar: temperatura i vlažnost sa DHT11 (DATA na pinu 3)
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#define DHTPIN 3
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
Adafruit_SSD1306 ekran(128, 64, &Wire, -1);
void setup() {
dht.begin();
ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
ekran.setTextColor(SSD1306_WHITE);
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
ekran.clearDisplay();
ekran.setTextSize(1);
ekran.setCursor(0, 0);
ekran.print("Sobni termometar");
ekran.drawLine(0, 10, 127, 10, SSD1306_WHITE); // linija ispod naslova
if (isnan(t) || isnan(h)) {
ekran.setCursor(0, 28);
ekran.print("Greska senzora!");
} else {
ekran.setTextSize(2);
ekran.setCursor(0, 18);
ekran.print(t, 1);
ekran.print(" C");
ekran.setCursor(0, 42);
ekran.print(h, 0);
ekran.print(" %");
}
ekran.display();
delay(2000); // DHT11 merimo na 2 sekunde
}
Ovo je prvi pravi uređaj koji radi bez računara: napajaj Arduino iz punjača za telefon ili baterije od 9 V i postavi ga bilo gde u sobi.
OLED displej na ESP32
Isti displej i iste biblioteke rade i na ESP32. Razlike su samo dve: displej se napaja sa 3V3, a I2C veza se pokreće naredbom Wire.begin(21, 22).
// ESP32 – isti OLED displej; menja se samo pokretanje I2C veze
// (SDA = GPIO21, SCL = GPIO22)
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 ekran(128, 64, &Wire, -1);
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // SDA, SCL – podrazumevani pinovi na ESP32
if (!ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Displej nije pronadjen!");
while (true) {
delay(100);
}
}
ekran.clearDisplay();
ekran.setTextColor(SSD1306_WHITE);
ekran.setTextSize(2);
ekran.setCursor(0, 0);
ekran.println("ESP32");
ekran.setTextSize(1);
ekran.println("OLED radi na 3,3 V");
ekran.display();
}
void loop() {
}
Displej ćemo koristiti i u završnom projektu pametna učionica.
Česti problemi
- Ekran je potpuno crn: proveri adresu skenerom (
0x3Cili0x3D) i da li si pozvaodisplay(). - Program staje na „Displej nije pronađen“: zamenjene su žice SDA i SCL ili displej nema napajanje.
- Arduino Uno radi čudno kada dodaš još koda: slika ekrana zauzima 1024 bajta, a Uno ima samo 2048 bajtova radne memorije. Koristi kraće tekstove i manje promenljivih (ili ESP32, koji ima mnogo više memorije).
- Tekst se preklapa: zaboravljen je
clearDisplay()pre novog crtanja.
Zadaci za vežbu
Pokušaj prvo sam da rešiš zadatak, pa tek onda otvori rešenje.
- Prikaži na displeju koliko je puta pritisnut taster na pinu 2, velikim brojevima (veličina slova 4).
- Nacrtaj grafik osvetljenja: LDR na A0, nova tačka svakih 100 ms, a stari deo grafika se pomera ulevo.
- Napravi animaciju: loptica poluprečnika 4 tačke kreće se po ekranu i odbija se od ivica.
Rešenje 1: brojač pritisaka na displeju
// Zadatak – brojač pritisaka tastera (pin 2) na OLED displeju, velikim brojevima
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 ekran(128, 64, &Wire, -1);
const int TASTER = 2;
int broj = 0;
int prethodno = HIGH;
void prikazi() {
ekran.clearDisplay();
ekran.setTextSize(1);
ekran.setCursor(0, 0);
ekran.print("Pritisaka:");
ekran.setTextSize(4);
ekran.setCursor(0, 20);
ekran.print(broj);
ekran.display();
}
void setup() {
pinMode(TASTER, INPUT_PULLUP);
ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
ekran.setTextColor(SSD1306_WHITE);
prikazi();
}
void loop() {
int sada = digitalRead(TASTER);
if (prethodno == HIGH && sada == LOW) {
broj++;
prikazi();
delay(30);
}
prethodno = sada;
}
Rešenje 2: grafik osvetljenja
// Zadatak – grafik osvetljenja: LDR na A0, nova tačka svakih 100 ms,
// a grafik se pomera ulevo
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 ekran(128, 64, &Wire, -1);
byte visine[128]; // pamtimo poslednjih 128 merenja (jedno po koloni)
void setup() {
ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
for (int x = 0; x < 128; x++) {
visine[x] = 63;
}
}
void loop() {
for (int x = 0; x < 127; x++) { // pomeri sve tačke ulevo
visine[x] = visine[x + 1];
}
visine[127] = map(analogRead(A0), 0, 1023, 63, 0); // veća vrednost = viša tačka
ekran.clearDisplay();
for (int x = 1; x < 128; x++) {
ekran.drawLine(x - 1, visine[x - 1], x, visine[x], SSD1306_WHITE);
}
ekran.display();
delay(100);
}
Rešenje 3: loptica koja se odbija
// Zadatak – loptica koja se odbija od ivica ekrana
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 ekran(128, 64, &Wire, -1);
int x = 10, y = 10; // položaj loptice
int dx = 2, dy = 1; // pomeraj u svakom koraku
const int R = 4; // poluprečnik
void setup() {
ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}
void loop() {
x += dx;
y += dy;
if (x - R <= 0 || x + R >= 127) dx = -dx; // udarac u levu ili desnu ivicu
if (y - R <= 0 || y + R >= 63) dy = -dy; // udarac u gornju ili donju ivicu
ekran.clearDisplay();
ekran.drawRect(0, 0, 128, 64, SSD1306_WHITE);
ekran.fillCircle(x, y, R, SSD1306_WHITE);
ekran.display();
delay(20);
}
Proveri znanje
Otvori kviz
Kviz: OLED displej
1. Na koje pinove Arduina Uno se vezuju SDA i SCL?
2. Gde je tačka (0, 0) na displeju?
3. Šta se desi ako zaboraviš display()?
4. Koja je najčešća I2C adresa displeja SSD1306?
