ESP8266 NodeMCU Веб-сервер со слайдером: Управление яркостью светодиода (ШИМ)

В этом руководстве показано, как создать веб-сервер ESP8266 NodeMCU со слайдером для управления яркостью светодиода. Вы узнаете, как добавить слайдер в ваши проекты веб-серверов, получить его значение и сохранить его в переменной, которую ESP8266 может использовать. Мы будем использовать это значение для управления коэффициентом заполнения ШИМ-сигнала и изменения яркости светодиода. Вместо светодиода вы можете управлять, например, сервоприводом.

ESP8266 NodeMCU Веб-сервер со слайдером для управления яркостью светодиода через ШИМ с использованием Arduino IDE

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

Обзор проекта

ESP8266 NodeMCU Веб-сервер со слайдером для управления яркостью светодиода
  • ESP8266 размещает веб-сервер, который отображает веб-страницу со слайдером;

  • Когда вы перемещаете слайдер, вы отправляете HTTP-запрос на ESP8266 с новым значением слайдера;

  • HTTP-запрос приходит в следующем формате: GET/slider?value=SLIDERVALUE, где SLIDERVALUE – это число от 0 до 1023. Вы можете изменить слайдер, чтобы включить любой другой диапазон;

  • Из HTTP-запроса ESP8266 получает текущее значение слайдера;

  • ESP8266 регулирует коэффициент заполнения ШИМ в соответствии со значением слайдера;

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

Необходимые условия

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

Arduino IDE

Мы будем программировать плату ESP8266 NodeMCU с использованием Arduino IDE, поэтому перед тем, как продолжить это руководство, убедитесь, что у вас установлена плата ESP8266 в вашей Arduino IDE.

Библиотеки асинхронного веб-сервера

Мы будем создавать веб-сервер с использованием следующих библиотек:

Вы можете установить эти библиотеки с помощью Менеджера библиотек Arduino. Перейдите в Sketch > Include Library > Manage Libraries и найдите библиотеки по их названиям.

Код

Следующий код управляет яркостью встроенного светодиода ESP8266 с помощью слайдера на веб-сервере. Другими словами, вы можете изменять коэффициент заполнения ШИМ с помощью слайдера. Это может быть полезно для управления яркостью светодиода или сервоприводом, например.

Скопируйте код в вашу Arduino IDE. Вставьте свои сетевые учётные данные, и код заработает сразу.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp8266-nodemcu-web-server-slider-pwm/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/

// Import required libraries
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

const int output = 2;

String sliderValue = "0";

const char* PARAM_INPUT = "value";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>ESP Web Server</title>
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    h2 {font-size: 2.3rem;}
    p {font-size: 1.9rem;}
    body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}
    .slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #FFD65C;
      outline: none; -webkit-transition: .2s; transition: opacity .2s;}
    .slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background: #003249; cursor: pointer;}
    .slider::-moz-range-thumb { width: 35px; height: 35px; background: #003249; cursor: pointer; }
  </style>
</head>
<body>
  <h2>ESP Web Server</h2>
  <p><span id="textSliderValue">%SLIDERVALUE%</span></p>
  <p><input type="range" onchange="updateSliderPWM(this)" id="pwmSlider" min="0" max="1023" value="%SLIDERVALUE%" step="1" class="slider"></p>
<script>
function updateSliderPWM(element) {
  var sliderValue = document.getElementById("pwmSlider").value;
  document.getElementById("textSliderValue").innerHTML = sliderValue;
  console.log(sliderValue);
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "/slider?value="+sliderValue, true);
  xhr.send();
}
</script>
</body>
</html>
)rawliteral";

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if (var == "SLIDERVALUE"){
    return sliderValue;
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  analogWrite(output, sliderValue.toInt());

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", index_html, processor);
  });

  // Send a GET request to <ESP_IP>/slider?value=<inputMessage>
  server.on("/slider", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    // GET input1 value on <ESP_IP>/slider?value=<inputMessage>
    if (request->hasParam(PARAM_INPUT)) {
      inputMessage = request->getParam(PARAM_INPUT)->value();
      sliderValue = inputMessage;
      analogWrite(output, sliderValue.toInt());
    }
    else {
      inputMessage = "No message sent";
    }
    Serial.println(inputMessage);
    request->send(200, "text/plain", "OK");
  });

  // Start server
  server.begin();
}

