Взаимодействие NodeMCU ESP8266 с графическим OLED дисплеем

Добавлено 7 августа 2020 в 19:19

Хотите добавить немного графики в свои IoT проекты на ESP8266? Или, может, хотите отобразить IP адрес вашего ESP8266, не прибегая к последовательному выходу. Для этого идеально подойдут суперкрутые OLED дисплеи (на органических светодиодах)! Они сверхлегкие, толщиной почти с бумагу, теоретически гибкие и дают более яркое и четкое изображение.

Взаимодействие NodeMCU ESP8266 с графическим OLED дисплеем
Взаимодействие NodeMCU ESP8266 с графическим OLED дисплеем

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

Главная особенность модуля OLED дисплея – небольшой монохромный OLED дисплей. Его ширина составляет 128 пикселей, а высота – 64 пикселя, а толщина – 0,96 дюйма. Он миниатюрен, но всё еще обладает преимуществами – OLED дисплей очень хорошо читабелен благодаря высокой контрастности, и вы можете разместить на нем обманчиво большое количество графики.

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

Рисунок 1 I2C OLED дисплей, 128x64, синий
Рисунок 1 – I2C OLED дисплей, 128x64, синий

Сердцем модуля является мощный однокристальный CMOS контроллер OLED драйвера, SSD1306, который обрабатывает всю буферизацию ОЗУ, поэтому вашему ESP8266 остается совсем немного работы. Рабочее напряжение контроллера SSD1306 составляет от 1,65 В до 3,3 В – идеально подходит для взаимодействия с микроконтроллерами 3,3 В, такими как ESP8266.

Распределение памяти OLED модуля

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

Независимо от размера OLED модуля драйвер SSD1306 обладает встроенным ОЗУ для отображаемых графических данных (Graphic Display Data RAM, GDDRAM) объемом 1 КБ для экрана, который содержит отображаемый битовый рисунок. Эта область памяти 1K организована в 8 страниц (от 0 до 7). Каждая страница содержит 128 столбцов/сегментов (от 0 до 127). И каждый столбец может хранить 8 бит данных (от 0 до 7). Это наверняка говорит вам, что в итоге мы имеем

8 страниц х 128 сегментов х 8 бит данных = 8192 бита = 1024 байта = 1 КБ памяти

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

Рисунок 2 Распределение 1 КБ RAM памяти OLED дисплея 128x64
Рисунок 2 – Распределение 1 КБ RAM памяти OLED дисплея 128x64

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

OLED дисплей 128×64 отображает всё содержимое ОЗУ, тогда как OLED дисплей 128x32 отображает только 4 страницы (половину содержимого) ОЗУ.

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

Хватит теории, приступим к практике! Давайте подключим дисплей к ESP8266 NodeMCU.

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

Затем подключите вывод SCL к выводу D1 (тактовый сигнал I2C) на NodeMCU и подключите вывод SDA к выводу D2 (данные I2C) на NodeMCU. Распиновку NodeMCU ESP8266 можно посмотреть в следующих статьях:

Схема подключения показана на рисунке ниже.

Рисунок 3 Подключение OLED дисплея к NodeMCU ESP8266
Рисунок 3 – Подключение OLED дисплея к NodeMCU ESP8266

Теперь вы готовы загрузить на NodeMCU ESP8266 какой-нибудь код и напечатать что-нибудь на дисплее.

Установка библиотеки для модуля OLED дисплея

У контроллера SSD1306 OLED дисплея гибкие, но сложные драйверы. Для использования контроллера SSD1306 требуются глубокие знания об адресации памяти. К счастью, была написана библиотека Adafruit SSD1306, чтобы скрыть все эти сложности, и чтобы мы могли выдавать простые команды для управления дисплеем.

Чтобы установить библиотеку, перейдите в меню Скетч → Подключить библиотеку → Управлять библиотеками…. Подождите, пока менеджер библиотеки загрузит список библиотек и обновит список установленных библиотек.

Рисунок 4 Выбор управления библиотеками в Arduino IDE
Рисунок 4 – Выбор управления библиотеками в Arduino IDE

Отфильтруйте результаты поиска, набрав «adafruit ssd1306». Должна остаться пара записей. Ищите Adafruit SSD1306 by Adafruit. Нажмите на эту запись, а затем выберите Установить.

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

