Подключение графического OLED дисплея к ESP32

Подключение графического OLED дисплея к ESP32

Хотите добавить стильную графику в свои проекты на ESP32 или отображать IP-адрес устройства без открытия Serial Monitor? Тогда пришло время зажечь OLED-экран. Эти маленькие дисплеи невероятно лёгкие, очень тонкие и создают более чёткие и яркие изображения, которые буквально выпрыгивают с экрана.

В этом практическом руководстве мы расскажем вам, как подключить OLED дисплей к ESP32. Вы узнаете, как отображать текст, рисовать простые фигуры и даже показывать собственные изображения. А чтобы было ещё интереснее, мы добавили инструмент для конвертации любого изображения в код, готовый для отображения!

Давайте приступим и оживим ваши проекты — пиксель за пикселем!

Обзор OLED дисплейного модуля

OLED дисплеи доступны в широком ассортименте, предоставляя вам множество вариантов в зависимости от потребностей вашего проекта. Они доступны в различных размерах, таких как 128×64 пикселей или 128×32 пикселя, и вы можете выбрать из множества цветов: белый, синий или даже интересные двухцветные версии. Эти дисплеи также поддерживают различные способы связи с вашим ESP32 — одни используют I2C, другие — SPI.

В этом руководстве мы будем работать с 0.96-дюймовым I2C OLED дисплеем 128×64. Но если ваш дисплей имеет другой размер или цвет, не беспокойтесь. Основные принципы, которые мы рассмотрим, по-прежнему применимы, и шаги по его настройке будут очень похожими.

I2C OLED дисплей 128x64 синий

Независимо от того, какой размер, цвет или способ связи вы выберете, все эти OLED дисплеи работают на одной и той же маленькой, но мощной микросхеме — драйвере OLED SSD1306. Эта микросхема выступает в роли «мозга» дисплея. Она отвечает за рисование всего, что вы видите на экране, сохраняя данные изображения в собственной памяти (буферизация RAM). Благодаря такому продуманному дизайну вашему микроконтроллеру не нужно постоянно обновлять экран — он может сосредоточиться на других задачах.

Питание

В отличие от традиционных LCD дисплеев, OLED дисплеям не нужна подсветка, потому что пиксели OLED сами излучают свет. Это обеспечивает OLED высокую контрастность, отличные углы обзора и по-настоящему глубокий чёрный цвет. Поскольку им не нужна подсветка, OLED дисплеи потребляют меньше энергии — в среднем около 20 мА, что делает их идеальными для проектов с батарейным питанием.

OLED дисплеи работают с напряжением от 3.3В до 5В. Это означает, что вы можете легко подключить свой OLED дисплей к микроконтроллеру с напряжением 3.3В или 5В без каких-либо проблем.

Карта памяти OLED

Чтобы управлять тем, что отображается на вашем OLED дисплее, нужно понимать, как организована память дисплея.

Независимо от размера вашего OLED дисплея, драйвер SSD1306 внутри имеет 1 КБ (килобайт) памяти, известной как Graphic Display Data RAM (GDDRAM). Эта память хранит шаблон пикселей, который отображается на экране. Каждый бит в этой памяти управляет одним пикселем.

Вот как организован этот 1 КБ памяти:

  • Память разделена на 8 страниц (пронумерованных от 0 до 7)

  • Каждая страница содержит 128 столбцов (также называемых сегментами)

  • Каждый столбец содержит 8 вертикальных пикселей на экране

Итого математика выглядит так:

8 страниц × 128 столбцов × 8 бит = 8 192 бита = 1 024 байта = 1 КБ памяти

Весь 1 КБ памяти, включая страницы, сегменты и данные, показан ниже.

Карта памяти RAM OLED дисплея 128x64 на 1 КБ

Примечание

Помните, что каждый OLED модуль содержит 1 КБ RAM, независимо от его размера. Модуль OLED 128×64 отображает всё содержимое этого 1 КБ RAM (все 8 страниц), тогда как модуль OLED 128×32 показывает только половину RAM (первые 4 страницы).

Распиновка

Прежде чем мы перейдём к подключению и примерам кода, давайте рассмотрим подробнее распиновку I2C OLED дисплейного модуля.

