Хотите добавить информативности, и сделать более интересными свои проекты с ESP32? Или, может быть, вы хотите отобразить IP-адрес вашего ESP32, не прибегая к выводу информации в последовательный монитор порта? OLED-дисплеи (органические светодиоды) могут идеально подойти! Они сверхлегкие, достаточно тонкие, теоретически гибкие, и дают более яркое и четкое изображение.
Для изучения данного урока рекомендую посмотреть предыдущий урок про ESP32 и ESP8266:
Базовый код, основного примера, будем использоваться из вышеуказанного урока.
Также, в данном уроке, расскажу поверхностно про OLED дисплей, и его возможности. Больше информации в моих уроках по подключению OLED дисплея к Arduino:
Подключить довольно просто. Начните с подключения вывода VCC к выходу 3,3 В на ESP32, и подключите GND к земле. На следующей схеме показано, как подключить дисплея OLED к ESP32.
Затем подключите контакт SCL к контакту D22 на ESP32, и подключите контакт SDA к контакту D21 на ESP32.
Теперь мы готовы загрузить код и что-нибудь вывести на дисплей.
Контроллер SSD1306 OLED-дисплея имеет гибкий, но сложный драйвер. Для использования контроллера SSD1306 требуются обширные знания в области адресации памяти. К счастью, библиотека Adafruit SSD1306 была написана, чтобы скрыть сложности контроллера SSD1306, и, чтобы мы могли выполнять простые команды для управления дисплеем.
Чтобы установить библиотеку, перейдите Скетч > Подключить библиотеку > Управлять библиотеками ... Подождите, пока диспетчер библиотек загрузит индекс библиотек и обновит список установленных библиотек.
Отфильтруйте результаты поиска, набрав «adafruit ssd1306». Должна быть пара записей. Ищите Adafruit SSD1306 от Adafruit . Щелкните эту запись и выберите «Установить».
Библиотека Adafruit SSD1306 - это аппаратно-зависимая библиотека, которая обрабатывает функции нижнего уровня. Она должна быть соединена с библиотекой Adafruit GFX, для отображения графических примитивов, таких как точки, линии, круги, прямоугольники и т. д. Установите и эту библиотеку.
Следующий скетч для ESP32 выведет «Hello World!» на дисплей, а также выведет:
Это даст вам полное представление о том, как использовать 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. Выводим текст, рисуем фигуры.
Для отображения текста на экране, нам необходимо установить размер шрифта. Это можно сделать, вызвав 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.
// 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). Для чисел с плавающей запятой этот параметр указывает количество используемых знаков после точки. Например:
// 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. Это прокрутит только первую строчку дисплея.
Так как Adafruit SSD1306 и Adafruit GFX совместимы с ESP32 и ESP8266, код для вывода теста не будет отличаться для обеих плат. Достаточно подключить отладочную плату к компьютеру, настроить Arduino IDE и загрузить код.
Подключение довольно простое. Начните с подключения вывода VCC к выходу 3,3 В на NodeMCU и подключите GND к земле.
Затем, подключите контакт SCL к контакту D1 на NodeMCU, и подключите контакт SDA к контакту D2 на NodeMCU.
Теперь все готово и можно загрузить код, и вывести текст на дисплей.
В начале урока рекомендовал посмотреть несколько уроков, прежде чем приступать к данному уроку. Сейчас мы будем выводить русские символы на OLED дисплей, воспользовавшись одним из этих уроков. Но весь этап настройки я повторю, чтобы закрепить знания, и вам лишний раз не искать, где скачать дополнительную информацию для вывода русских символов на OLED дисплей, подключённому к ESP32 или ESP8266.
/* Функция перекодировки русских букв из 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; }
display.cp437(true);
После того, как выполнили все 5 пунктов настройки Arduino IDE. Изменим вывод надписи:
display.println("Hello,world!");
На
display.println(utf8rus("Привет МИР!"));
Полный код примера вывода русских символов на OLED, подключение ESP32 и ESP8266.
В этом примере мы выведем на 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. Выводим текст, рисуем фигуры». И пишите ваши вопросы в комментариях.
Пришло время сделать что-то более интересное и применимое в жизни. В предыдущем уроке мы подключали светодиоды и создавали Веб-сервер, позволяющий управлять данными светодиодами через веб-интерфейс. Достаточно было загрузить адрес нашего устройства в строке браузера, и при нажатии кнопок, включать и выключать светодиод. При этом, в браузере мы видели статус, включен светодиод или выключен. Как же сделать так, чтобы и без приложения можно было определить, включен светодиод или нет? У вас возник вопрос: "светодиод светится и не заметить, что он работает не сложно?" Но вместо светодиода мы можем подключить нагрузку, используя реле или MOSFET транзистор. И все поместить в корпус, или разместить в распределительной коробке. И тогда, как определить, что у нас включено, а что выключено? Для этого мы и подключим OLED дисплей и выведем, для начала, статус включения светодиода. А что подключите вы, - это уже ваше решение.
Как видно, мы просто совместили схему из прошлого урока, и схему подключения 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, а в данном уроке подключение 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; } }
Сперва, нам нужно определить, изменилось ли состояние светодиодов. Для этого сравниваем текущее и предыдущее состояние светодиодов. Например, мы нажали на включение первого светодиода. Переменная 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 дисплей.ino | 7 Kb | 1322 | Скачать |
![]() |
Скетч ESP32 вывод геометрических фигур на OLED дисплей.ino | 3 Kb | 1136 | Скачать |
![]() |
Скетч ESP32 - вывод текста на OLED дисплей.ino | 3 Kb | 1202 | Скачать |
когда планируется 4 урок по есп32 вывод данных с дачиков температуры и тд?
Уроки ESP32 и ESP8266
29 ноября , 2020
Комментариев:1
Файлов для скачивания:3
Фото:6
Понравилась статья? Нажми
Виджеты для Easy HMI
Читайте также
Мы в соц сетях
Комментарии