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

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

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

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

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

Обзор модуля OLED-дисплея

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

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

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

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

Питание

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

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

Карта памяти OLED-дисплея

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

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

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

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

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

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

Таким образом, расчёт выглядит следующим образом:

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

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

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

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

Распиновка

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

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

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

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

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

SDA — это вывод данных последовательного интерфейса I2C.

Подключение OLED-дисплея к ESP8266 NodeMCU

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

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

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

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

OLED-дисплейESP8266
VCC3.3V
GNDGND
SCLD1
SDAD2

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

Схема подключения OLED-дисплея к ESP8266 NodeMCU

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

Контроллер 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

Пример кода для ESP8266 №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. Эти библиотеки позволяют ESP8266 взаимодействовать с 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, Decimal, OCT, Binary на 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 и для начальной, и для конечной страницы, будет прокручиваться только первая страница дисплея.

Пример кода для ESP8266 №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() и передайте те же координаты и цвет.

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

В этом последнем примере мы научимся отображать изображение на 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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Чтобы отобразить изображение на 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() пустой.