void loop() {

}

Просмотреть исходный код

Как работает код

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

Импорт библиотек

Сначала импортируйте необходимые библиотеки. Библиотеки ESP8266WiFi, ESPAsyncWebServer и ESPAsyncTCP необходимы для создания веб-сервера.

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

Настройка сетевых учётных данных

Вставьте свои сетевые учётные данные в следующие переменные, чтобы ESP8266 мог подключиться к вашей локальной сети.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Определение переменных

Мы будем управлять яркостью встроенного светодиода ESP8266. Встроенный светодиод соответствует GPIO 2. Сохраните GPIO, которым вы хотите управлять, в переменной output.

const int output = 2;

Переменная sliderValue будет хранить значение слайдера. При запуске она установлена на ноль.

String sliderValue = "0";

Входные параметры

Переменная PARAM_INPUT будет использоваться для «поиска» значения слайдера в запросе, полученном ESP8266 при перемещении слайдера. (Помните: ESP8266 получит запрос вида GET/slider?value=SLIDERVALUE)

const char* PARAM_INPUT = "value";

Она будет искать value в URL и получать присвоенное ему значение.

Создание веб-страницы

Теперь перейдём к странице веб-сервера.

Объяснение работы веб-страницы слайдера ESP8266 NodeMCU

Веб-страница для этого проекта довольно простая. Она содержит один заголовок, один абзац и один элемент ввода типа range.

Давайте посмотрим, как создаётся веб-страница.

Весь HTML-текст со стилями хранится в переменной index_html. Теперь мы рассмотрим HTML-текст и посмотрим, что делает каждая часть.

Следующий тег <meta> делает вашу веб-страницу адаптивной в любом браузере.

<meta name="viewport" content="width=device-width, initial-scale=1">

Между тегами <title> </title> указывается заголовок нашего веб-сервера. Заголовок – это текст, который отображается на вкладке веб-браузера.

Стили

Между тегами <style></style> мы добавляем CSS для стилизации веб-страницы.

<style>
  html {font-family: Arial; display: inline-block; text-align: center;}
  h2 {font-size: 2.3rem;}
  p {font-size: 1.9rem;}
  body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}
  .slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #FFD65C;
    outline: none; -webkit-transition: .2s; transition: opacity .2s;}
  .slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background: #003249; cursor: pointer;}
  .slider::-moz-range-thumb { width: 35px; height: 35px; background: #003249; cursor: pointer; }
</style>

По сути, мы настраиваем HTML-страницу для отображения текста шрифтом Arial, в виде блока без отступов, с выравниванием по центру.

html {font-family: Arial; display: inline-block; text-align: center;}

Следующие строки устанавливают размер шрифта для заголовка (h2) и абзаца (p).

h2 {font-size: 2.3rem;}
p {font-size: 1.9rem;}

Установите свойства тела HTML.

body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}

Следующие строки настраивают слайдер:

.slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #FFD65C;
      outline: none; -webkit-transition: .2s; transition: opacity .2s;}
.slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background: #003249; cursor: pointer;}
.slider::-moz-range-thumb { width: 35px; height: 35px; background: #003249; cursor: pointer; }

Тело HTML

Внутри тегов <body></body> мы добавляем содержимое веб-страницы.

Теги <h2></h2> добавляют заголовок на веб-страницу. В данном случае текст «ESP Web Server», но вы можете добавить любой другой текст.

<h2>ESP Web Server</h2>

Первый абзац будет содержать текущее значение слайдера. Этому конкретному HTML-тегу присвоен id textSliderValue, чтобы мы могли ссылаться на него позже.

<p><span id="textSliderValue">%SLIDERVALUE%</span></p>

%SLIDERVALUE% – это заполнитель (placeholder) для значения слайдера. Он будет заменён ESP8266 на фактическое значение при отправке страницы в браузер. Это полезно для отображения текущего значения при первом доступе к браузеру.

Создание слайдера

Чтобы создать слайдер в HTML, используется тег <input>. Тег <input> определяет поле, в которое пользователь может вводить данные.

Существует большое разнообразие типов ввода. Чтобы определить слайдер, используйте атрибут «type» со значением «range». Для слайдера также необходимо определить минимальный и максимальный диапазон с помощью атрибутов «min» и «max» (в данном случае 0 и 1023 соответственно).

<p><input type="range" onchange="updateSliderPWM(this)" id="pwmSlider" min="0" max="1023" value="%SLIDERVALUE%" step="1" class="slider"></p>

Вам также необходимо определить другие атрибуты, такие как:

  • атрибут step определяет интервал между допустимыми числами. В нашем случае он установлен на 1;

  • class для стилизации слайдера (class=»slider»);

  • id для обновления текущей позиции, отображаемой на веб-странице;

  • атрибут onchange для вызова функции (updateSliderPWM(this)) для отправки HTTP-запроса на ESP8266 при перемещении слайдера. Ключевое слово this ссылается на текущее значение слайдера.

Добавление JavaScript в HTML-файл

Далее вам нужно добавить JavaScript-код в ваш HTML-файл с помощью тегов <script> и </script>. Вам нужно добавить функцию updateSliderPWM(), которая будет отправлять запрос на ESP8266 с текущим значением слайдера.

function updateSliderPWM(element) {
  var sliderValue = document.getElementById("pwmSlider").value;
  document.getElementById("textSliderValue").innerHTML = sliderValue;
  console.log(sliderValue);
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "/slider?value="+sliderValue, true);
  xhr.send();
}

Следующая строка получает текущее значение слайдера по его id и сохраняет его в JavaScript-переменной sliderValue. Ранее мы присвоили id слайдера значение pwmSlider. Поэтому мы получаем его следующим образом:

var sliderValue = document.getElementById("pwmSlider").value;

После этого мы устанавливаем метку слайдера (id которой – textSliderValue) на значение, сохранённое в переменной sliderValue.

Наконец, выполняется HTTP GET-запрос.

var xhr = new XMLHttpRequest();
xhr.open("GET", "/slider?value="+sliderValue, true);
xhr.send();

Например, когда слайдер находится в положении 0, выполняется HTTP GET-запрос по следующему URL:

http://ESP-IP-ADDRESS/slider?value=0

А когда значение слайдера равно 200, запрос будет по следующему URL.

http://ESP-IP-ADDRESS/slider?value=200

Таким образом, когда ESP8266 получает GET-запрос, он может извлечь параметр value из URL и соответствующим образом управлять ШИМ-сигналом, как мы увидим в следующих разделах.

Процессор

Теперь нам нужно создать функцию processor(), которая заменит заполнители в нашем HTML-тексте текущим значением слайдера при первом доступе через браузер.

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if (var == "SLIDERVALUE"){
    return sliderValue;
  }
  return String();
}

Когда запрашивается веб-страница, мы проверяем, содержит ли HTML какие-либо заполнители. Если находится заполнитель %SLIDERVALUE%, мы возвращаем значение, сохранённое в переменной sliderValue.

setup()

В setup() инициализируем Serial Monitor для целей отладки.

Serial.begin(115200);

Установите коэффициент заполнения ШИМ-сигнала на значение, сохранённое в sliderValue (при запуске ESP8266 оно установлено на 0).

analogWrite(output, sliderValue.toInt());

Чтобы узнать больше о ШИМ на ESP8266, прочитайте наше руководство: ESP8266 PWM с Arduino IDE (аналоговый выход).