Библиотека Adafruit SSD1306 представляет собой аппаратную библиотеку, которая выполняет функции более низкого уровня. Для отображения графических примитивов (таких как точки, линии, круги, прямоугольники и т.д.) она должна работать в паре с библиотекой Adafruit GFX. Установите и эту библиотеку.

Рисунок 6 Установка библиотеки графического ядра Adafruit GFX
Рисунок 6 – Установка библиотеки графического ядра Adafruit GFX

Примечание

Библиотека выделяет для буфера 1 КБ ((128×64)/8 бит) памяти ESP8266. Таким образом, она может манипулировать экранным буфером и затем выполнять групповую передачу из памяти ESP8266 во внутреннюю память контроллера SSD1306.

Модификация библиотеки Adafruit SSD1306

Библиотека Adafruit SSD1306 не настроена для дисплеев OLED 128×64 (один из которых мы сейчас используем). Чтобы она заработала, в заголовочном файле Adafruit_SSD1306.h необходимо изменить размер экрана. Если он не будет изменен, при попытке компиляции скетча может появиться сообщение об ошибке #error (“Height incorrect, please fix Adafruit_SSD1306.h!”) (некорректная высота, исправьте Adafruit_SSD1306.h):

Рисунок 7 Некорректная высота, пожалуйста, исправьте ошибку Adafruit_SSD1306.h
Рисунок 7 – Некорректная высота, пожалуйста, исправьте ошибку Adafruit_SSD1306.h

Чтобы изменить заголовочный файл Adafruit_SSD1306.h, откройте папку с библиотеками. Стандартный путь: Мои Документы → Arduino. Теперь перейдите в libraries → Adafruit_SSD1306

Рисунок 8 Расположение библиотеки Adafruit SSD1306
Рисунок 8 – Расположение библиотеки Adafruit SSD1306

Откройте файл Adafruit_SSD1306.h в текстовом редакторе. Прокрутите файл вниз, чтобы найти секцию SSD1306 Displays или сразу перейдите к строке 73. Закомментируйте #define SSD1306_128_32 и раскомментируйте #define SSD1306_128_64, чтобы код в этом разделе выглядел следующим образом:

Рисунок 9 Удаление ошибки неверной высоты, изменив файл Adafruit_SSD1306.h
Рисунок 9 – Удаление ошибки неверной высоты, изменив файл Adafruit_SSD1306.h

Вот и всё. Теперь сохраните файл и перезапустите Arduino IDE.

Код ESP8266: отображение текста

Теперь самое интересное!

Следующий тестовый скетч напечатает на дисплее сообщение «Hello World!». Он также включает в себя:

  • отображение инвертированного текста;
  • отображение чисел;
  • отображение чисел с основанием (hex, dec);
  • отображение символов ASCII
  • прокрутка текста по горизонтали и по вертикали;
  • прокрутка части дисплея.

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

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

Adafruit_SSD1306 display(-1);

