OLED displej 128×64 2,42″ SSD1309 SPI a Arduino

Malé OLED displeje mám rád, protože se dají rychle připojit k Arduinu nebo ESP a hned je na čem zobrazovat hodnoty, menu nebo stav zařízení. Tentokrát tu mám ale trochu větší variantu. Nejde o klasický malý 0,96″ OLED modul, ale o bílý OLED displej s úhlopříčkou 2,42″ a rozlišením 128×64 bodů.

Displej komunikuje přes SPI, takže má víc vodičů než běžné I²C moduly, ale zase může být rychlejší a pro grafické výpisy příjemnější. V článku ho připojím k Arduinu, zkusím první zobrazení textu a grafiky a pak se podívám, k čemu se takový displej hodí v praktických projektech.

OLED displej 128×64 2,42″ SPI s řadičem SSD1309
OLED displej 128×64 2,42″ SPI s řadičem SSD1309

Co je to za displej

Jedná se o monochromatický OLED displej s bílými pixely. Monochromatický znamená, že každý bod může být jen rozsvícený nebo zhasnutý. Není to barevný displej, ale na texty, jednoduché grafy, ikony, stavové obrazovky nebo menu úplně stačí.

OLED displej nepotřebuje klasické podsvícení jako LCD. Svítí přímo jednotlivé pixely. Díky tomu má obraz pěkný kontrast, černá plocha je opravdu tmavá a bílé znaky jsou dobře čitelné.

Použitý displej má tyto základní parametry:

  • Úhlopříčka: 2,42″
  • Rozlišení: 128×64 bodů
  • Barva obrazu: bílá
  • Řadič: SSD1309
  • Komunikace: SPI
  • Napájení: 3,3 až 5 V
  • Pracovní proud: podle obsahu a jasu přibližně 100 až 300 mA
  • Rozměry modulu: 73×44 mm

Oproti menším OLEDům je tenhle displej na první pohled výrazně větší. Rozlišení zůstává 128×64 bodů, takže se na něj nevejde víc informací než na menší displej se stejným rozlišením, ale text a grafika jsou fyzicky větší a lépe čitelné.

SPI místo I²C

Hodně malých OLED displejů používá I²C sběrnici. Tam stačí napájení a dva signálové vodiče SDA a SCL. Tady je použitá sběrnice SPI, takže vodičů je víc.

Typicky se používají tyto signály:

  • VCC – napájení displeje
  • GND / VSS – zem
  • SCK / SCLK / D0 – hodinový signál SPI
  • MOSI / DIN / SDA / D1 – datový signál do displeje
  • CS – výběr displeje na SPI sběrnici
  • DC / A0 – rozlišení dat a příkazů
  • RES / RST – reset displeje

Výhoda SPI je v tom, že se po něm dají data do displeje posílat rychle. U obyčejného výpisu pár čísel je to skoro jedno, ale u grafiky, překreslování celé obrazovky nebo většího menu se to hodí.

Nevýhoda je jasná: je potřeba víc pinů na Arduinu.

Použitý hardware

Pro první test budu potřebovat:

Pro test použiju Arduino UNO, protože na něm je dobře vidět klasické hardwarové SPI zapojení. Stejný displej půjde použít i s ESP8266 nebo ESP32, jen se změní piny v programu.

Zapojení k Arduinu Nano / Uno

U SPI displeje je potřeba propojit napájení, SPI signály a řídicí piny. Zapojení pro Arduino může vypadat takto:

DisplejArduinoVýznam
VDD5VNapájení displeje
VSSGNDZem
SCLKD13Hodiny SPI
SDAD11Data do displeje
CSD10Výběr displeje
DCD9Data / příkaz
RESD8Reset displeje
zapojení s Arduino UNO

Pozor na to, že různé moduly můžou mít popisky pinů trochu jiné. Někde je datový pin označený jako DIN, jinde jako MOSI, SDA nebo D1. Hodinový pin může být SCK, CLK nebo D0. Důležité je držet se popisků přímo na konkrétním modulu.

Před připojením je dobré si pinout vyfotit nebo opsat. U displejů se vyplatí nespěchat, protože špatně připojené napájení nebo prohozené piny můžou znamenat zbytečné hledání chyby.

Knihovna U8g2

Pro ovládání displeje použiju knihovnu U8g2. Je to univerzální knihovna pro spoustu monochromatických displejů a podporuje i řadič SSD1309.

