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

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

ESP32 Веб-сервер с ползунком для управления яркостью светодиода (ШИМ) с использованием Arduino IDE

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

Содержание

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

  2. Необходимые компоненты

  3. Код

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

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

SDK
  • ESP32 размещает веб-сервер, который отображает веб-страницу с ползунком.

  • Когда вы перемещаете ползунок, вы отправляете HTTP-запрос на ESP32 с новым значением ползунка.

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

  • Из HTTP-запроса ESP32 получает текущее значение ползунка.

  • ESP32 настраивает коэффициент заполнения ШИМ в соответствии с значением ползунка.

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

Необходимые компоненты

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

Arduino IDE

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

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

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

  • ESPAsyncWebServer

  • AsyncTCP

Эти библиотеки недоступны для установки через диспетчер библиотек Arduino, поэтому вам нужно скопировать файлы библиотек в папку Libraries вашей установки Arduino. Альтернативно, в Arduino IDE вы можете перейти в Sketch > Include Library > Add .zip Library и выбрать только что загруженные библиотеки.

Код

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

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

Пример: Асинхронный веб-сервер ESP32 для управления PWM

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

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

const int output = 2;
String sliderValue = "0";

const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;

const char* PARAM_INPUT = "value";

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; text-align: center;}
    h2 {font-size: 2.3rem;}
    p {font-size: 1.9rem;}
    body {max-width: 400px; margin:auto; padding-bottom: 25px;}
    .slider { width: 360px; height: 25px; background: #FFD65C; }
    .slider::-webkit-slider-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="255" 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";

String processor(const String& var) {
  if (var == "SLIDERVALUE") {
    return sliderValue;
  }
  return String();
}

void setup() {
  Serial.begin(115200);
  ledcAttachChannel(output, freq, resolution, ledChannel);
  ledcWrite(output, sliderValue.toInt());

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Подключение к WiFi...");
  }

  Serial.println(WiFi.localIP());

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

  server.on("/slider", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    if (request->hasParam(PARAM_INPUT)) {
      inputMessage = request->getParam(PARAM_INPUT)->value();
      sliderValue = inputMessage;
      ledcWrite(output, sliderValue.toInt());
    } else {
      inputMessage = "Сообщение не отправлено";
    }
    Serial.println(inputMessage);
    request->send(200, "text/plain", "OK");
  });

  server.begin();
}

void loop() {
}

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

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

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

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

#include <WiFi.h>
#include <AsyncTCP.h>

Установка сетевых учетных данных

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

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

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

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

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

String sliderValue = "0";

Настройка свойств ШИМ

Следующие строки определяют свойства ШИМ для управления светодиодом.

const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;

Мы будем использовать 8-битное разрешение, что означает, что вы можете управлять яркостью светодиода, используя значение от 0 до 255.

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

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

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

const char* PARAM_INPUT = "value";

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

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

Теперь давайте перейдем к созданию страницы веб-сервера.

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

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

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

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

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

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

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

  • Класс для стилизации ползунка (class=»slider»).

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

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

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

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

<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>

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

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

Затем мы устанавливаем метку ползунка (чей идентификатор 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

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

Processor

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

// Заменяет заполнители на странице вашего веб-сервера
String processor(const String& var){
  if (var == "SLIDERVALUE"){
    return sliderValue;
  }
  return String();
}

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

setup()

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

Serial.begin(115200);

Настраиваем пин светодиода с функциями ШИМ, определенными ранее.

// Настройка функций ШИМ светодиода
ledcAttachChannel(output, freq, resolution, ledChannel);

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

ledcWrite(output, sliderValue.toInt());

Подключаемся к локальной сети и печатаем IP-адрес ESP32.

// Подключение к Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.println("Подключение к WiFi..");
}

// Печать локального IP-адреса ESP
Serial.println(WiFi.localIP());

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

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

// Маршрут для корневой / веб-страницы
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

// Отправить GET-запрос на <ESP_IP>/slider?value=<inputMessage>
server.on("/slider", HTTP_GET, [] (AsyncWebServerRequest *request) {
  String inputMessage;
  if (request->hasParam(PARAM_INPUT)) {
    inputMessage = request->getParam(PARAM_INPUT)->value();
    sliderValue = inputMessage;
    ledcWrite(output, sliderValue.toInt());
  }
  else {
    inputMessage = "Сообщение не отправлено";
  }
  Serial.println(inputMessage);
  request->send(200, "text/plain", "OK");
});

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

// Маршрут для корневой / веб-страницы
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

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

server.on("/slider", HTTP_GET, [](AsyncWebServerRequest *request) {
  String inputMessage;
  if (request->hasParam(PARAM_INPUT)) {
    inputMessage = request->getParam(PARAM_INPUT)->value();
    sliderValue = inputMessage;
    ledcWrite(output, sliderValue.toInt());
  }
  else {
    inputMessage = "Сообщение не отправлено";
  }
  Serial.println(inputMessage);
  request->send(200, "text/plain", "OK");
});

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

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

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

ledcWrite(output, sliderValue.toInt());

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

server.begin();

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

void loop() {}

Вот так и работает код.

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

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

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

SDK

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

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

SDK

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

Заключение

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

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