void setup()   
{                
  // инициализация с I2C адресом 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

  // очистить буфер
  display.clearDisplay();

  // показать текст
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,28);
  display.println("Hello world!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // показать инвертированный текст
  display.setTextColor(BLACK, WHITE); // 'инвертированный' текст
  display.setCursor(0,28);
  display.println("Hello world!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // изменение размера шрифта
  display.setTextColor(WHITE);
  display.setCursor(0,24);
  display.setTextSize(2);
  display.println("Hello!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // показать числа
  display.setTextSize(1);
  display.setCursor(0,28);
  display.println(123456789);
  display.display();
  delay(2000);
  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);
  display.clearDisplay();

  // показать символы ASCII
  display.setCursor(0,24);
  display.setTextSize(2);
  display.write(3);
  display.display();
  delay(2000);
  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();
  display.clearDisplay();

  // прокрутка части экрана
  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() {}

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

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

Далее нам нужно создать объект Adafruit_SSD1306. Конструктор Adafruit_SSD1306 принимает номер вывода ESP8266, к которому подключен вывод сброса дисплея. Поскольку используемый нами OLED дисплей не имеет вывода RESET, мы отправим конструктору значение -1, чтобы ни один из выводов ESP8266 не использовался в качестве сброса для дисплея.

Adafruit_SSD1306 display(-1);

В функции setup() нам нужно инициализировать объект OLED дисплея с помощью функции begin(). Эта функция принимает два параметра. Первый параметр SSD1306_SWITCHCAPVCC включает внутреннюю схему питания, а второй параметр предоставляет I2C адрес OLED дисплея. Адрес I2C такого модуля OLED дисплея обычно равен 0x3C. Он фиксированный и не может быть изменен.

Далее перед печатью нашего первого сообщения на экране мы очищаем буфер.

// инициализация с I2C адресом 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

// очистить буфер
display.clearDisplay();

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

Рисунок 10 Отображение текста на модуле OLED дисплея
Рисунок 10 – Отображение текста на модуле OLED дисплея
// показать текст
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Для отображения текста на экране нам нужно установить размер шрифта. Это можно сделать, вызвав setTextSize(font-size) и передав в качестве параметра размер шрифта (размер начинается с 1).

Далее нам нужно установить цвет шрифта, вызвав функцию setTextColor(color). Передайте параметр WHITE для темного фона или BLACK для светлого фона. Теперь перед печатью сообщения нам нужно установить позицию курсора, вызвав функцию setCursor(X, Y). Пиксели на экране адресуются по горизонтальным (X) и вертикальным (Y) координатам. Система координат размещает начало координат (0,0) в верхнем левом углу, причем положительный X смещается вправо, а положительный Y смещается вниз.

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

Чтобы библиотека могла выполнять чрезвычайно быстрые математические операции с буфером экрана (более 100 кадров в секунду), вызовы функций печати не сразу передают содержимое экранного буфера на контроллер SSD1306. Для указания библиотеке выполнить массовую передачу из экранного буфера в ESP8266 во внутреннюю память контроллера SSD1306 необходимо вызвать функцию display(). Как только содержимое памяти будет перенесено, на OLED дисплее появятся пиксели, соответствующие содержимому экранного буфера.

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

Рисунок 11 Отображение инвертированного текста на модуле OLED дисплея
Рисунок 11 – Отображение инвертированного текста на модуле OLED дисплея
// показать инвертированный текст
display.clearDisplay();
display.setTextColor(BLACK, WHITE); // 'инвертированный' текст
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Для отображения инвертированного текста мы снова вызовем функцию setTextColor(FontColor, BackgroundColor). Если вы были внимательны, то знаете, что ранее мы передали этой функции только один параметр, но теперь мы передаем два параметра. Это возможно благодаря перегрузке функций. Перегрузка функций – это возможность создавать несколько функций с одинаковым именем, но с разными наборами параметров. Вызовы перегруженной функции будут запускать конкретную реализацию этой функции в зависимости от переданных параметров.

В нашем случае вызов setTextColor(BLACK, WHITE) отобразит черный текст на заполненном светлом фоне.

Изменение размера шрифта

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

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

Символы отображаются в соотношении сторон 7:10. Это означает, что при передаче размера шрифта 1 текст будет отображаться с разрешением 7×10 пикселей на символ, при передаче 2 текст будет отображаться с разрешением 14×20 пикселей на символ, и так далее.

За рендеринг шрифта отвечает библиотека Adafruit_GFX. По умолчанию выбран моноширинный шрифт. Однако более поздние версии библиотеки Adafruit GFX предлагают возможность использовать альтернативные шрифты. В библиотеку входит несколько альтернативных шрифтов, плюс есть возможность добавлять новые.

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

Рисунок 13 Отображение чисел на модуле OLED дисплея
Рисунок 13 – Отображение чисел на модуле OLED дисплея
// показать числа
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,28);
display.println(123456789);
display.display();
delay(2000);

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

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

Рисунок 14 Отображение чисел на модуле OLED дисплея в восьмеричном, шестнадцатеричном и двоичном форматах
Рисунок 14 – Отображение чисел на модуле OLED дисплея в восьмеричном, шестнадцатеричном и двоичном форматах
// указать основание для чисел
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);