Instalace v Arduino IDE:

  1. Otevřít Manažéra knihoven
  2. Vyhledat U8g2
  3. Nainstalovat knihovnu U8g2 od oliver
  4. Restartovat Arduino IDE, pokud by se příklady nebo knihovna nenačetly správně

U8g2 umí různé displeje. Pro tenhle typ displeje je důležité vybrat variantu pro SSD1309, rozlišení 128×64 a 4-wire SPI.

První testovací program – zobrazení textu

První program udělá jen základní věc. Inicializuje displej, smaže obrazovku a vypíše krátký text. Cílem není hned kreslit složitou grafiku, ale ověřit, že displej komunikuje a že je zapojení správně.

///////////////////////OLED SSD1309 128x64 SPI fw v.0.1 /////////////////////
///////////////////////6.7.2026 /////////////////////////////////////////////
///////////////////////www.michaluvbrloh.cz//////////////////////////////////

#include <Arduino.h>       //základní knihovna Arduino
#include <SPI.h>           //komunikace přes SPI
#include <U8g2lib.h>       //knihovna pro OLED displej

const byte OLED_CS = 10;       //pin CS displeje
const byte OLED_DC = 9;        //pin DC displeje
const byte OLED_RST = 8;       //pin reset displeje

// typ displeje SSD1309 128x64 přes hardwarové SPI
U8G2_SSD1309_128X64_NONAME2_F_4W_HW_SPI displej(U8G2_R0, OLED_CS, OLED_DC, OLED_RST);

/////////////////////////////po spuštění///////////////////////////////////////////////////////////////////////////////////////
void setup()
  {
    displej.begin();                    //spusť displej

    vypisUvod();                        //vypiš úvodní obrazovku
  }

/////////////////////////////hlavní smyčka/////////////////////////////////////////////////////////////////////////////////////
void loop()
  {
    //v prvním testu se v hlavní smyčce nic nedělá
  }

/////////////////////////////výpis úvodní obrazovky///////////////////////////////////////////////////////////////////////////
void vypisUvod()
  {
    displej.clearBuffer();              //smaž obraz v paměti

    displej.drawFrame(4, 3, 118, 58);   //nakresli rámeček kolem displeje

    displej.setFont(u8g2_font_ncenB08_tr);       //větší font
    displej.drawStr(12, 20, "Michaluv brloh");    //první řádek

    displej.setFont(u8g2_font_6x10_tr);          //menší font
    displej.drawStr(12, 38, "OLED 128x64 SPI");   //druhý řádek
    displej.drawStr(12, 53, "Radic SSD1309");     //třetí řádek

    displej.sendBuffer();              //pošli obraz do displeje
  }

Pokud je všechno správně zapojené, měl by se po nahrání programu zobrazit rámeček a několik řádků textu.

zobrazení textu

Pokud se nezobrazí nic, zkontroloval bych postupně:

  • Jestli je správně připojené VCC a GND
  • Jestli má displej opravdu společnou zem s Arduinem
  • Jestli nejsou prohozené piny SCK a MOSI
  • Jestli sedí piny CS, DC a RST v programu
  • Jestli je použitý správný typ displeje v knihovně U8g2

Druhý testovací program – zobrazení grafiky

Když už displej bez problému zobrazoval text, chtěl jsem zkusit i trochu grafiky. U takového OLEDu nejde o žádné složité obrázky, ale pro různé rámečky, čáry, kružnice, ikony nebo ukazatele je ideální.

Právě v tomhle bývají podobné displeje nejpraktičtější. Dá se na ně zobrazit název zařízení, několik hodnot, jednoduchý grafický symbol nebo třeba stavový proužek. Na malý měřák, menu nebo ovládací panel je to úplně dostačující.

Na zkoušku jsem si připravil jednoduchou obrazovku, která kombinuje text a základní grafické prvky. Je na ní rámeček, vodorovná čára, kružnice, vyplněný obdélník a jednoduchý ukazatel stavu.

///////////////////////OLED SSD1309 grafika v.0.1 ////////////////////////////
///////////////////////7.7.2026 /////////////////////////////////////////////
///////////////////////www.michaluvbrloh.cz//////////////////////////////////

#include <Arduino.h> //základní knihovna Arduino
#include <SPI.h> //komunikace přes SPI
#include <U8g2lib.h> //knihovna pro OLED displej

const byte OLED_CS = 10; //pin CS displeje
const byte OLED_DC = 9; //pin DC displeje
const byte OLED_RST = 8; //pin reset displeje

U8G2_SSD1309_128X64_NONAME2_F_4W_HW_SPI displej(U8G2_R0, OLED_CS, OLED_DC, OLED_RST);