Распиновка I2C OLED дисплея

GND — вывод заземления.

VCC — вывод питания дисплея. Вы можете подключить его к выводу 3.3В или 5В на вашем микроконтроллере.

SCL — вывод тактового сигнала для интерфейса I2C.

SDA — вывод данных для интерфейса I2C.

Подключение OLED дисплейного модуля к ESP32

Давайте подключим OLED дисплей к ESP32.

Подключение простое. Сначала подключите вывод VCC дисплея к выходу 3.3В ESP32, а вывод GND — к земле.

Далее нам нужно подключить выводы, используемые для I2C связи. Подключите вывод SCL на дисплее к D22 на ESP32, а вывод SDA — к D21 на ESP32.

Вот краткая справочная таблица подключения выводов:

OLED дисплей

ESP32

VCC

3.3V

GND

GND

SCL

D22

SDA

D21

Эта схема показывает, как именно всё подключить:

Схема подключения OLED дисплейного модуля к ESP32

Установка библиотеки

Контроллер SSD1306, используемый в OLED дисплеях, очень гибкий, но может быть довольно сложным при прямом использовании. Чтобы правильно с ним работать, обычно необходимо хорошее понимание адресации памяти, что может быть непросто — особенно для начинающих.

К счастью, нам не нужно обо всём этом беспокоиться. Библиотека Adafruit SSD1306 была создана, чтобы значительно упростить задачу. Эта библиотека берёт на себя всю сложную работу за кулисами, так что вы можете управлять OLED дисплеем с помощью простых и понятных команд.

Чтобы установить библиотеку:

  1. Сначала откройте программу Arduino IDE. Затем нажмите на иконку Library Manager на левой боковой панели.

  2. Введите «adafruit ssd1306» в поле поиска для фильтрации результатов.

  3. Найдите Adafruit SSD1306 Library от Adafruit.

  4. Нажмите кнопку Install, чтобы добавить её в Arduino IDE.

Установка библиотеки Adafruit SSD1306 для монохромного OLED дисплея

Поскольку библиотека Adafruit SSD1306 зависит от других библиотек, вам будет предложено установить её зависимости, которые включают библиотеку Adafruit Bus IO и библиотеку Adafruit GFX.

Когда появится это сообщение, просто нажмите INSTALL ALL, чтобы убедиться, что всё настроено правильно.

Установка библиотек Adafruit BusIO и GFX

Пример кода ESP32 1 — Отображение текста

Теперь начинается самое интересное — давайте начнём отображать крутые вещи на OLED-экране!

Скетч ниже показывает, как:

  • Отображать простой текст

  • Отображать инвертированный текст

  • Отображать числа

  • Отображать числа с указанием основания (Hex, Dec)

  • Отображать ASCII символы

  • Прокручивать текст горизонтально и вертикально

  • Прокручивать часть дисплея