У функций print() и println() есть необязательный второй параметр, который определяет основание (формат); допустимые значения: BIN (двоичное, или основание 2), OCT (восьмеричное, или основание 8), DEC (десятичное, или основание 10), HEX (шестнадцатеричное, или основание 16). Для чисел с плавающей запятой этот параметр указывает количество десятичных знаков. Например:

  • print(78, BIN) дает “1001110
  • print(78, OCT) дает “116
  • print(78, DEC) дает “78
  • print(78, HEX) дает “4E
  • println(1.23456, 0) дает “1
  • println(1.23456, 2) дает “1.23
  • println(1.23456, 4) дает “1.2346

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

Рисунок 15 Отображение символов ASCII на модуле OLED дисплея
Рисунок 15 – Отображение символов ASCII на модуле OLED дисплея
// показать символы ASCII
display.clearDisplay();
display.setCursor(0,24);
display.setTextSize(2);
display.write(3);
display.display();
delay(2000);

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

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

Рисунок 16 Прокрутка всего экрана на модуле OLED дисплея
Рисунок 16 – Прокрутка всего экрана на модуле OLED дисплея
// прокрутка всего экрана
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(startPage, stopPage) и startscrollleft(startPage, stopPage), и по диагонали, вызывая startscrolldiagright(startPage, stopPage) и startscrolldiagleft(startPage, stopPage). Все эти функции принимают два параметра, а именно, начальная страница (startPage) и конечная страница (stopPage). Для объяснения страниц обратитесь к разделу «Распределение памяти OLED модуля». Поскольку на дисплее отображается восемь страниц от 0 до 7, вы можете прокручивать весь экран, прокручивая все страницы, то есть, передавая параметры 0x00 и 0x07.

Чтобы остановить прокрутку дисплея, используется функция stopcroll().

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

Рисунок 17 Прокрутка определенной части экрана на модуле OLED дисплея
Рисунок 17 – Прокрутка определенной части экрана на модуле OLED дисплея
// прокрутка части экрана
display.clearDisplay();
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);

Иногда нам не нужно прокручивать весь экран. Прокрутку только определенной части можно выполнить, передав функциям прокрутки правильную информацию о стартовой и конечной страницах. Для объяснения страниц обратитесь к разделу «Распределение памяти OLED модуля». Поскольку на дисплее отображается восемь страниц от 0 до 7, вы можете прокрутить какую-либо часть экрана, передав в качестве параметров конкретные номера страниц.

В нашем примере мы передали в оба параметра значение 0x00. Это позволит прокрутить только первую страницу (первые 8 строк) дисплея.

Код ESP8266: основы рисования

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

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

Adafruit_SSD1306 display(-1);

void setup()   
{                
  // инициализация с I2C адресом 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

  // очистить буфер
  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);
  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);
  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);
  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);
  display.clearDisplay();
}

void loop() {}

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

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

Рисунок 18 Рисование прямоугольника на модуле OLED дисплея
Рисунок 18 – Рисование прямоугольника на модуле 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);
Рисунок 19 Рисование закрашенного прямоугольника на модуле OLED дисплея
Рисунок 19 – Рисование закрашенного прямоугольника на модуле OLED дисплея
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().

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

Рисунок 20 Рисование скругленного прямоугольника на модуле OLED дисплея
Рисунок 20 – Рисование скругленного прямоугольника на модуле 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);
Рисунок 21 Рисование скругленного закрашенного прямоугольника на модуле OLED дисплея
Рисунок 21 – Рисование скругленного закрашенного прямоугольника на модуле OLED дисплея
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(X_координата, Y_координата, ширина, высота, радиус, цвет). Эта функция принимает те же параметры, что и функция drawRect(), за исключением одного дополнительного параметра – радиуса скругления углов. Эта функция рисует полый скругленный прямоугольник с границей в 1 пиксель. Нарисовать закрашенный скругленный прямоугольник можно с помощью функции fillRoundRect().

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

Рисунок 22 Рисование круга на модуле OLED дисплея
Рисунок 22 – Рисование круга на модуле 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);
Рисунок 23 Рисование закрашенного круга на модуле OLED дисплея
Рисунок 23 – Рисование закрашенного круга на модуле OLED дисплея
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_координата_центра, радиус, цвет). Эта функция рисует полый круг с границей в 1 пиксель. Нарисовать заполненный круг можно с помощью функции fillCircle().

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