/////////////////////////////po spuštění///////////////////////////////////////////////////////////////////////////////////////
void setup()
{
displej.begin(); //spusť displej
vykresliGrafiku(); //zobraz ukázkovou grafiku
}

/////////////////////////////hlavní smyčka/////////////////////////////////////////////////////////////////////////////////////
void loop()
{
//v ukázce není potřeba nic opakovat
}

/////////////////////////////vykreslení ukázkové grafiky///////////////////////////////////////////////////////////////////////
void vykresliGrafiku()
{
displej.clearBuffer(); //smaž buffer

displej.drawFrame(4, 3, 118, 58); //hlavní rámeček
displej.drawLine(8, 18, 118, 18); //vodorovná oddělovací čára

displej.setFont(u8g2_font_6x10_tr); //nastav menší font
displej.drawStr(10, 14, "Ukazka grafiky");

displej.drawCircle(20, 34, 8); //kružnice
displej.drawDisc(45, 34, 8); //vyplněný kruh

displej.drawFrame(60, 26, 50, 12); //rámeček ukazatele
displej.drawBox(62, 28, 30, 8); //vyplněná cast ukazatele

displej.drawFrame(12, 46, 16, 10); //maly ramecek
displej.drawBox(34, 46, 16, 10); //vyplneny obdelnik
displej.drawRFrame(58, 44, 20, 14, 3); //zaobleny ramecek
displej.drawRBox(86, 44, 20, 14, 3); //vyplneny zaobleny obdelnik

displej.sendBuffer(); //pošli obraz do displeje
}

Co je na obrazovce vidět

Na téhle ukázce je několik základních grafických funkcí:

  • drawFrame() – nakreslí prázdný obdélník
  • drawLine() – nakreslí čáru
  • drawCircle() – nakreslí kružnici
  • drawDisc() – nakreslí vyplněný kruh
  • drawBox() – nakreslí vyplněný obdélník
  • drawRFrame() – nakreslí obdélník se zaoblenými rohy
  • drawRBox() – nakreslí vyplněný zaoblený obdélník
zobrazení grafiky

Díky tomu se dají poměrně snadno vytvořit jednoduché obrazovky s hodnotami, stavem zařízení nebo třeba s menu.

Zobrazení bitmapového obrázku

Když už displej zvládal text i jednoduchou grafiku, chtěl jsem zkusit ještě obrázek. Tady je ale potřeba si říct jednu důležitou věc. Běžný soubor BMP z počítače se do programu pro Arduino nedává přímo.

Nejjednodušší cesta je převést obrázek na černobílou 1bitovou bitmapu a vložit ho do programu jako pole bajtů. Knihovna U8g2 pro to umí použít formát XBM. Ten je pro malé monochromatické displeje ideální, protože každý pixel zabírá jen jeden bit.

Obrázek si můžeme připravit třeba v GIMPu nebo v online převodníku. Důležité je:

  • obrázek musí být černobílý
  • ideálně mít rozměr, který se vejde na displej
  • pro celý displej použít maximálně 128×64 pixelů
  • pro ikonu stačí třeba 32×32 nebo 64×32 pixelů

Na první test jsem použil malou ikonu 32×32 pixelů. Nezabere moc místa a dobře ukáže, že displej umí kromě textu zobrazit i jednoduchou grafiku.

///////////////////////OLED SSD1309 bitmapa v.0.1 ////////////////////////////
///////////////////////7.7.2026 /////////////////////////////////////////////
///////////////////////www.michaluvbrloh.cz//////////////////////////////////

#include <Arduino.h> //základní knihovna Arduino
#include <SPI.h> //komunikace přes SPI
#include <U8g2lib.h> //knihovna pro OLED displej

const byte OLED_CS = 10; //pin CS displeje
const byte OLED_DC = 9; //pin DC displeje
const byte OLED_RST = 8; //pin reset displeje

U8G2_SSD1309_128X64_NONAME2_F_4W_HW_SPI displej(U8G2_R0, OLED_CS, OLED_DC, OLED_RST);

#define logo_width 32 //šířka obrázku
#define logo_height 32 //výška obrázku

