Модули · статья
OLED-дисплей SSD1306 0.96″ и Arduino: подключение, библиотеки, память
Маленький яркий экран на 128×64 точки, четыре провода и ни одного подстроечника. Разбираем, чем он отличается от LCD 1602, почему фирменный пример оставляет экран чёрным, какую из трёх библиотек брать — Adafruit, U8g2 или GyverOLED — и сколько каждая съедает из двух килобайт памяти Arduino Uno. Все числа мы измерили сборкой; живого экрана под рукой не было, и там, где это важно, мы так и пишем.
Что это за экран и чем он не LCD
OLED 0.96″ — это матрица 128 на 64 светящиеся точки под управлением контроллера SSD1306. Подсветки нет: каждая точка светится сама, поэтому чёрный на нём по-настоящему чёрный, углы обзора любые, а питания хватает от USB. Бывает двухцветным — верхние 16 строк жёлтые, остальное голубое; это не режим, а так напечатана матрица, и в коде это никак не выбирается.
От LCD 1602 он отличается принципиально. LCD показывает знаки из зашитой таблицы: вы шлёте код буквы, экран рисует её сам. OLED не знает никаких букв — это просто 8 192 точки, и каждую зажигает ваша программа. Отсюда всё: любые шрифты и картинки, в том числе русские буквы без фокусов — но и буфер кадра в памяти платы, который на Arduino Uno занимает половину всей оперативной памяти.
Встречаются и родственники. Экран 0.91″ — это 128×32, те же контроллер и библиотеки, меняется размер в конструкторе: у Adafruit число 64 → 32, у U8g2 имя класса с «128X32», у GyverOLED параметр SSD1306_128x32. Экран 1.3″ выглядит так же, но внутри обычно стоит другой контроллер — SH1106; код для SSD1306 на нём даст сдвинутую картинку с мусором по краям, про это отдельный раздел ниже.
Подключение: четыре провода и один подвох
- GND → GND (земля)
- 5V → VCC (питание)
- A4 → SDA (данные)
- A5 → SCL (такт)
| На модуле | Uno, Nano | Mega 2560 | Leonardo, Micro | ESP8266 (NodeMCU, D1 mini) | ESP32 (классический DevKit) |
|---|---|---|---|---|---|
| GND | GND | GND | GND | GND | GND |
| VCC | 5V или 3.3V | 5V или 3.3V | 5V или 3.3V | 3V3 | 3V3 |
| SDA | A4 | 20 | 2 | D2 (GPIO4) | 21 |
| SCL | A5 | 21 | 3 | D1 (GPIO5) | 22 |
Подвох в порядке выводов. У одних модулей слева направо идут GND, VCC, SCL, SDA, у других — VCC, GND, SCL, SDA. Они выглядят одинаково, и если воткнуть второй по памяти о первом, питание и земля поменяются местами — а защиты от этого на модуле нет, перепутанные провода могут его сжечь. Читайте подписи на плате до включения, а не положение контактов. Сам чип SSD1306 трёхвольтовый, но на модулях стоит стабилизатор, и от 5 В платы Arduino они питаются штатно; на ESP берите 3V3. И ещё: если у модуля не четыре вывода, а семь (GND, VCC, D0, D1, RES, DC, CS) — это версия с шиной SPI, и всё ниже про четыре провода и адрес к ней не относится; конструктор там другой, display(128, 64, &SPI, DC, RES, CS). Куда идут его семь проводов — в таблице ниже.
| Вывод модуля по SPI | Куда на Uno и Nano | Что это |
|---|---|---|
| GND | GND | земля |
| VCC | 5V или 3.3V | питание |
| D0 (SCK, CLK) | 13 | такт шины SPI |
| D1 (MOSI, SDA) | 11 | данные в дисплей |
| RES (RST) | любой свободный, например 9 | сброс дисплея |
| DC | любой свободный, например 8 | команда или данные |
| CS | любой свободный, например 10 | выбор устройства |
В коде меняется только конструктор: Adafruit_SSD1306 display(128, 64, &SPI, 8, 9, 10) — числа здесь это DC, RES и CS. Всё остальное в статье — библиотеки, буфер, шрифты, ошибки — к SPI-версии относится полностью: контроллер тот же.
Линии SDA и SCL у всех плат те же, что и для любого другого устройства I2C: на Uno это A4 и A5, они же продублированы двумя контактами рядом с AREF. Что за плата NodeMCU и почему у неё выводы зовутся D1 и D2 — в статье про ESP8266. Номера взяты из файлов pins_arduino.h ядер 1.8.8 и 3.1.2. Если к той же шине подключён LCD 1602 или датчик — ничего не меняется, у каждого свой адрес.
Адрес 0x3C и почему фирменный пример не работает
Почти все модули 0.96″ сидят на адресе 0x3C. На обратной стороне есть резистор или перемычка, которой адрес меняют на 0x3D — но с завода она стоит на 0x3C. Иногда прямо на плате напечатано «0x78»: это тот же 0x3C, только записанный со сдвигом на бит, как его видит сам контроллер; в код пишите 0x3C. И вот самая частая история первого запуска.
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address;
///< 0x3D for 128x64, 0x3C for 128x32
...
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}I2C scanner
Found 0x3C
Адрес 0x3D бывает только после перепайки перемычки
или резистора на обратной стороне платы.Человек открывает пример из библиотеки Adafruit, ssd1306_128x64_i2c, загружает — и видит чёрный экран. В примере стоит #define SCREEN_ADDRESS 0x3D, потому что Adafruit ориентируется на свои фирменные модули. Замените на 0x3C — и появится заставка. Мы это взяли прямо из файла примера версии 2.5.17; в более старых версиях цифра была та же. Та же ловушка прячется и без #define: вызов begin(SSD1306_SWITCHCAPVCC) без второго аргумента для экрана 128×64 подставит 0x3D сам (так написано в коде библиотеки). Всегда указывайте адрес явно.
Второй слой той же ловушки — в исходниках begin(). Эта функция не спрашивает у дисплея, есть ли он на шине: она выделяет память под буфер, шлёт команды настройки и возвращает «успех». false она возвращает в одном случае — если malloc не смог выделить 1 024 байта. Поэтому проверка if (!display.begin(…)) ловит не отсутствие экрана, а нехватку памяти, и надпись «SSD1306 allocation failed» значит именно это.
Чтобы узнать адрес наверняка, нужен сканер I2C — тот же, что для LCD: он опрашивает все адреса и печатает, кто отозвался. Код и разбор — в статье про LCD 1602 по I2C; в Trema IDE сканер лежит в примерах, раздел «Полезное».
Три библиотеки и сколько памяти берёт каждая
Для SSD1306 в нашем каталоге десятки библиотек, но живых варианта три. Мы поставили каждую из каталога libraries.trema.ru и собрали один и тот же скетч «привет» для Arduino Uno — вот что вышло.
| Библиотека | Флеш, байт из 32 256 (у Nano — из 30 720) | ОЗУ, байт из 2 048 | Русские буквы | Что надо знать |
|---|---|---|---|---|
| Adafruit SSD1306 2.5.17 + GFX 1.12.6 + BusIO 1.17.4 | 14 078 (43 %) | 569 (27 %) + 1 024 при запуске | нет: русские буквы выйдут мусором | Больше всего примеров в интернете. Буфер берётся командой malloc в begin() и в отчёте компилятора не виден. |
| U8g2 2.36.19, полный буфер (_F_) | 10 730 (33 %) | 1 572 (76 %) | 22 шрифта _t_cyrillic | Сотни шрифтов, все контроллеры монохромных экранов. Архив 14 МБ — самая тяжёлая установка. |
| U8g2, постранично (_1_) | 10 756 (33 %) | 676 (33 %) | те же шрифты | Тот же код, но кадр рисуется за восемь проходов; буфер — одна полоска в 128 байт. Лучший выбор для Uno с датчиками. |
| GyverOLED 1.6.4, с буфером | 5 530 (17 %) | 1 327 (64 %) | да, включая строчную ё | Самая лёгкая по флешу: в 2,5 раза меньше Adafruit. Один шрифт 5×7, но с русскими буквами (заглавная Ё печатается как Е); масштаб текста setScale(1…4). |
| iarduino_OLED_txt 1.2.5 (текст и числа) | 7 664 (23 %) | 325 (15 %) | да, шрифты с кириллицей | Русская библиотека под модули Trema: буфера кадра нет вовсе, поэтому ОЗУ почти свободно. Только текст и числа — ни линий, ни картинок. Понимает UTF-8, CP866 и Windows-1251. |
| iarduino_OLED 1.2.5 (графическая) | 8 118 (25 %) | 1 350 (65 %) | да, те же шрифты | Та же библиотека, но с буфером 1 024 байта: добавляются линии, прямоугольники, круги и картинки. Кадр уходит на экран по update(). |
| GyverOLED, без буфера | 5 524 (17 %) | 303 (14 %) | да | Рисует прямо в дисплей байтами по 8 точек в высоту: текст и битмапы, выровненные по строкам из 8 точек, выходят чисто, а линии, контуры и окружности затирают соседние точки в том же столбике. Зато ОЗУ почти свободно. |
Компилятор видит 569 байт (27 %). Ещё 1 024 библиотека просит при запуске, и в отчёте их нет — а получит их, только если свободно было не меньше ≈1 200.
Честные 1 572 байта (76 %) — буфер объявлен заранее, компилятор его показывает.
676 байт (33 %): вместо целого кадра хранится одна полоска в 128 байт, кадр рисуется за 8 проходов.
1 327 байт (64 %). Зато флеша всего 5 530 байт — в два с половиной раза меньше, чем у Adafruit.
303 байта (14 %): текст и фигуры уходят сразу в дисплей, но читать экран обратно нельзя.
Главное, что стоит вынести из этой картинки: буфер кадра — это 1 024 байта, и он есть у всех, просто библиотеки берут его по-разному. U8g2 в полном режиме и GyverOLED объявляют его заранее, и компилятор честно показывает 76 % и 64 % — при 76 % он ещё и напишет «Недостаточно памяти, программа может работать нестабильно»: это предупреждение, прошивка загрузится, но это сигнал перейти на постраничный режим. Adafruit берёт его командой malloc в момент запуска, и компилятор о нём не знает: в отчёте 27 %, а по факту те же 78 %. Мы проверили на скетче с массивом из 300 чисел: отчёт сборки говорит «59 %, свободно 829 байт», сборка зелёная, а при запуске begin() попросит 1 024 — и получит отказ. Экран чёрный, в мониторе «allocation failed», и ни одной ошибки при компиляции. Причём мало, чтобы свободных было ровно тысяча: по документации avr-libc malloc держит запас в 128 байт до стека и два байта тратит на заголовок, да и самому стеку нужно место — на практике буфер влезает, когда отчёт показывает не меньше ≈1 200 свободных, то есть статика не больше ≈40 %.
Для Arduino Uno и Nano отсюда простой совет: если экран — не единственное, что делает плата, берите U8g2 в постраничном режиме (676 байт) или GyverOLED без буфера (303 байта). На Mega 2560 с её 8 КБ и на ESP8266 с 80 КБ всё это не имеет значения: на Mega Adafruit вместе с буфером берёт 1 593 байта из 8 192 (19 %; компилятор покажет 569, то есть 6 %), на ESP8266 — около 1,7 КБ из 80 (2 %; в отчёте будет 35 %, но это само ядро ESP8266 занимает 28 КБ на любом скетче) — мы собрали и для них. Подробнее про то, какие бывают памяти и куда деваются байты, — в статье «Память Arduino».
Adafruit_GFX.h: No such file or directory или Adafruit_I2CDevice.h: No such file — это они. Любопытно, что строка #include <Adafruit_GFX.h> в самом скетче не обязательна: мы собрали без неё, и всё сошлось, потому что заголовок SSD1306 подключает её сам.Если экрана ещё нет. В магазине, для модулей которого мы и делаем среду, лежит ровно такой: OLED-экран 128×64 / 0,96″ (Trema-модуль) — артикул 830, 594 ₽, контроллер SSD1306, белое свечение, питание 3,3–5 В, плата 30×30 мм. Два его отличия от безымянных модулей стоят упоминания: адрес переключается переключателем на обороте (0x3C или 0x3D — то есть два экрана на одной шине заводятся без пайки), и к нему идут две русские библиотеки с готовыми шрифтами кириллицы — мы их измерили и внесли в таблицу выше.
Про эти две библиотеки отдельно, потому что в списке выше они выглядят выгоднее всех для Arduino Uno. iarduino_OLED_txt вообще не держит буфер кадра: текст уходит прямо в экран, и в оперативной памяти остаётся 1 723 байта из 2 048 — больше, чем у любой другой библиотеки с русским текстом. Платой служит флеш: русские шрифты лежат в нём, и «привет» весит 7 664 байта (со вторым шрифтом 12×16 — 11 980). iarduino_OLED — та же библиотека с буфером и графикой: 8 118 байт флеша и 1 350 ОЗУ. Обе есть в нашем каталоге, ставятся оттуда же.
Первый скетч: Adafruit
Начнём с самой распространённой библиотеки — под неё написано больше всего чужих примеров, и её стоит понимать, даже если потом перейдёте на другую.
// Первый скетч на библиотеке Adafruit: текст двух размеров.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// 128×64 точки, шина Wire, вывода сброса нет (-1).
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void setup() {
Serial.begin(9600);
// Адрес 0x3C — у почти всех модулей 0.96". В фирменном примере стоит
// 0x3D, и с ним экран останется чёрным.
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed"); // не хватило ОЗУ под буфер
for (;;);
}
display.clearDisplay();
display.setTextSize(1); // 6×8 точек на знак: 21 знак в строке
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Hello, Arduino!");
display.setTextSize(2); // 12×16: 10 знаков в строке
display.println("OLED");
display.display(); // без этой строки на экране ничего
}
void loop() {
}
14 078 байт флеша и 569 байт ОЗУ по отчёту (плюс тысяча при запуске). Три вещи, которые ловят всех. Первая — адрес 0x3C в begin(), уже обсудили. Вторая — display() в конце: всё рисование идёт в буфер, и пока не вызвать эту команду, на стекле ничего не меняется. Третья — встроенный шрифт 5×7 точек с шагом 6: при setTextSize(1) в строку помещается 21 знак, при размере 2 — 10, и кириллицы в нём нет: таблица на 256 знаков, и каждый байт русской буквы попадёт на чужой символ — рамки, чёрточки, греческие буквы. Вместо «Привет» выйдет двенадцать знаков мусора.
Версии 128×32 — тот же скетч с display(128, 32, …). Если перепутать высоту, картинка пойдёт «через строку» — сжатая или растянутая, — это не брак экрана.
U8g2: постраничный режим для Uno
U8g2 — самая большая библиотека для монохромных экранов: сотни шрифтов и почти любой контроллер. Платой за это служит архив в 14 МБ — ставится дольше остальных. Конструкторов в ней почти пять тысяч (для одного SSD1306 128×64 — девяносто), поэтому имя читается как формула: U8G2_SSD1306_128X64_NONAME_1_HW_I2C — контроллер, размер, тип платы, режим буфера, способ подключения. Режимов три: _F_ — полный кадр в памяти, _1_ — одна полоска в 128 байт, _2_ — две. Для Uno берите _1_.
// U8g2 в постраничном режиме: 676 байт ОЗУ вместо 1 572.
#include <Wire.h>
#include <U8g2lib.h>
// _1_ в имени — постраничный буфер. Замените на _F_ — будет полный.
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
void setup() {
u8g2.begin();
}
void loop() {
u8g2.firstPage();
do { // этот блок выполнится 8 раз
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0, 24, "Hello, Arduino!");
} while (u8g2.nextPage());
delay(1000);
}
Цикл do … while (nextPage()) — это и есть постраничный режим: библиотека рисует кадр восемь раз, каждый раз только полоску в 8 строк, и шлёт её в дисплей. Код внутри цикла должен рисовать одно и то же все восемь проходов — поэтому считывать датчик надо до firstPage(), а не внутри. Мы измерили цену: 10 756 байт флеша, 676 байт ОЗУ против 1 572 у _F_ при том же флеше. Кадр обновляется медленнее, но для показаний датчиков и меню это незаметно.
Вот показания аналогового входа крупными цифрами с полоской внизу — скетч, который после замены analogRead на чтение любого датчика становится готовым прибором. Собран: 10 688 байт флеша, 670 байт ОЗУ — крупный цифровой шрифт стоит всего полкилобайта, потому что в нём только цифры и знаки, и вместе с мелким 6×12 это меньше одного шрифта ncenB14 из первого скетча.
// Крупное число с аналогового входа — как будто показания датчика.
#include <Wire.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
void setup() {
u8g2.begin();
}
void loop() {
int value = analogRead(A0);
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_6x12_tr);
u8g2.drawStr(0, 10, "A0 reading");
u8g2.setFont(u8g2_font_logisoso32_tn); // только цифры, 32 точки высотой
u8g2.setCursor(0, 58);
u8g2.print(value);
// Полоска-индикатор вдоль нижнего края:
u8g2.drawFrame(0, 60, 128, 4);
u8g2.drawBox(0, 60, map(value, 0, 1023, 0, 128), 4);
} while (u8g2.nextPage());
delay(100);
}
Русский текст на OLED
В отличие от LCD 1602, здесь никаких ограничений: буква — это просто точки. Нужен только шрифт, в котором эти буквы нарисованы. В U8g2 таких 22, их имена кончаются на _t_cyrillic, а строки надо печатать через print() после enableUTF8Print():
// Русский текст на OLED: шрифт с кириллицей и печать через print().
#include <Wire.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
void setup() {
u8g2.begin();
u8g2.enableUTF8Print(); // понимать русские буквы в строках
}
void loop() {
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_10x20_t_cyrillic); // _t_cyrillic — с кириллицей
u8g2.setCursor(0, 24);
u8g2.print("Привет, мир!");
} while (u8g2.nextPage());
delay(1000);
}
Собрано: 15 764 байта флеша — шрифт 10×20 с кириллицей весит почти 7 КБ против 1,4 КБ у того же шрифта без неё: в нём 387 знаков вместо 95, потому что это не только русский алфавит, а весь блок кириллицы с украинскими, сербскими и казахскими буквами. ОЗУ почти не изменилось — 682 байта против 676: шрифты лежат во флеше. Если нужно компактнее — u8g2_font_6x12_t_cyrillic или u8g2_font_5x8_t_cyrillic. А одну строку можно вывести и без enableUTF8Print() — командой drawUTF8(x, y, "Привет").
Второй путь — GyverOLED: русские буквы, включая строчную ё, у неё в единственном встроенном шрифте, и никаких настроек (одна мелочь из кода: заглавная Ё печатается как Е):
// GyverOLED: русские буквы сразу, 5,5 КБ флеша.
#include <GyverOLED.h>
// OLED_BUFFER — кадр в памяти платы (скетч берёт 1 327 байт ОЗУ, из них 1 024 — буфер),
// OLED_NO_BUFFER — рисовать прямо в дисплей (303 байта).
GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;
void setup() {
oled.init();
oled.clear();
oled.setScale(2); // буквы вдвое крупнее
oled.setCursor(0, 0);
oled.print("Привет!");
oled.setScale(1);
oled.setCursor(0, 4); // строка 4 — это 4-я «страница» по 8 точек
oled.print("GyverOLED, 128x64");
oled.update(); // отправить буфер в дисплей
}
void loop() {
}
5 530 байт флеша — в два с половиной раза меньше, чем у Adafruit, и 1 327 байт ОЗУ с буфером или 303 без (второй параметр шаблона OLED_NO_BUFFER). Масштаб setScale(2) делает буквы 12×16, и это простейший способ получить крупные цифры термометра. У библиотеки русский автор и русская документация — для кружка это аргумент.
И третий путь — русские библиотеки iarduino_OLED_txt и iarduino_OLED. Текст в них печатается функцией print(строка, столбец, строка_экрана), а шрифты с кириллицей уже внутри: SmallFontRus 6×8 и MediumFontRus 12×16. Скетч ниже мы собрали: 7 664 байта флеша и всего 325 байт ОЗУ.
// Русский текст библиотекой iarduino_OLED_txt: буфера кадра нет,
// в оперативной памяти остаётся 1 723 байта из 2 048.
#include <Wire.h>
#include <iarduino_OLED_txt.h>
// Адрес 0x3C или 0x3D — у модуля Trema он выбирается переключателем.
iarduino_OLED_txt oled(0x3C);
void setup() {
oled.begin(&Wire);
oled.setFont(SmallFontRus); // шрифт 6x8 с кириллицей
oled.print("Привет, мир!", OLED_C, 2); // OLED_C — по центру, строка 2
}
void loop() {
}
Если русский текст выходит «кракозябрами», у этих библиотек есть переключатель кодировки: setCoding(TXT_UTF8) — как сохраняет современная Arduino IDE и Trema IDE, TXT_CP866 и TXT_WIN1251 — для старых файлов. По умолчанию UTF-8, так что обычно трогать не нужно.
Яркость и выгорание
Подстроечника у OLED нет, но яркость регулируется из кода: у Adafruit — display.dim(true) или команда SSD1306_SETCONTRAST, у U8g2 и GyverOLED — setContrast(0…255). И одно свойство, о котором редко пишут: точки OLED изнашиваются от работы, и надпись, которая месяцами горит на одном месте, оставляет след — это заметно на приборах, включённых круглые сутки. Для таких гасите экран, когда на него не смотрят, или сдвигайте картинку на пару точек время от времени. Для кружкового проекта это не важно.
SSD1306 или SH1106: почему картинка съехала
Экраны 1.3″ и часть 0.96″ собраны на контроллере SH1106. Он почти совместим с SSD1306, но у него матрица 132 столбца, а не 128, и нет команды «горизонтальная адресация», которой пользуются библиотеки для SSD1306. В результате код для SSD1306 на SH1106 рисует, но со сдвигом на два столбца и полосой мусора у края — или не рисует вовсе.
- U8g2: замените в конструкторе
SSD1306наSH1106— всё остальное то же самое. - GyverOLED: первый параметр шаблона
SSH1106_128x64(именно с двумя S — так в библиотеке), и только вместе сOLED_BUFFER: без буфера SH1106 она не поддерживает. - Adafruit: нужна отдельная библиотека Adafruit SH110X с классом
Adafruit_SH1106G; она тоже в каталоге — и, в отличие от SSD1306, еёbegin()честно возвращает false, если экрана нет на шине.
Определить контроллер по внешнему виду нельзя; продавец обычно пишет его в названии. Если не написано, а экран 1.3″ — скорее всего SH1106; 0.96″ — скорее всего SSD1306. Проверка простая: загрузить скетч для одного и посмотреть, ровная ли картинка.
Ошибки и странности, которые мы воспроизвели или разобрали
| Что видно | Что это | Что делать |
|---|---|---|
| Чёрный экран после примера Adafruit | В примере адрес 0x3D, у модуля 0x3C | Исправить SCREEN_ADDRESS на 0x3C. |
SSD1306 allocation failed в мониторе | Не хватило ОЗУ под буфер 1 024 байта | Строки во флеш через F("…"), меньше массивов, или U8g2 _1_. Компилятор про это не предупредит. |
Adafruit_SSD1306.h: No such file or directory | Библиотека не установлена | Поставить из каталога — вместе с ней встанут GFX и BusIO. Trema IDE предложит её сама. |
U8g2lib.h: No such file or directory | Не установлена U8g2 | Поставить «U8g2» — архив 14 МБ, это нормально. |
| Рисую, а на экране ничего | Не вызван display() (Adafruit), sendBuffer() (U8g2 _F_) или update() (GyverOLED с буфером); в постраничном режиме U8g2 — нет цикла firstPage()/nextPage() | Добавить вызов после рисования. |
| Картинка через строку — сжатая или растянутая | Высота 32 вместо 64 или наоборот | Исправить число в конструкторе. |
| Сдвиг на два столбца и мусор у края | Контроллер SH1106, код для SSD1306 | Сменить конструктор на SH1106. |
| Русские буквы — мусор (Adafruit) или пусто (U8g2) | Шрифт без кириллицы | U8g2: шрифт _t_cyrillic + enableUTF8Print(); или GyverOLED. |
Сканер пишет No devices | Экран не виден на шине | Провода SDA/SCL местами, VCC и GND местами (порядок выводов на модулях разный), нет земли. |
OLED в Trema IDE
Мы делаем русскую среду для школ и кружков; OLED — одна из деталей, с которыми в ней знакомятся с окном «Нужна библиотека».
- Библиотека ставится из окна ошибки. Напишите
#include <Adafruit_SSD1306.h>или<U8g2lib.h>, нажмите «Проверить» — и программа предложит нужную библиотеку из нашего каталога, а зависимости Adafruit доставит сама. Каталог — российский сервер libraries.trema.ru; U8g2 со всеми её 14 МБ качается оттуда же. - Сканер адресов — в примерах, раздел «Полезное», скетч I2C_Scanner с русскими комментариями.
- Ошибки объясняются по-русски. «Не хватает библиотеки: Adafruit_SSD1306.h» — карточка с кнопкой. Честно о том, чего нет: «SSD1306 allocation failed» — это сообщение из монитора порта во время работы, а не из компилятора, и карточки на него нет; подсказать, что 1 024 байта буфера не видны в отчёте сборки, программа пока тоже не умеет. Мы это знаем и думаем, как показать.
Живой дисплей к этой статье мы не подключали: все числа — из сборок, все ловушки — из исходников библиотек. Если у вас получается иначе — напишите, проверим.
Как подключить OLED 0.96 дюйма к Arduino?
У модуля четыре вывода: GND к GND, VCC к 5V (или 3.3V — на модуле стоит свой стабилизатор), SDA к A4, SCL к A5 на Uno и Nano. На Mega это выводы 20 и 21, на NodeMCU — D2 и D1. Внимание: у некоторых модулей порядок выводов VCC–GND, а не GND–VCC, — читайте подписи, а не положение.
Какой адрес у OLED SSD1306 — 0x3C или 0x3D?
У почти всех модулей 0.96 дюйма — 0x3C. Адрес 0x3D получается только после перепайки резистора на обратной стороне. Фирменный пример Adafruit для 128×64 задаёт 0x3D, и из-за этого после его загрузки экран остаётся чёрным — замените строку SCREEN_ADDRESS на 0x3C.
Какую библиотеку выбрать для OLED SSD1306: Adafruit, U8g2 или GyverOLED?
Adafruit SSD1306 с Adafruit GFX — самая распространённая, по ней больше всего примеров, но она тяжёлая для Uno: 14 КБ флеша и почти 1,6 КБ из 2 КБ оперативной памяти с учётом буфера. U8g2 — самая богатая шрифтами, включая 22 кириллических, и умеет постраничный режим, который берёт всего 676 байт ОЗУ. GyverOLED — самая лёгкая по флешу (5,5 КБ) и с русскими буквами из коробки. Все три есть в каталоге Trema IDE.
Почему в мониторе порта написано SSD1306 allocation failed?
Это не про провода и не про адрес: библиотека Adafruit не смогла выделить 1 024 байта под буфер кадра в оперативной памяти. Компилятор этот буфер не показывает — отчёт может говорить 59 % занято, а при запуске места уже не хватит: буфер влезает, когда свободно не меньше примерно 1 200 байт. Освободите ОЗУ: вынесите строки во флеш через F(), уменьшите массивы или перейдите на U8g2 в постраничном режиме.
Почему OLED не показывает ничего, хотя скетч загрузился?
По порядку: адрес (0x3C, а не 0x3D), провода SDA и SCL не перепутаны, питание есть. Запустите сканер I2C — если он пишет No devices, дело в проводах; если находит 0x3C, а экран чёрный, — в адресе в скетче. У Adafruit функция begin() ответ дисплея не проверяет и вернёт успех даже при неверном адресе.
Как вывести русский текст на OLED?
В U8g2 выберите шрифт с суффиксом _t_cyrillic (например u8g2_font_10x20_t_cyrillic), включите enableUTF8Print() и печатайте через print() — мы собрали такой скетч, 15 764 байта флеша. В GyverOLED русские буквы работают сразу, в том числе ё. В Adafruit GFX встроенный шрифт кириллицу не содержит.
В чём разница между SSD1306 и SH1106?
Это два разных контроллера, которые ставят в одинаковые корпуса. SH1106 обычно стоит в экранах 1,3 дюйма, SSD1306 — в 0,96. Если на SH1106 запустить код для SSD1306, картинка будет сдвинута и с мусором по краям. У U8g2 и GyverOLED есть отдельные конструкторы для SH1106, у Adafruit — отдельная библиотека Adafruit SH110X.
Почему экран 128×64 показывает только половину или через строку?
В конструкторе указана высота 32 вместо 64 или наоборот: в обоих случаях картинка идёт через строку — сжатая вдвое или растянутая на весь экран с пропусками. Проверьте высоту в конструкторе Adafruit и имя класса U8g2.
Подключите OLED в Trema IDE
Библиотека ставится из окна ошибки вместе с зависимостями, сканер адресов в примерах, ошибки объясняются по-русски. Дома бесплатно: через неделю попросит бесплатную регистрацию по почте — и всё. Дальше по теме: LCD 1602 по I2C, память Arduino, как ставить библиотеки.