Рисунок 24 Рисование треугольника на модуле OLED дисплея
Рисунок 24 – Рисование треугольника на модуле 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);
Рисунок 25 Рисование закрашенного треугольника на модуле OLED дисплея
Рисунок 25 – Рисование закрашенного треугольника на модуле OLED дисплея
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(x0, y0, x1, y1, x2, y2, color). Данная функция принимает семь параметров, а именно, координаты 3 вершин треугольника (x,y) и цвет. (x0, y0) представляет верхнюю вершину, (x1, y1) – левую вершину, и (x2, y2) – правую вершину.

Эта функция рисует полый треугольник с границей в 1 пиксель. Нарисовать заполненный треугольник можно с помощью функции fillTriangle().

Код NodeMCU ESP8266: отображение растрового изображения

В последнем примере показано, как на OLED дисплее рисовать растровые изображения. Это полезно для создания заставок с логотипом компании, создания спрайтов или просто создания забавной графики при отображении информации. Скопируйте следующий код, вставьте его в Arduino IDE и нажмите «Загрузить».

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

Adafruit_SSD1306 display(-1);

// Образ растрового изображения с Мэрилин Монро
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()   
{                
  // инициализация с I2C адресом 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

  // очистить буфер
  display.clearDisplay();

  // показать растровое изображение
  display.drawBitmap(0, 0,  MarilynMonroe, 128, 64, WHITE);
  display.display();

  // инвертировать экран
  //display.invertDisplay(1);
}

void loop() {}

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

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

Чтобы показать растровое изображение на OLED дисплее, нам нужно вызвать функцию drawBitmap(X_координата, Y_координата, растровый_массив, ширина, высота, цвет). Она принимает шесть параметров, а именно, координата X левого верхнего угла, координата Y левого верхнего угла, байтовый массив монохромного растрового изображения, ширина растрового изображения в пикселях, высота растрового изображения в пикселях и цвет.

В нашем примере растровое изображение имеет размер 128×64. Таким образом, координаты X и Y установлены в 0, а ширина и высота установлены в 128 и 64.

// показать растровое изображение
display.drawBitmap(0, 0,  MarilynMonroe, 128, 64, WHITE);
display.display();

Но прежде чем мы сможем вызвать функцию drawBitmap(), нам сначала нужно нарисовать изображение. Помните, что разрешение OLED дисплея составляет 128×64 пикселей, поэтому изображения большего размера будут отображаться некорректно. Чтобы получить изображение правильного размера, вы можете использовать ваши любимые программы для рисования, такие как Inkscape, Photoshop, Paint и т.д., установив размер холста 128×64 пикселей.

В качестве примера мы взяли изображение Мэрилин Монро, преобразовали размер его в 128×64 пикселей с помощью Paint и сохранили в формате .bmp.

Рисунок 27 Мэрилин Монро
Рисунок 27 – Мэрилин Монро
Рисунок 28 Мэрилин Монро 128x64
Рисунок 28 – Мэрилин Монро 128x64

Теперь, когда у нас есть растровое изображение, самое время преобразовать его в массив, понятный OLED контроллеру SSD1306. Это можно сделать двумя способами: онлайн-метод с использованием image2cpp и офлайн-метод с использованием LCD Assistant.

Онлайн-генератор растровых массивов image2cpp

Онлайн-приложение image2cpp может преобразовать ваше изображение в массив. Image2cpp является более новым и намного более мощным, чем LCD Assistant. Оно позволит вам:

  • преобразовать несколько изображений одновременно;
  • масштабировать файл изображения (растянуть/масштабировать по размеру или относительно оригинала);
  • настроить порог яркости между черным и белым;
  • отцентрировать изображение по вертикали и/или по горизонтали;
  • инвертировать цвета изображения.

Этот инструмент настолько мощный, что может работать и в автономном режиме. Просто сохраните страницу на своем ПК и откройте ее в браузере.

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

Рисунок 29 Выберите изображение - image2cpp Инструмент преобразования растрового изображения в массив данных онлайн
Рисунок 29 – Выберите изображение

Размеры вашего изображения будут отображаться в параметре Canvas size в разделе Image settings. Если вы выбрали изображение большего размера, чем 128×64, измените его на 128×64 и выберите подходящий параметр масштабирования Scaling. Вы можете просмотреть вывод в разделе предварительного просмотра Preview section.