static const unsigned char logo_bits[] U8X8_PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x00,
0x00, 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00,
0xf0, 0x01, 0x80, 0x0f, 0x00, 0xf9, 0x9f, 0x00,
0x00, 0x09, 0x90, 0x00, 0x00, 0x19, 0x94, 0x00,
0xf0, 0x39, 0x96, 0x0f, 0x00, 0x59, 0x95, 0x00,
0x00, 0x99, 0x94, 0x00, 0x00, 0x19, 0x94, 0x00,
0xf0, 0x19, 0x94, 0x0f, 0x00, 0x19, 0x94, 0x00,
0x00, 0xf9, 0xbf, 0x00, 0x00, 0x01, 0xb0, 0x00,
0xf0, 0x01, 0x80, 0x0f, 0x00, 0xff, 0xff, 0x00,
0x00, 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x00,
0x00, 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};

/////////////////////////////po spuštění///////////////////////////////////////////////////////////////////////////////////////
void setup()
{
displej.begin(); //spusť displej
vykresliBitmapu(); //zobraz bitmapu
}

/////////////////////////////hlavní smyčka/////////////////////////////////////////////////////////////////////////////////////
void loop()
{
//v ukázce není potřeba nic opakovat
}

/////////////////////////////vykreslení bitmapy////////////////////////////////////////////////////////////////////////////////
void vykresliBitmapu()
{
displej.clearBuffer(); //smaž obraz v paměti

displej.drawFrame(4, 3, 118, 58); //rámeček kolem obrazovky

displej.drawXBMP(10, 20, logo_width, logo_height, logo_bits); //vykresli bitmapu

displej.setFont(u8g2_font_6x10_tr); //nastav font
displej.drawStr(52, 24, "Bitmapa"); //text vedle obrázku
displej.drawStr(52, 38, "32 x 32 px");
displej.drawStr(52, 52, "SSD1309");

displej.sendBuffer(); //pošli obraz do displeje
}

Tahle ukázka zobrazí malý čip jako bitmapový obrázek a vedle něj text. Prakticky se stejným způsobem dá zobrazit logo webu, ikona baterie, symbol Wi-Fi, výstražný znak nebo třeba malý obrázek zařízení.

Pokud bych chtěl zobrazit opravdu klasický BMP soubor, třeba načtený z SD karty, už by to bylo složitější. Program by musel soubor otevřít, přečíst BMP hlavičku, zjistit rozměry, projít obrazová data a převést je na černobílý obraz pro OLED. To už je spíš na samostatný pokus.

Jednoduchá animace

Když displej zvládl text, grafiku i bitmapový obrázek, zkusil jsem ještě jednoduchou animaci. Princip je vlastně jednoduchý. Program vždy smaže obraz v paměti, vykreslí nový stav obrázku a pošle ho do displeje. Potom se změní souřadnice nebo stav animace a celé se to opakuje.

Není to displej na video ani složité animace, ale pro malé efekty je úplně dostačující. Hodí se třeba pro načítací obrazovku, pohybující se ukazatel, blikající varování nebo jednoduchou stavovou animaci.

V ukázce se po displeji pohybuje malý vyplněný kruh a dole běží jednoduchý progress bar. Program nepoužívá delay(), ale časování přes millis(), takže by se později dala animace spojit i s měřením nebo čtením tlačítek.

///////////////////////OLED SSD1309 animace v.0.1 ////////////////////////////
///////////////////////7.7.2026 /////////////////////////////////////////////
///////////////////////www.michaluvbrloh.cz//////////////////////////////////

#include <Arduino.h> //základní knihovna Arduino
#include <SPI.h> //komunikace přes SPI
#include <U8g2lib.h> //knihovna pro OLED displej

const byte OLED_CS = 10; //pin CS displeje
const byte OLED_DC = 9; //pin DC displeje
const byte OLED_RST = 8; //pin reset displeje

int xKruh = 14; //aktuální poloha kruhu X
int smerKruh = 1; //směr pohybu kruhu
int progress = 0; //hodnota progress baru

unsigned long posledniAnimace = 0; //čas posledního překreslení
const unsigned long intervalAnimace = 40; //rychlost animace v ms

U8G2_SSD1309_128X64_NONAME2_F_4W_HW_SPI displej(U8G2_R0, OLED_CS, OLED_DC, OLED_RST);

/////////////////////////////po spuštění///////////////////////////////////////////////////////////////////////////////////////
void setup()
{
displej.begin(); //spusť displej
}

/////////////////////////////hlavní smyčka/////////////////////////////////////////////////////////////////////////////////////
void loop()
{
animace(); //obsluha animace
}

/////////////////////////////animace///////////////////////////////////////////////////////////////////////////////////////////
void animace()
{
if(millis() - posledniAnimace >= intervalAnimace) //pokud je čas na další snímek
{
posledniAnimace = millis(); //ulož čas posledního snímku

vykresliAnimaci(); //vykresli aktuální snímek
posunAnimaci(); //připrav další snímek
}
}