Подключитесь к локальной сети и выведите IP-адрес ESP8266.

// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.println("Connecting to WiFi..");
}

// Print ESP Local IP Address
Serial.println(WiFi.localIP());

Обработка запросов

Наконец, добавьте следующие строки кода для обработки веб-сервера.

// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

// Send a GET request to <ESP_IP>/slider?value=<inputMessage>
server.on("/slider", HTTP_GET, [] (AsyncWebServerRequest *request) {
  String inputMessage;
  // GET input1 value on <ESP_IP>/slider?value=<inputMessage>
  if (request->hasParam(PARAM_INPUT)) {
    inputMessage = request->getParam(PARAM_INPUT)->value();
    sliderValue = inputMessage;
    ledcWrite(ledChannel, sliderValue.toInt());
  }
  else {
    inputMessage = "No message sent";
  }
  Serial.println(inputMessage);
  request->send(200, "text/plain", "OK");
});

Когда мы делаем запрос на корневой URL, мы отправляем HTML-текст, хранящийся в переменной index_html. Нам также нужно передать функцию processor(), которая заменит все заполнители правильными значениями.

// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

Нам нужен ещё один обработчик, который сохранит текущее значение слайдера и установит яркость светодиода соответствующим образом.

server.on("/slider", HTTP_GET, [] (AsyncWebServerRequest *request) {
  String inputMessage;
  // GET input1 value on <ESP_IP>/slider?value=<inputMessage>
  if (request->hasParam(PARAM_INPUT)) {
    inputMessage = request->getParam(PARAM_INPUT)->value();
    sliderValue = inputMessage;
    ledcWrite(ledChannel, sliderValue.toInt());
  }
  else {
    inputMessage = "No message sent";
  }
  Serial.println(inputMessage);
  request->send(200, "text/plain", "OK");
});

По сути, мы получаем значение слайдера в следующих строках:

if (request->hasParam(PARAM_INPUT)) {
  inputMessage = request->getParam(PARAM_INPUT)->value();
  sliderValue = inputMessage;

Затем обновляем яркость светодиода (коэффициент заполнения ШИМ) с помощью функции ledcWrite(), которая принимает в качестве аргументов канал, которым вы хотите управлять, и значение.

ledcWrite(ledChannel, sliderValue.toInt());

Наконец, запускаем сервер.

server.begin();

Поскольку это асинхронный веб-сервер, нам не нужно ничего писать в loop().

void loop(){

}

Вот и всё, что касается работы кода.

Загрузка кода

Теперь загрузите код на ваш ESP8266. Убедитесь, что у вас выбрана правильная плата и COM-порт.

После загрузки откройте Serial Monitor на скорости 115200 бод. Нажмите кнопку сброса ESP8266. IP-адрес ESP8266 должен быть выведен в серийном мониторе.

ESP32 ESP8266 ШИМ Веб-сервер Arduino IDE Serial Monitor IP-адрес

Демонстрация веб-сервера

Откройте браузер и введите IP-адрес ESP8266. Ваш веб-сервер должен отобразить слайдер и его текущее значение.

Демонстрация работы веб-сервера ESP8266 NodeMCU со слайдером и ШИМ-выходом

Перемещайте слайдер и наблюдайте, как встроенный светодиод ESP8266 увеличивает и уменьшает яркость.

Заключение

В этом руководстве вы узнали, как добавить слайдер в ваши проекты веб-серверов, получить и сохранить его значение в переменной, которую ESP8266 может использовать. В качестве примера мы управляем ШИМ-сигналом для изменения яркости светодиода. Вместо светодиода вы можете управлять, например, сервоприводом.

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

Если вы используете плату ESP32, прочитайте ESP32 Веб-сервер со слайдером для управления яркостью светодиода (ШИМ).

Надеемся, что этот проект оказался для вас полезным. Вам также могут понравиться следующие руководства:

Узнайте больше о ESP8266 из наших ресурсов:

Спасибо за чтение.