При необходимости вы можете изменить цвет фона (Background color) или инвертировать цвета изображения (Invert image colors).

Наконец, измените в соответствии с вашими требованиями наиболее важный параметр – порог яркости (Brightness threshold). Установка порога сделает пиксели выше этого уровня белыми и ниже черными. В нашем случае мы установили 171, чтобы получить достаточно детализированное изображение Мэрилин Монро.

Рисунок 30 Настройки преобразования растрового изображения в массив данных в image2cpp
Рисунок 30 – Настройки преобразования растрового изображения в массив данных в image2cpp

Это изображение предварительного просмотра отражает все изменения, которые вы вносите в свои настройки. Вы можете изменять настройки, следя за ним.

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

Как только вы будете удовлетворены результатом, можете приступить к созданию массива данных. Просто выберите формат вывода кода (Code output format) как Arduino Code и нажмите кнопку Generate code.

Для информации, есть еще опция под названием Режим рисования (Draw mode). Она на самом деле создает изображение в соответствии с шаблоном сканирования дисплея. Если ваше изображение выглядит на дисплее испорченным, попробуйте изменить этот режим.

Рисунок 32 Генерирование вывода в image2cpp
Рисунок 32 – Генерирование вывода в image2cpp

Вот и всё. Сейчас будет сгенерирован байтовый массив вашего растрового изображения. И вы можете использовать этот вывод непосредственно в коде нашего примера. Просто не забудьте назвать его соответствующим образом. А затем вызовите ваш массив внутри функции drawBitmap().

Рисунок 33 Вывод image2cpp в формате Arduino Code
Рисунок 33 – Вывод image2cpp в формате Arduino Code

Автономный генератор массивов растровых изображений LCD Assistant

Преобразовать ваше растровое изображение в массив данных может еще одно приложение, LCD Assistant. Оно не такой мощное, как image2cpp, но по-прежнему популярно среди любителей.

Для начала вам необходимо преобразовать ваше изображение в монохромное растровое изображение 128×64. Чтобы сделать это, вы можете использовать ваши любимые программы для рисования, такие как Inkscape, Photoshop, Paint и т.д. Мы делали это в MS Paint.

Откройте ваш файл в MS Paint и измените его размер на 128×64.

Рисунок 34 Открытие изображения в Paint
Рисунок 34 – Открытие изображения в Paint

Теперь сохраните ваш файл как растровое изображение. При сохранении файла выберите Сохранить как: Монохромный рисунок (*.bmp; *.dib). Это создаст 1-битное/двоичное растровое изображение, которое для каждого пикселя имеет только два возможных значения, то есть 0 (черный) или 1 (белый).

Рисунок 35 Сохранение 1-битного монохромного растрового изображения в MS Paint
Рисунок 35 – Сохранение 1-битного монохромного растрового изображения в MS Paint

Единственным недостатком здесь является то, что вы не можете установить пороговый уровень яркости. По умолчанию он установлен на 50% и не может быть изменен.

Теперь скачайте программу LCD Assistant. Откройте ее и загрузите ваше растровое изображение из меню File.

Рисунок 36 LCD Assistant преобразует растровое изображение в массив данных для графических LCD и OLED дисплеев
Рисунок 36 – LCD Assistant преобразует растровое изображение в массив данных для графических LCD и OLED дисплеев

Ничего особого с этим инструментом вы сделать не можете. Итак, просто зайдите в меню File и нажмите Save output. Сохраните файл как текстовый файл.

Для информации, здесь есть еще опция под названием Byte Orientation. Она создает изображение в соответствии с шаблоном сканирования дисплея. Если ваше изображение выглядит на дисплее испорченным, попробуйте изменить этот режим.

Рисунок 37 Сохранить вывод LCD Assistant
Рисунок 37 – Сохранить вывод LCD Assistant

Вот и всё. Создав массив, вставьте его в свой код.

Рисунок 38 Вывод преобразования растрового изображения в массив данных
Рисунок 38 – Вывод преобразования растрового изображения в массив данных

Просто не забудьте назвать его соответствующим образом. Затем вызовите ваш массив внутри функции drawBitmap().

Теги

ESP8266EspressifIoT (интернет вещей)NodeMCUOLEDМикроконтроллер

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.