Как только вы разберётесь в этом примере, вы будете на верном пути к созданию более креативных и продвинутых проектов с вашим OLED дисплеем.

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

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for SSD1306 display connected using I2C
#define OLED_RESET -1  // Reset pin
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

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

  // initialize the OLED object
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }

  // Clear the buffer.
  display.clearDisplay();

  // Display Text
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 28);
  display.println("Hello world!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Display Inverted Text
  display.setTextColor(BLACK, WHITE);  // 'inverted' text
  display.setCursor(0, 28);
  display.println("Hello world!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Changing Font Size
  display.setTextColor(WHITE);
  display.setCursor(0, 24);
  display.setTextSize(2);
  display.println("Hello!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Display Numbers
  display.setTextSize(1);
  display.setCursor(0, 28);
  display.println(123456789);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Specifying Base For Numbers
  display.setCursor(0, 28);
  display.print("0x");
  display.print(0xFF, HEX);
  display.print("(HEX) = ");
  display.print(0xFF, DEC);
  display.println("(DEC)");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Display ASCII Characters
  display.setCursor(0, 24);
  display.setTextSize(2);
  display.write(3);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Scroll full screen
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.println("Full");
  display.println("screen");
  display.println("scrolling!");
  display.display();
  display.startscrollright(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  display.clearDisplay();

  // Scroll part of the screen
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.println("Scroll");
  display.println("some part");
  display.println("of the screen.");
  display.display();
  display.startscrollright(0x00, 0x00);
}

void loop() {
}

Вот как выглядит результат.

Результат работы примера 1 OLED дисплея

Объяснение кода

Скетч начинается с подключения четырёх библиотек: SPI.h, Wire.h, Adafruit_GFX.h и Adafruit_SSD1306.h. Эти библиотеки позволяют ESP32 взаимодействовать с OLED дисплеем. Хотя мы используем I2C (для которого библиотека SPI не нужна), мы всё равно подключаем SPI.h, чтобы код компилировался без ошибок.

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

Далее мы определяем ширину и высоту экрана в пикселях. Большинство распространённых OLED дисплеев имеют ширину 128 пикселей и высоту 64 пикселя, поэтому мы устанавливаем SCREEN_WIDTH равным 128 и SCREEN_HEIGHT равным 64.

Затем мы создаём объект display с помощью библиотеки Adafruit_SSD1306. Мы указываем размер нашего экрана — 128 пикселей в ширину и 64 пикселя в высоту — и сообщаем, что используем I2C. Поскольку наш OLED модуль не имеет вывода сброса, мы передаём -1, чтобы показать, что мы его не используем.

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for SSD1306 display connected using I2C
#define OLED_RESET     -1 // Reset pin
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Внутри функции setup() мы сначала инициализируем последовательную связь для вывода сообщений в Serial Monitor для отладки.

Затем мы вызываем display.begin() для начала связи с OLED дисплеем. Первый аргумент включает внутреннюю схему зарядки (charge pump), которая помогает питать экран, а второй аргумент задаёт I2C адрес (I2C адрес экрана обычно 0x3C, но некоторые дисплеи используют 0x3D, поэтому при необходимости его можно изменить). Если дисплей не запускается корректно, мы показываем сообщение об ошибке и останавливаем программу.

Serial.begin(9600);

// initialize the OLED object
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
  Serial.println(F("SSD1306 allocation failed"));
  for (;;)
    ;  // Don't proceed, loop forever
}

Когда дисплей готов, мы очищаем экран с помощью display.clearDisplay(). Это гарантирует, что мы работаем с чистым экраном.

// Clear the buffer.
display.clearDisplay();

Отображение простого текста (Hello World)

Отображение текста на OLED дисплейном модуле
// Display Text
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Чтобы показать текст на OLED-экране, мы сначала задаём размер текста с помощью функции setTextSize(). Эта функция принимает число, где 1 — наименьший размер, а большие числа делают текст крупнее.

Далее мы выбираем цвет текста с помощью setTextColor(). Используйте WHITE для тёмного фона и BLACK для светлого фона. Поскольку наш OLED-экран имеет тёмный фон, мы используем WHITE, чтобы текст был хорошо виден.

Прежде чем что-то печатать, мы указываем дисплею, где начать запись, устанавливая позицию курсора с помощью setCursor(x, y). Значение x определяет, насколько далеко от левого края начинается текст, а y — насколько далеко от верхнего. Верхний левый угол — это позиция (0, 0).

Чтобы фактически отобразить сообщение на экране, мы используем функции print(" ") или println(" "). Они работают точно так же, как вывод в Serial Monitor. Помните, что println() переводит курсор на следующую строку после печати, тогда как print() оставляет его на той же строке.

Наконец, мы используем display() для обновления экрана и отображения всего, что мы подготовили в коде. Экран не обновляется, пока вы не вызовете эту функцию.

Отображение инвертированного текста

Отображение инвертированного текста на OLED дисплейном модуле
// Display Inverted Text
display.clearDisplay();
display.setTextColor(BLACK, WHITE); // 'inverted' text
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Если вы хотите отобразить текст с перевёрнутыми цветами (чёрный текст на белом фоне), вы можете сделать это, используя функцию setTextColor() снова, но на этот раз с двумя значениями. Когда мы используем setTextColor(BLACK, WHITE), мы указываем дисплею рисовать чёрные буквы на белом прямоугольнике. Причина, по которой мы теперь можем передать два значения, связана с так называемой «перегрузкой функций» — это просто означает, что одна и та же функция может вести себя по-разному в зависимости от того, сколько значений мы ей передаём.

Масштабирование размера шрифта

Изменение размера шрифта на OLED дисплейном модуле
// Changing Font Size
display.clearDisplay();
display.setTextColor(WHITE);
display.setCursor(0,24);
display.setTextSize(2);
display.println("Hello!");
display.display();
delay(2000);

Ранее в скетче мы использовали функцию setTextSize() и передали число 1 для установки размера шрифта по умолчанию. Но вы не ограничены только этим — вы можете сделать текст крупнее, передав большее число.

Например, вызов setTextSize(2) сделает текст вдвое больше размера 1. Вы можете использовать любое целое число (например, 2, 3, 4…) в зависимости от того, насколько крупным вы хотите видеть текст.

Обратите внимание, что каждый символ на OLED-экране рисуется в прямоугольной области с соотношением сторон 7:10. Итак:

  • Размер шрифта 1 рисует каждый символ в 7×10 пикселей

  • Размер шрифта 2 рисует каждый символ в 14×20 пикселей

  • Размер шрифта 3 будет 21×30 пикселей, и так далее

Отображение чисел

Отображение чисел на OLED дисплейном модуле
// Display Numbers
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,28);
display.println(123456789);
display.display();
delay(2000);

Так же, как и с текстом, вы можете использовать print() или println() для отображения чисел на экране. Эти функции принимают 32-битные беззнаковые целые значения, что означает, что вы можете отображать числа в диапазоне от 0 до 4 294 967 295.

Указание основания для чисел

Отображение HEX, десятичных, восьмеричных, двоичных чисел на OLED дисплейном модуле
// Specifying Base For Numbers
display.clearDisplay();
display.setCursor(0,28);
display.print("0x"); display.print(0xFF, HEX);
display.print("(HEX) = ");
display.print(0xFF, DEC);
display.println("(DEC)");
display.display();
delay(2000);

Иногда вам может понадобиться показать число в другом формате, например, двоичном (основание 2), восьмеричном (основание 8), десятичном (основание 10) или шестнадцатеричном (основание 16). Функции print() и println() позволяют это сделать, добавив второй параметр, который указывает, какой формат использовать. Например, print(78, BIN) покажет 1001110, а print(78, HEX) покажет 4E.

Этот второй параметр также можно использовать для десятичных чисел, чтобы контролировать, сколько цифр появится после запятой. Например, print(1.23456, 2) покажет 1.23, а print(1.23456, 4) покажет 1.2346.

Отображение ASCII символов

Отображение ASCII символов на OLED дисплейном модуле
// Display ASCII Characters
display.clearDisplay();
display.setCursor(0,24);
display.setTextSize(2);
display.write(3);
display.display();
delay(2000);

Вы также можете отображать специальные символы с помощью функции write(). Она работает немного иначе, чем print() — вместо обычного текста она отправляет число, представляющее ASCII символ, непосредственно на экран. Например, write(3) отобразит символ сердечка. Это забавный способ добавить иконки на ваш дисплей!

Прокрутка всего экрана

Прокрутка всего экрана на OLED дисплейном модуле
// Scroll full screen
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1);
display.println("Full");
display.println("screen");
display.println("scrolling!");
display.display();
display.startscrollright(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();

Если вы хотите, чтобы ваше сообщение двигалось по экрану, вы можете заставить его прокручиваться. Сначала вы отображаете сообщение обычным образом, используя уже изученные шаги. Затем вы используете startscrollright() или startscrollleft(), чтобы текст двигался в этом направлении. Вы также можете использовать startscrolldiagright() или startscrolldiagleft() для диагональной прокрутки.

Каждая из этих функций требует два параметра: начальную страницу и конечную страницу. Для получения дополнительной информации о страницах обратитесь к разделу Карта памяти OLED. Поскольку дисплей имеет восемь страниц, пронумерованных от 0 до 7, вы можете прокрутить весь экран, прокручивая все страницы. Для этого просто передайте параметры 0x00 (для начальной страницы) и 0x07 (для конечной страницы).

Когда вы хотите остановить прокрутку, просто используйте stopscroll().

Прокрутка определённой части

Прокрутка части экрана на OLED дисплейном модуле
// Scroll part of the screen
display.setCursor(0,0);
display.setTextSize(1);
display.println("Scroll");
display.println("some part");
display.println("of the screen.");
display.display();
display.startscrollright(0x00, 0x00);

Иногда вам может не понадобиться прокручивать весь экран, а только его часть. Вы можете сделать это, указав правильные значения начальной и конечной страниц в функциях прокрутки. Например, если вы передадите 0x00 для обеих — начальной и конечной страницы, это прокрутит только первую страницу дисплея.

Пример кода ESP32 2 — Базовые рисунки

Этот пример скетча показывает, как рисовать простые фигуры, такие как прямоугольники, круги и треугольники, на OLED дисплее.

Загрузите скетч на ваш Arduino, чтобы увидеть, как он работает, прежде чем мы объясним его подробно.

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

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for SSD1306 display connected using I2C
#define OLED_RESET -1  // Reset pin
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

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

  // initialize the OLED object
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }

  // Clear the buffer.
  display.clearDisplay();

  // Draw Rectangle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Rectangle");
  display.drawRect(0, 15, 60, 40, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Draw Filled Rectangle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Filled Rectangle");
  display.fillRect(0, 15, 60, 40, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Draw Round Rectangle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Round Rectangle");
  display.drawRoundRect(0, 15, 60, 40, 8, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Draw Filled Round Rectangle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Filled Round Rectangl");
  display.fillRoundRect(0, 15, 60, 40, 8, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Draw Circle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Circle");
  display.drawCircle(20, 35, 20, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Draw Filled Circle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Filled Circle");
  display.fillCircle(20, 35, 20, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Draw Triangle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Triangle");
  display.drawTriangle(30, 15, 0, 60, 60, 60, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Draw Filled Triangle
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Filled Triangle");
  display.fillTriangle(30, 15, 0, 60, 60, 60, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();
}

void loop() {
}

Вот как выглядит результат.

Результат работы примера 2 OLED дисплея

Вы заметите, что код настройки дисплея точно такой же, как в предыдущем примере. Разница здесь в том, что мы используем новые функции, которые позволяют рисовать фигуры вместо простого отображения текста.

Рисование прямоугольника

Рисование прямоугольника на OLED дисплейном модуле Рисование закрашенного прямоугольника на OLED дисплейном модуле
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Rectangle");
display.drawRect(0, 15, 60, 40, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Rectangle");
display.fillRect(0, 15, 60, 40, WHITE);
display.display();
delay(2000);

Чтобы нарисовать прямоугольник, мы используем функцию drawRect(). Эта функция принимает пять значений: откуда начать рисование на экране (координаты X и Y), ширину и высоту прямоугольника, а также цвет рисования. Эта функция рисует только контур прямоугольника с толщиной границы в 1 пиксель.

Если вы хотите, чтобы прямоугольник был полностью залит, используйте вместо этого fillRect().

Рисование скруглённого прямоугольника

Рисование скруглённого прямоугольника на OLED дисплейном модуле Рисование закрашенного скруглённого прямоугольника на OLED дисплейном модуле
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Round Rectangle");
display.drawRoundRect(0, 15, 60, 40, 8, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Round Rectangl");
display.fillRoundRect(0, 15, 60, 40, 8, WHITE);
display.display();
delay(2000);

Для прямоугольника с закруглёнными углами используйте drawRoundRect(). Так же, как и drawRect(), вы указываете координаты X и Y, ширину и высоту, а также цвет. Но этой функции также нужен дополнительный параметр, который указывает, насколько скруглёнными должны быть углы (радиус скругления).

Опять же, если вы хотите залить скруглённый прямоугольник, используйте fillRoundRect().

Рисование круга

Рисование круга на OLED дисплейном модуле Рисование закрашенного круга на OLED дисплейном модуле
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Circle");
display.drawCircle(20, 35, 20, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Circle");
display.fillCircle(20, 35, 20, WHITE);
display.display();
delay(2000);

Чтобы нарисовать круг, используйте функцию drawCircle(). Здесь, в отличие от прямоугольников, где мы указываем верхний левый угол, мы указываем координаты X и Y центра круга, а также радиус и цвет. Эта функция рисует только контур круга.

Если вы хотите нарисовать сплошной круг, используйте fillCircle() с теми же значениями.

Рисование треугольника

Рисование треугольника на OLED дисплейном модуле Рисование закрашенного треугольника на OLED дисплейном модуле
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Triangle");
display.drawTriangle(30, 15, 0, 60, 60, 60, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Triangle");
display.fillTriangle(30, 15, 0, 60, 60, 60, WHITE);
display.display();
delay(2000);

Чтобы нарисовать треугольник, мы используем функцию drawTriangle(). Эта функция немного отличается, потому что нам нужно указать три точки — каждая точка состоит из координат X и Y. Эти три точки представляют вершины треугольника. Первая точка — верхняя вершина, а две другие — левая и правая вершины, в таком порядке. Эта функция рисует контур треугольника, соединяя три точки прямыми линиями. Вы также передаёте цвет, как и раньше.

Если вы хотите залитый треугольник, используйте fillTriangle() и укажите те же координаты и цвет.

Пример кода ESP32 3 — Отображение изображения

В этом заключительном примере мы научимся отображать изображение на OLED-экране. Это может быть очень полезно, когда вы хотите отобразить такие вещи, как логотипы, иконки, игровые спрайты или даже простую инфографику.

Чтобы отобразить изображение на OLED, вам сначала нужно преобразовать его в формат, понятный OLED — специальный байтовый массив. Этот массив состоит из чисел, представляющих каждый отдельный пиксель изображения.

Чтобы упростить задачу, мы разработали простой инструмент, который помогает превратить ваше изображение в массив, который может использовать OLED дисплей.

Конвертер изображений для OLED

1. Select image

Choose a file

2. Image Settings

x
128

3. Preview

Only images file type are allowed No file selected

4. Output

Как использовать конвертер?

Для начала загрузите изображение, которое вы хотите отобразить на OLED-экране.

Выбор изображения в онлайн-инструменте конвертации image2cpp Bitmap to Data Array

Для этого примера мы выбрали фотографию Мэрилин Монро.

Мэрилин Монро

После загрузки изображения заполните поле Identifier именем, соответствующим вашему изображению. Это имя будет использоваться как заголовок массива в вашем итоговом коде Arduino.

Поскольку наше изображение — Мэрилин Монро, мы ввели «MarilynMonroe» в качестве идентификатора.

Прежде чем двигаться дальше, очень важно убедиться, что ваше изображение соответствует разрешению OLED-экрана 128×64 пикселей. Если ваше изображение больше, оно может неправильно отображаться на экране.

Вы увидите текущий размер вашего изображения в разделе «Image size» в настройках изображения. Чтобы изменить размер, введите 128 для ширины и 64 для высоты. Затем выберите подходящий вариант масштабирования для вашего изображения. Вы также можете центрировать изображение по вертикали или горизонтали и даже отразить его, если хотите. Все ваши изменения отобразятся мгновенно в разделе предварительного просмотра.

В нашем случае оригинальное изображение Мэрилин Монро имело размер 400×300 пикселей. Поэтому мы ввели 128 для ширины и 64 для высоты, выбрали «scale to fit» и центрировали изображение горизонтально, чтобы убедиться, что оно расположено красиво.

Настройки изображения в онлайн-инструменте конвертации image2cpp

Одна из самых важных настроек — порог яркости. Эта настройка определяет, какие пиксели станут чёрными, а какие белыми. Любой пиксель ярче порога будет белым, а всё, что темнее — чёрным. Также есть настройка, которая позволяет инвертировать цвета изображения, что может быть полезно в зависимости от того, как вы хотите, чтобы оно выглядело на дисплее.

Для нашего изображения мы установили порог яркости на 171, чтобы захватить больше деталей и сделать изображение чётче.

При настройке этих параметров следите за разделом предварительного просмотра — он обновляется в реальном времени, чтобы вы могли видеть, как именно изображение будет выглядеть на OLED.

Предварительный просмотр изображения в онлайн-инструменте конвертации image2cpp

Когда вы будете довольны тем, как всё выглядит, просто нажмите кнопку Generate code.

Вот и всё! Ваше изображение будет преобразовано в готовый к использованию массив, который вы можете скопировать и вставить в ваш скетч Arduino.

Генерация вывода в онлайн-инструменте конвертации image2cpp

Код Arduino

Чтобы отобразить ваше изображение на OLED-экране, вставьте сгенерированный байтовый массив в скетч Arduino ниже.

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

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for SSD1306 display connected using I2C
#define OLED_RESET -1  // Reset pin
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Bitmap of MarilynMonroe Image
const unsigned char MarilynMonroe[] PROGMEM = {
  0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xf0, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xf1, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xfc, 0x02, 0x78, 0x7f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfe, 0x03, 0x7c, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xfe, 0x01, 0xfe, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfd, 0xe0, 0x03, 0xff, 0xff, 0xfc, 0x00, 0xfe, 0x0f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfe, 0x87, 0xe0, 0xff, 0xff, 0xfc, 0x00, 0x06, 0x07, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xf9, 0xff, 0xff, 0xfc, 0x00, 0x02, 0x07, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xc3, 0xc3, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xe0, 0x0c, 0x00, 0xe7, 0x81, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0, 0x02, 0x00, 0x02, 0x00, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x1e, 0x3f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0x3f, 0xf8, 0x00, 0x18, 0x7f, 0x1f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xf8, 0x01, 0x80, 0x03, 0xfc, 0x3f, 0xfc, 0x00, 0x70, 0xfe, 0x1f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xf0, 0x43, 0xff, 0xff, 0xf8, 0x7f, 0xf8, 0x00, 0x00, 0x7e, 0x1f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xf0, 0xff, 0xfc, 0x00, 0x00, 0x7c, 0x3f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xf1, 0xef, 0xf8, 0x00, 0x01, 0xfc, 0x3f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xe4, 0xff, 0xff, 0xff, 0xf3, 0x80, 0xa0, 0x00, 0x07, 0xfc, 0xaf, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xec, 0x5f, 0xff, 0xff, 0xe7, 0xf0, 0x00, 0x00, 0x03, 0xfe, 0xdf, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xee, 0x7f, 0xff, 0xff, 0xc7, 0xf8, 0x00, 0x00, 0x03, 0xff, 0xdf, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xf7, 0xc7, 0xff, 0x06, 0x00, 0x03, 0xff, 0xbf, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xfe, 0x5f, 0xff, 0xc7, 0x07, 0xff, 0x80, 0x00, 0x07, 0xdb, 0xbf, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xee, 0xff, 0xff, 0x80, 0x03, 0xff, 0xc0, 0x00, 0x03, 0xc3, 0x0f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0x98, 0x03, 0xff, 0xf8, 0x00, 0x07, 0xe0, 0x0f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xfc, 0x01, 0x07, 0xfc, 0x1f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xcf, 0xef, 0xff, 0xff, 0xe1, 0xff, 0xfc, 0x01, 0x07, 0xf8, 0x1f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x7f, 0xf1, 0xff, 0xf8, 0x02, 0x07, 0x88, 0x3f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xcf, 0xef, 0xf8, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x07, 0x84, 0x3f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xe7, 0xef, 0xf0, 0x04, 0x7f, 0xff, 0xc0, 0x00, 0x07, 0x84, 0x7f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x3f, 0xff, 0xe0, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x06, 0x04, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x3f, 0x7f, 0xe1, 0xf0, 0x07, 0xff, 0x80, 0x00, 0x07, 0x06, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xfe, 0x03, 0xff, 0x00, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xf2, 0x3f, 0xc6, 0x7f, 0x81, 0xce, 0x00, 0x00, 0x01, 0xc1, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xe0, 0x3f, 0xc0, 0x07, 0xc1, 0xfe, 0x00, 0x00, 0x0d, 0xc0, 0x7f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xe0, 0x3f, 0xc0, 0x01, 0xe0, 0xfc, 0x00, 0x00, 0x0f, 0xc0, 0x7f, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xc0, 0x3f, 0xc0, 0x00, 0x50, 0xfc, 0x00, 0x00, 0x0e, 0xc0, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xc0, 0x3f, 0xc0, 0x00, 0x18, 0xf8, 0x00, 0x00, 0x0e, 0xc1, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xc0, 0x3f, 0xc0, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x66, 0x81, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xc0, 0x1f, 0xc7, 0x80, 0x00, 0xf8, 0x00, 0x01, 0xe0, 0x00, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xc0, 0x1f, 0xc1, 0xe0, 0x01, 0xf8, 0x00, 0x03, 0xf0, 0x01, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x80, 0x1f, 0xc0, 0x3e, 0x03, 0xf0, 0x00, 0x00, 0xe0, 0x03, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x00, 0x1f, 0xe0, 0xe0, 0x03, 0xf2, 0x00, 0x00, 0xc0, 0x03, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x80, 0x1f, 0xf0, 0x00, 0x07, 0xe6, 0x00, 0x00, 0xc0, 0x03, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0x00, 0x1f, 0xee, 0x00, 0x00, 0x80, 0x07, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xb8, 0x0f, 0xff, 0xf0, 0x3f, 0xdc, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xbc, 0x0f, 0xff, 0xff, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x9e, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x08, 0x0f, 0xff, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x00, 0x0b, 0xff, 0xff, 0xfe, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x00, 0x0b, 0xff, 0xff, 0xf9, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x3c, 0x09, 0xff, 0xff, 0xf1, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x1e, 0x08, 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x1f, 0x08, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x80, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xce, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xfe, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff
};

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

  // initialize the OLED object
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }

  // Clear the buffer.
  display.clearDisplay();

  // Display bitmap
  display.drawBitmap(0, 0, MarilynMonroe, 128, 64, WHITE);
  display.display();

  // Invert Display
  //display.invertDisplay(1);
}

void loop() {
}

После загрузки этого скетча на Arduino ваше изображение появится на OLED-экране точно так же, как в предварительном просмотре инструмента конвертера.

Отображение растрового изображения на OLED дисплейном модуле

Попробуйте и получайте удовольствие, экспериментируя со своими любимыми изображениями!

Объяснение кода

Этот скетч начинается так же, как и предыдущие примеры, где мы сначала настраиваем OLED дисплей. Мы подключаем необходимые библиотеки и инициализируем дисплей с помощью функции begin(). Как только настройка завершена, мы добавляем пользовательское изображение на экран.

Для этого мы сначала размещаем данные изображения — байтовый массив — в глобальной секции кода, выше функции setup(). Этот массив генерируется с помощью нашего инструмента конвертации изображений, который превращает картинку в формат, понятный OLED-экрану. В нашем примере массив называется MarilynMonroe.

Внутри функции setup(), после очистки дисплея, мы используем новую функцию drawBitmap() для рисования изображения на экране. Эта функция является ключом к отображению изображений и требует шести входных параметров.

Первые два значения — это координаты X и Y, которые определяют, где на экране начнётся изображение. В нашем случае мы установили оба в 0, что означает, что изображение начинается с верхнего левого угла дисплея. Третье значение — это имя массива изображения, который мы хотим нарисовать, в нашем примере это MarilynMonroe. Следующие два значения — ширина и высота изображения в пикселях. Наш OLED-экран имеет ширину 128 пикселей и высоту 64 пикселя, и наше изображение точно такого же размера, поэтому мы передаём 128 и 64. Последний параметр — цвет. Поскольку мы работаем с монохромным экраном, мы используем WHITE для отображения изображения белыми пикселями на тёмном фоне.

Итого полная строка выглядит так:

// Display bitmap
display.drawBitmap(0, 0,  MarilynMonroe, 128, 64, WHITE);

Однако, хотя эта функция подготавливает изображение к показу, оно фактически не появится на экране, пока мы не вызовем display.display();. Эта строка отправляет всё, что мы подготовили в памяти, на реальный OLED-экран, чтобы это можно было увидеть.

display.display();

Поскольку изображение не нужно менять или повторять в этом примере, мы оставляем функцию loop() пустой.