/////////////////////////////vykreslení animace////////////////////////////////////////////////////////////////////////////////
void vykresliAnimaci()
{
displej.clearBuffer(); //smaž obraz v paměti

displej.drawFrame(4, 3, 118, 58); //rámeček obrazovky

displej.setFont(u8g2_font_6x10_tr); //nastav font
displej.drawStr(12, 15, "Jednoducha animace");

displej.drawLine(12, 20, 112, 20); //oddělovací čára

displej.drawDisc(xKruh, 34, 5); //pohybující se kruh

displej.drawFrame(12, 48, 100, 8); //rámeček progress baru
displej.drawBox(14, 50, progress, 4); //vyplněná část progress baru

displej.sendBuffer(); //pošli obraz do displeje
}

/////////////////////////////posun animace/////////////////////////////////////////////////////////////////////////////////////
void posunAnimaci()
{
xKruh = xKruh + smerKruh; //posuň kruh

if(xKruh >= 106) //pokud je kruh u pravého okraje
{
smerKruh = -1; //změň směr doleva
}

if(xKruh <= 14) //pokud je kruh u levého okraje
{
smerKruh = 1; //změň směr doprava
}

progress++; //zvětši progress bar

if(progress > 96) //pokud progress dojel na konec
{
progress = 0; //začni znovu od začátku
}
}

Výsledek je jednoduchý, ale pro test displeje pěkný. Je vidět, že se obraz dá pravidelně překreslovat a že SPI komunikace stíhá i rychlejší změny. Pro reálné použití bych animaci držel spíš střídmou. OLED je nejlepší na přehledné stavové obrazovky, ne na zbytečně blikající efekty.

video jednoduché animace

První dojmy

Na tomhle displeji je pěkné hlavně to, že je fyzicky větší než běžné malé OLED moduly. Rozlišení 128×64 sice není nijak obrovské, ale pro stavovou obrazovku zařízení úplně stačí.

Hodí se třeba pro:

  • Menu malého přístroje
  • Zobrazení hodnot ze senzorů
  • Stav baterie a napájení
  • Jednoduché grafy
  • Výpis IP adresy, času nebo režimu zařízení
  • Malý terminálový výstup
  • Ovládací panel k Arduino nebo ESP projektu

Naopak se nehodí tam, kde je potřeba hodně textu, barevná grafika nebo jemné rozhraní jako na telefonu. Pořád je to jen 128×64 bodů, takže je potřeba šetřit místem.

Na co si dát pozor

OLED displeje mají krásný kontrast, ale není dobré na nich dlouhodobě nechávat úplně stejný obraz na plný jas. Důvodem je to, že jednotlivé pixely svítí samy o sobě a postupně se opotřebovávají. Pokud některé části displeje svítí pořád stejně, opotřebují se rychleji než zbytek a může dojít k takzvanému vypálení obrazu, kdy na displeji zůstane slabý „duch“ původního obsahu. U trvale běžících zařízení je proto lepší občas obraz změnit, snížit kontrast nebo po delší době nečinnosti displej vypnout.

Neznamená to, že se displej zničí po pár minutách, ale u zařízení, které má běžet týdny nebo měsíce se stejnou obrazovkou, je dobré s tím počítat.

Druhá věc je proud. Tenhle větší OLED může brát víc než malé 0,96″ moduly. Pokud bude součástí bateriového zařízení, je potřeba s tím počítat. Pro stolní přístroj napájený z USB to problém nebude, ale pro dlouhodobý provoz z akumulátoru už ano.

Třetí věc je zapojení přes SPI. Není složité, ale je tam víc vodičů. U prvního testu je proto nejlepší začít jen s displejem a jednoduchým programem. Teprve až bude obraz fungovat, má smysl přidávat další senzory, tlačítka nebo menu.

Závěr

Za mě se tenhle displej hodí hlavně tam, kde je potřeba dobře čitelná stavová obrazovka, ale není potřeba barevné nebo jemné grafické rozhraní. SPI zapojení znamená o pár vodičů víc, ale odměnou je rychlé překreslování a pohodlné použití s knihovnou U8g2. Na malé měřáky, ovládací panely, stavové displeje nebo různé Arduino a ESP projekty mi to dává smysl. Jen je potřeba počítat s větší spotřebou a u dlouhodobého provozu nenechávat na displeji pořád stejný obraz.

Tento displej zakoupíte na Laskakit.cz, přímý odkaz je ZDE.

Další díly ze začátečnické série o modulech najdete zde:

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *