Урок 3. ESP32 и ESP8266 с выводом статуса на веб-страницу и на OLED дисплей.

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

Для изучения данного урока рекомендую посмотреть предыдущий урок про ESP32 и ESP8266:

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

Также, в данном уроке, расскажу поверхностно про OLED дисплей, и его возможности. Больше информации в моих уроках по подключению OLED дисплея к Arduino:

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

Подключить довольно просто. Начните с подключения вывода VCC к выходу 3,3 В на ESP32, и подключите GND к земле. На следующей схеме показано, как подключить дисплея OLED к ESP32.

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

Затем подключите контакт SCL к контакту D22 на ESP32, и подключите контакт SDA к контакту D21 на ESP32.

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

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

Установка библиотеки Adafruit SSD1306 для OLED-дисплея.

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

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

Установка библиотеки Adafruit SSD1306 для OLED-дисплея.

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

Отфильтруйте результаты поиска, набрав «adafruit ssd1306»

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

Она должна быть соединена с библиотекой Adafruit GFX

Код ESP32 - вывод текста на OLED дисплей.

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

  • Текст инвертированного цвета
  • Числа
  • Числа с основанием (Hex, Dec)
  • Символы ASCII
  • Текст с прокруткой по горизонтали и вертикали
  • Текст с частичной прокруткой

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

#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 an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
  Serial.begin(115200);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println("SSD1306 allocation failed");
    for(;;);
  }
  delay(2000);
  display.cp437(true);
  display.clearDisplay();
  display.setTextSize(1);             
  display.setTextColor(WHITE);        
  display.setCursor(0,20);             
  display.println("Hello world!");
  display.display();
  delay(2000); 
  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() {
}

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

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

Далее, нам нужно создать объект Adafruit_SSD1306.h. Функция Adafruit_SSD1306 принимает номер вывода ESP32, к которому подключен вывод сброса дисплея. Поскольку используемый нами OLED-дисплей не имеет вывода RESET, мы отправим «- 1» в функцию, чтобы ни один из выводов ESP32 не использовался для сброса дисплея.

Adafruit_SSD1306 display(-1);

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

// initialize with the I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// Clear the buffer.
display.clearDisplay();

Затем, мы очищаем буфер, перед выводом нашего первого сообщения на экран. Фото каждого примера выкладывать не буду, примеры вывода текста и геометрических фигур на OLED дисплей есть в уроке: Дисплей SSD1306 подключаем к Arduino. Выводим текст, рисуем фигуры.

Вывод на OLED простого текста (Hello World).

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

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

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

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

Чтобы библиотека могла выполнять чрезвычайно быстрые математические операции с экранным буфером (более 100 кадров в секунду), требуется display() команда для указания библиотеке выполнить массовую передачу из буфера в ESP32 во внутреннюю память контроллера SSD1306, так как вызовы функций печати не передают немедленно содержимое экранного буфера на контроллер SSD1306. Как только данные будут переданы, пиксели, соответствующие экранному буферу, появятся на 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(FontColor,BackgroundColor) функцию. Если вы обратили внимание, и вы заметили, что раньше мы передавали только один параметр этой функции, то теперь мы передаем два параметра. Это возможно из-за того, что называется перегрузкой функций. Перегрузка функций - это возможность создавать несколько функций с одним и тем же именем, но с различным набором параметров. Вызов перегруженной функции запускает конкретную реализацию этой функции, в зависимости от переданных параметров.

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

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

// Changing Font Size
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 предлагают возможность использования альтернативных шрифтов. В библиотеке есть несколько альтернативных шрифтов, плюс есть возможность добавлять новые.

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

// Display Numbers
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.

Указание формата чисел для вывода на 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);

У функций 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.

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

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

Текст с прокруткой по горизонтали и вертикали.

// 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(start page, stop page) или startscrollleft(start page, stop page), и по диагонали, вызывая startscrolldiagright(start page, stop page) или startscrolldiagleft(start page, stop page). Все эти функции принимают два параметра, а именно: начальная страница и стоп-страница. Поскольку на дисплее восемь строчек, от 0 до 7, вы можете прокручивать весь экран, прокручивая все строчки, то есть, передавая параметры 0x00 и 0x07.

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

Текст с частичной прокруткой.

// 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);

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

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

Вывод теста на OLED ESP8266 NodeMCU.

Так как Adafruit SSD1306 и Adafruit GFX совместимы с ESP32 и ESP8266, код для вывода теста не будет отличаться для обеих плат. Достаточно подключить отладочную плату к компьютеру, настроить Arduino IDE и загрузить код.

Вывод теста на OLED ESP8266 NodeMCU.

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

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

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

Затем, подключите контакт SCL к контакту D1 на NodeMCU, и подключите контакт SDA к контакту D2 на NodeMCU.

Теперь все готово и можно загрузить код, и вывести текст на дисплей.

Вывод русских символов на OLED, подключенного к ESP32 или ESP8266.

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

Вывод русских символов на OLED, подключенного к ESP32 или ESP8266.

Настройка Arduino IDE для вывода русских символов на OLED подключение ESP32 и ESP8266.

  • Установить библиотеки Adafruit: библиотеку Adafruit_SSD1306 и библиотеку Adafruit_GFX. Как установить данные библиотеки, рассказывал выше
  • Скачать файл glcdfont.c (скачиваем файлы внизу страницы, в разделе Файлы для скачивания) и заменить его в библиотеке Adafruit-GFX. Библиотека находится C:\Users\USER\Documents\Arduino\libraries\Adafruit_GFX_Library. У вас путь до библиотеки может быть другим.
  • В скетч нужно добавить функцию перекодировки русских букв из UTF-8 в Win-1251. Добавить функцию можно в самом низу кода.
/* Функция перекодировки русских букв из UTF-8 в Win-1251 */
String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };
  k = source.length(); i = 0;
  while (i < k) {
    n = source[i]; i++;
    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}
  • Добавить в блок void setup() {} следующую строчку кода.
display.cp437(true);
  • При выводе русского текста использовать функцию utf8rus().

После того, как выполнили все 5 пунктов настройки Arduino IDE. Изменим вывод надписи:

display.println("Hello,world!");

На

display.println(utf8rus("Привет МИР!"));

Полный код примера вывода русских символов на OLED, подключение ESP32 и ESP8266.

Код ESP32 вывод геометрических фигур на OLED дисплей.

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

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSerif9pt7b.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
  Serial.begin(115200);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println("SSD1306 allocation failed");
    for(;;);
  }
  // Clear the buffer.
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(utf8rus("прямоугольник"));
  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(utf8rus("прямоугольник заполненный"));
  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(utf8rus("прямоугольник с круглениями"));
  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 (utf8rus("прямоугольник с круглениями заполненный"));
  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(utf8rus("круг"));
  display.drawCircle(20, 35, 20, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(utf8rus("круг заполенный"));
  display.fillCircle(20, 35, 20, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(utf8rus("треугольник"));
  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(utf8rus("треугольник заполненный"));
  display.fillTriangle(30, 15, 0, 60, 60, 60, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();
}
void loop() {
}
/* Функция перекодировки русских букв из UTF-8 в Win-1251 */
String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };
  k = source.length(); i = 0;
  while (i < k) {
    n = source[i]; i++;
    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

Расписывать код не буду, думаю тут и так все понятно. Если будут вопросы, то смотрите урок: «Дисплей SSD1306 подключаем к Arduino. Выводим текст, рисуем фигуры». И пишите ваши вопросы в комментариях.

Управление светодиодами с выводом статуса на веб-страницу и на OLED дисплей.

Пришло время сделать что-то более интересное и применимое в жизни. В предыдущем уроке мы подключали светодиоды и создавали Веб-сервер, позволяющий управлять данными светодиодами через веб-интерфейс. Достаточно было загрузить адрес нашего устройства в строке браузера, и при нажатии кнопок, включать и выключать светодиод. При этом, в браузере мы видели статус, включен светодиод или выключен. Как же сделать так, чтобы и без приложения можно было определить, включен светодиод или нет? У вас возник вопрос: "светодиод светится и не заметить, что он работает не сложно?" Но вместо светодиода мы можем подключить нагрузку, используя реле или MOSFET транзистор. И все поместить в корпус, или разместить в распределительной коробке. И тогда, как определить, что у нас включено, а что выключено? Для этого мы и подключим OLED дисплей и выведем, для начала, статус включения светодиода. А что подключите вы, - это уже ваше решение.

Схема подключения светодиодов и OLED дисплея к ESP32.

Схема подключения светодиодов и OLED дисплея к ESP32.

Схема подключения светодиодов и OLED дисплея к ESP8266.

Схема подключения светодиодов и OLED дисплея к ESP8266.

Как видно, мы просто совместили схему из прошлого урока, и схему подключения OLED дисплея.

Скетч для ESP32 и ESP8266 вывод статуса на веб-страницу и на OLED дисплей.

Скетч писать для каждой платы отдельно не стал. Написал общий код, для прошивки обеих плат. Подключайте к ПК вашу отладочную плату, выбирайте в Arduino IDE, что за плата подключена к компьютеру, и загружаете прошивку.

#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#else
#include <WiFi.h>
#include <WebServer.h>
#endif
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSerif9pt7b.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Определяем переменные wifi
const char* ssid = "Wi-Fi";
const char* password = "password";
#ifdef ESP8266
// Web интерфейс для устройства
ESP8266WebServer server(80);
uint8_t LED1pin = D4;
uint8_t LED2pin = D5;
#else
// Web интерфейс для устройства
WebServer server(80);
uint8_t LED1pin = 4;
uint8_t LED2pin = 5;
#endif
bool LED1status = LOW;
bool LED2status = LOW;
bool LED1statusOld = LOW;
bool LED2statusOld = LOW;
void setup() {
  Serial.begin(115200);
  delay(100);
  pinMode(LED1pin, OUTPUT);
  pinMode(LED2pin, OUTPUT);
  Serial.println("Connecting to ");
  Serial.println(ssid);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 allocation failed");
    for (;;);
  }
  //connect to your local wi-fi network
  WiFi.begin(ssid, password);
  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());
  server.on("/", handle_OnConnect);
  server.on("/led1on", handle_led1on);
  server.on("/led1off", handle_led1off);
  server.on("/led2on", handle_led2on);
  server.on("/led2off", handle_led2off);
  server.onNotFound(handle_NotFound);
  server.begin();
  Serial.println("HTTP server started");
  display.cp437(true);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 3);
  display.println(utf8rus("IP:"));
  display.setCursor(32, 3);
  display.println(WiFi.localIP());
  display.setCursor(0, 20);
  display.println(utf8rus("Состояние LED1: ВЫКЛ."));
  display.setCursor(0, 40);
  display.println(utf8rus("Состояние LED2: ВЫКЛ."));
  display.display();
}
void loop() {
  server.handleClient();
  oled_text();
  if (LED1status)
  {
    digitalWrite(LED1pin, HIGH);
  }
  else
  {
    digitalWrite(LED1pin, LOW);
  }
  if (LED2status)
  {
    digitalWrite(LED2pin, HIGH);
  }
  else
  {
    digitalWrite(LED2pin, LOW);
  }
}
void handle_OnConnect() {
  LED1status = LOW;
  LED2status = LOW;
  Serial.println("GPIO4 Status: OFF | GPIO5 Status: OFF");
  server.send(200, "text/html", SendHTML(LED1status, LED2status));
}
void handle_led1on() {
  LED1status = HIGH;
  Serial.println("GPIO4 Status: ON");
  server.send(200, "text/html", SendHTML(true, LED2status));
}
void handle_led1off() {
  LED1status = LOW;
  Serial.println("GPIO4 Status: OFF");
  server.send(200, "text/html", SendHTML(false, LED2status));
}
void handle_led2on() {
  LED2status = HIGH;
  Serial.println("GPIO5 Status: ON");
  server.send(200, "text/html", SendHTML(LED1status, true));
}
void handle_led2off() {
  LED2status = LOW;
  Serial.println("GPIO5 Status: OFF");
  server.send(200, "text/html", SendHTML(LED1status, false));
}
void handle_NotFound() {
  server.send(404, "text/plain", "Not found");
}
void oled_text() {
  if (LED1statusOld != LED1status || LED2statusOld != LED2status) {
    display.clearDisplay();
    display.cp437(true);
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 20);
    if ( LED1status == HIGH)
      display.println(utf8rus("Состояние LED1: ВКЛ."));
    else
      display.println(utf8rus("Состояние LED1: ВЫКЛ."));
    display.setCursor(0, 40);
    if ( LED2status == HIGH)
      display.println(utf8rus("Состояние LED2: ВКЛ."));
    else
      display.println(utf8rus("Состояние LED2: ВЫКЛ."));
    display.display();
    LED1statusOld = LED1status;
    LED2statusOld = LED2status;
  }
}
String SendHTML(uint8_t led1stat, uint8_t led2stat) {
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>Управление светодиодом</title>\n";
  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  ptr += ".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button-on {background-color: #3498db;}\n";
  ptr += ".button-on:active {background-color: #2980b9;}\n";
  ptr += ".button-off {background-color: #34495e;}\n";
  ptr += ".button-off:active {background-color: #2c3e50;}\n";
  ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
#ifdef ESP8266
  ptr += "<h1>ESP8266 Веб сервер</h1>\n";
#else
  ptr += "<h1>ESP32 Веб сервер</h1>\n";
#endif
  ptr += "<h3>Режим станции (STA)</h3>\n";
  if (led1stat)
  {
    ptr += "<p>Состояние LED1: ВКЛ.</p><a class=\"button button-off\" href=\"/led1off\">ВЫКЛ.</a>\n";
  }
  else
  {
    ptr += "<p>Состояние LED1: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led1on\">ВКЛ.</a>\n";
  }
  if (led2stat)
  {
    ptr += "<p>Состояние LED2: ВКЛ.</p><a class=\"button button-off\" href=\"/led2off\">ВЫКЛ.</a>\n";
  }
  else
  {
    ptr += "<p>Состояние LED2: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led2on\">ВКЛ.</a>\n";
  }
  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}
/* Функция перекодировки русских букв из UTF-8 в Win-1251 */
String utf8rus(String source)
{
  int i, k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };
  k = source.length(); i = 0;
  while (i < k) {
    n = source[i]; i++;
    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
            n = source[i]; i++;
            if (n == 0x81) {
              n = 0xA8;
              break;
            }
            if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
            break;
          }
        case 0xD1: {
            n = source[i]; i++;
            if (n == 0x91) {
              n = 0xB8;
              break;
            }
            if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
            break;
          }
      }
    }
    m[0] = n; target = target + String(m);
  }
  return target;
}

Описание кода для ESP32 и ESP8266, вывод статуса на веб-страницу и на OLED дисплей.

Описание кода для ESP32 и ESP8266, вывод статуса на веб-страницу и на OLED дисплей.

Расписывать весь код не буду. В предыдущем уроке мы рассмотрели, как создать Веб-сервер на ESP32, а в данном уроке подключение OLED дисплея. Осталось понять, как, на основании полученных знаний, сделать синхронно вывод, состояния светодиодов, на Веб-страницу и на OLED дисплей.

В скетч из урока: Веб-сервер ESP32 (ESP8266) в среде Arduino IDE. Подключим библиотеки для работы с OLED дисплеем, и настроим код для работы с дисплеем, что мы делали в данном уроке не однократно.

#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#else
#include <WiFi.h>
#include <WebServer.h>
#endif
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSerif9pt7b.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Определяем переменные wifi
const char* ssid = "Wi-Fi";
const char* password = "password";
#ifdef ESP8266
// Web интерфейс для устройства
ESP8266WebServer server(80);
uint8_t LED1pin = D4;
uint8_t LED2pin = D5;
#else
// Web интерфейс для устройства
WebServer server(80);
uint8_t LED1pin = 4;
uint8_t LED2pin = 5;
#endif

Добавим дополнительно 2 переменные для определения предыдущего состояния светодиода.

bool LED1status = LOW;
bool LED2status = LOW;
bool LED1statusOld = LOW;
bool LED2statusOld = LOW;

В функцию setup() добавим код вывода на дисплей IP-адреса устройства, а также, текущее состояние светодиодов. Так как мы только включили устройство, светодиоды выключены.

  display.cp437(true);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 3);
  display.println(utf8rus("IP:"));
  display.setCursor(32, 3);
  display.println(WiFi.localIP());
  display.setCursor(0, 20);
  display.println(utf8rus("Состояние LED1: ВЫКЛ."));
  display.setCursor(0, 40);
  display.println(utf8rus("Состояние LED2: ВЫКЛ."));
  display.display();

Напишем небольшую функцию oled_text(), которая будет выводить состояние светодиодов на OLED дисплей.

void oled_text() {
  if (LED1statusOld != LED1status || LED2statusOld != LED2status) {
    display.clearDisplay();
    display.cp437(true);
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 20);
    if ( LED1status == HIGH)
      display.println(utf8rus("Состояние LED1: ВКЛ."));
    else
      display.println(utf8rus("Состояние LED1: ВЫКЛ."));
    display.setCursor(0, 40);
    if ( LED2status == HIGH)
      display.println(utf8rus("Состояние LED2: ВКЛ."));
    else
      display.println(utf8rus("Состояние LED2: ВЫКЛ."));
    display.display();
    LED1statusOld = LED1status;
    LED2statusOld = LED2status;
  }
}

Описание функции oled_text().

Сперва, нам нужно определить, изменилось ли состояние светодиодов. Для этого сравниваем текущее и предыдущее состояние светодиодов. Например, мы нажали на включение первого светодиода. Переменная LED1status стала равной HIGH, а значение переменой LED1statusOld мы задали по умолчанию равной LOW.

if (LED1statusOld != LED1status || LED2statusOld != LED2status) {

Если изменение было, то обновляем информацию на дисплее. Сначала чистим дисплей.

display.clearDisplay();

При выводе информации на дисплей есть 2 условия. В первом, если LED1status == HIGH, то мы выводим на дисплей надпись: "Состояние LED1: ВКЛ." Иначе выводим надпись "Состояние LED1: ВЫКЛ.". Второе условие аналогично, но для второго светодиода.

if ( LED1status == HIGH)
      display.println(utf8rus("Состояние LED1: ВКЛ."));
    else
      display.println(utf8rus("Состояние LED1: ВЫКЛ."));

И в конце функции переприсваиваем прошлому состоянию светодиодов LED1statusOld текущее состояние светодиодов LED1status.

LED1statusOld = LED1status;
LED2statusOld = LED2status;

С функцией oled_text() разобрались, и теперь ее осталось вызвать в основном цикле loop().

void loop() {
  server.handleClient();
  oled_text();
  if (LED1status)
  {
    digitalWrite(LED1pin, HIGH);
  }
  else
  {
    digitalWrite(LED1pin, LOW);
  }
  if (LED2status)
  {
    digitalWrite(LED2pin, HIGH);
  }
  else
  {
    digitalWrite(LED2pin, LOW);
  }
}

Для вывода синхронного статуса подключённых устройств к ESP32 и ESP8266, нужно дописать не так и много кода. Аналогично, можно выводить показание температуры и влажности с датчика DHT11, DHT22, который мы подключали к ESP32 и ESP8266 в прошлом уроке. А также, можно выводить данные с других датчиков и сенсоров. В следующем уроке про ESP32 расширим наш кругозор и изучим новые возможности данной отладочной платы.

Предыдущий урок: Урок 2. Подключаем DHT11, DHT22 к ESP32, ESP8266. Показание на веб-странице.

Понравился Урок 2. ESP32 и ESP8266 с выводом статуса на веб-страницу и на OLED дисплей? Не забудь поделиться с друзьями в соц. сетях.

А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в группу на Facebook.

Спасибо за внимание!

Технологии начинаются с простого!

Фотографии к статье

Файлы для скачивания

Скетч для ESP32 и ESP8266, вывод статуса на веб-страницу и на OLED дисплей Скетч для ESP32 и ESP8266, вывод статуса на веб-страницу и на OLED дисплей.ino7 Kb 84 Скачать
Скетч ESP32 вывод геометрических фигур на OLED дисплей Скетч ESP32 вывод геометрических фигур на OLED дисплей.ino3 Kb 65 Скачать
Скетч ESP32 - вывод текста на OLED дисплей Скетч ESP32 - вывод текста на OLED дисплей.ino3 Kb 71 Скачать

Комментарии

Ваше Имя*