ESP32:Примеры/Веб-сервер на базе ESP32: удаленное управление сервоприводом: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
Нет описания правки
 
(не показана 1 промежуточная версия 1 участника)
Строка 1: Строка 1:
{{ESP32 панель перехода}}
{{ESP32 панель перехода}}
{{Перевод от Сubewriter}}
{{Перевод от Сubewriter}}
{{Myagkij-редактор}}
{{Myagkij-редактор}}
{{Черновик}}


=Веб-сервер на базе ESP32: удаленное управление сервоприводом=
=Веб-сервер на базе ESP32: удаленное управление сервоприводом=
Строка 68: Строка 65:
Давайте начнем с разбора [[HTML-код]]а, который [[ESP32]] будет отсылать вашему [[браузер]]у. Этот [[HTML-код]] также можно найти по [https://github.com/RuiSantosdotme/ESP32-Course/blob/master/code/Servo/slider.html этой ссылке].
Давайте начнем с разбора [[HTML-код]]а, который [[ESP32]] будет отсылать вашему [[браузер]]у. Этот [[HTML-код]] также можно найти по [https://github.com/RuiSantosdotme/ESP32-Course/blob/master/code/Servo/slider.html этой ссылке].


<syntaxhighlight lang="html5" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="html5" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<html>
Строка 115: Строка 112:
Компоненты типа <input> бывают разными. Чтобы сделать ползунок, нам нужно воспользоваться атрибутом ''«type»'' и задать ему значение ''«range»''. Кроме того, для ползунка нужно задать минимальное и максимальное значения диапазона при помощи атрибутов ''«min»'' и ''«max»''.
Компоненты типа <input> бывают разными. Чтобы сделать ползунок, нам нужно воспользоваться атрибутом ''«type»'' и задать ему значение ''«range»''. Кроме того, для ползунка нужно задать минимальное и максимальное значения диапазона при помощи атрибутов ''«min»'' и ''«max»''.


<syntaxhighlight lang="html5" enclose="div">
<syntaxhighlight lang="html5">
<input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>
<input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>
</syntaxhighlight>
</syntaxhighlight>
Строка 128: Строка 125:
Далее при помощи тегов <script> и </script> добавляем [[JS-код]] в [[HTML-файл]]. Фрагмент кода ниже обновляет позицию ползунка на веб-странице:
Далее при помощи тегов <script> и </script> добавляем [[JS-код]] в [[HTML-файл]]. Фрагмент кода ниже обновляет позицию ползунка на веб-странице:


<syntaxhighlight lang="html5" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="html5" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
var slider = document.getElementById("servoSlider");
var slider = document.getElementById("servoSlider");
var servoP = document.getElementById("servoPos");
var servoP = document.getElementById("servoPos");
Строка 140: Строка 137:
Фрагмент кода ниже делает [[HTTP-запрос]] [[GET]] на [[IP-адрес]] [[ESP32]] со ссылкой '''«/?value=[SLIDER_POSITION]&»'''.  
Фрагмент кода ниже делает [[HTTP-запрос]] [[GET]] на [[IP-адрес]] [[ESP32]] со ссылкой '''«/?value=[SLIDER_POSITION]&»'''.  


<syntaxhighlight lang="html5" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="html5" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
$.ajaxSetup({timeout:1000});
$.ajaxSetup({timeout:1000});
function servo(pos) {
function servo(pos) {
Строка 150: Строка 147:
К примеру, если ползунок будет на '''«0»''', мы сделаем [[HTTP-запрос]] [[GET]] с такой [[URL]]-ссылкой:
К примеру, если ползунок будет на '''«0»''', мы сделаем [[HTTP-запрос]] [[GET]] с такой [[URL]]-ссылкой:


<syntaxhighlight lang="html5" enclose="div">
<syntaxhighlight lang="html5">
http://192.168.1.135/?value=0&
http://192.168.1.135/?value=0&
</syntaxhighlight>
</syntaxhighlight>
Строка 156: Строка 153:
А если переместить ползунок на '''180 градусов''', [[URL]]-ссылка будет такой:
А если переместить ползунок на '''180 градусов''', [[URL]]-ссылка будет такой:


<syntaxhighlight lang="html5" enclose="div">
<syntaxhighlight lang="html5">
http://192.168.1.135/?value=180&
http://192.168.1.135/?value=180&
</syntaxhighlight>
</syntaxhighlight>
Строка 166: Строка 163:
Во-первых, подключаем библиотеку «Servo» и создаем экземпляр класса «Servo» под названием «myservo»:
Во-первых, подключаем библиотеку «Servo» и создаем экземпляр класса «Servo» под названием «myservo»:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
#include <Servo.h>
#include <Servo.h>
Servo myservo;
Servo myservo;
Строка 173: Строка 170:
Также создаем переменную, в которой будет храниться номер GPIO-контакта, к которому подключен сервопривод. В данном случае это GPIO13.
Также создаем переменную, в которой будет храниться номер GPIO-контакта, к которому подключен сервопривод. В данном случае это GPIO13.


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
static const int servoPin = 13;
static const int servoPin = 13;
</syntaxhighlight>
</syntaxhighlight>
Строка 179: Строка 176:
Не забудьте отредактировать две строчки кода ниже, вставив туда свои SSID и пароль:
Не забудьте отредактировать две строчки кода ниже, вставив туда свои SSID и пароль:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
const char* ssid = "";
const char* ssid = "";
const char* password = "";
const char* password = "";
Строка 186: Строка 183:
Затем создаем несколько переменных, которые будут использоваться для считывания позиции ползунка из [[HTTP-запрос]]а:
Затем создаем несколько переменных, которые будут использоваться для считывания позиции ползунка из [[HTTP-запрос]]а:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
// несколько переменных для расшифровки значения в HTTP-запросе GET:
// несколько переменных для расшифровки значения в HTTP-запросе GET:
String valueString = String(5);
String valueString = String(5);
Строка 197: Строка 194:
В блоке [[setup()]] привязываем объект '''«servo»''' к GPIO-контакту, к которому подключен сервопривод. Делаем это при помощи функции myservo.attach().
В блоке [[setup()]] привязываем объект '''«servo»''' к GPIO-контакту, к которому подключен сервопривод. Делаем это при помощи функции myservo.attach().


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
myservo.attach(servoPin);  // привязываем сервопривод,
myservo.attach(servoPin);  // привязываем сервопривод,
                             // подключенный к контакту «servoPin»,
                             // подключенный к контакту «servoPin»,
Строка 209: Строка 206:
Фрагмент кода ниже извлекает из [[HTTP-запрос]]а значение ползунка:
Фрагмент кода ниже извлекает из [[HTTP-запрос]]а значение ползунка:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
//GET /?value=180& HTTP/1.1
//GET /?value=180& HTTP/1.1
if(header.indexOf("GET /?value=")>=0) {
if(header.indexOf("GET /?value=")>=0) {
Строка 219: Строка 216:
Перемещая ползунок, вы делаете [[HTTP-запрос]] с [[URL]]-ссылкой, содержащей позицию ползунка между символами '''«=»''' и '''«&»''':
Перемещая ползунок, вы делаете [[HTTP-запрос]] с [[URL]]-ссылкой, содержащей позицию ползунка между символами '''«=»''' и '''«&»''':


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
http://ip-адрес-вашей-esp32/?value=[SLIDER_POSITION]&
http://ip-адрес-вашей-esp32/?value=[SLIDER_POSITION]&
</syntaxhighlight>
</syntaxhighlight>
Строка 225: Строка 222:
Позиция ползунка сохраняется в переменную '''«valueString»'''. Затем мы при помощи метода myservo.write() – и указав в его параметре значение '''«valueString»''' – задаем для [[сервомотор]]а нужную позицию. Переменная '''«valueString»''' – это строка, поэтому нам также необходим метод toInt(), чтобы преобразовать ее в целое число, т.к. это тип данных, принимаемых методом write().
Позиция ползунка сохраняется в переменную '''«valueString»'''. Затем мы при помощи метода myservo.write() – и указав в его параметре значение '''«valueString»''' – задаем для [[сервомотор]]а нужную позицию. Переменная '''«valueString»''' – это строка, поэтому нам также необходим метод toInt(), чтобы преобразовать ее в целое число, т.к. это тип данных, принимаемых методом write().


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
myservo.write(valueString.toInt());
myservo.write(valueString.toInt());
</syntaxhighlight>
</syntaxhighlight>
Строка 270: Строка 267:
==Код==
==Код==


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
/*********
/*********
   Руи Сантос
   Руи Сантос
Строка 422: Строка 419:


=См.также=
=См.также=
{{ads}}


=Внешние ссылки=
=Внешние ссылки=
Строка 429: Строка 424:
<references />
<references />


{{Навигационная таблица/Телепорт}}
{{Навигационная таблица/Портал/ESP32}}


[[Категория:ESP32]]
[[Категория:ESP32]]

Текущая версия от 09:23, 18 июня 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Веб-сервер на базе ESP32: удаленное управление сервоприводом

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

Итак, веб-сервер, который мы создадим:

  • Будет иметь ползунок со значениями от «0» до «180», с помощью которого пользователь будет управлять осью сервопривода;
  • Когда пользователь двигает ползунок, его текущее значение (число рядом со словом "Position:") автоматически обновляется на веб-странице (одновременно с этим автоматически начинает двигаться ось сервопривода), что избавляет от необходимости обновлять веб-страницу вручную.
  • Обновление веб-страницы не поменяет ни значение ползунка, ни позицию оси сервопривода;

Подключение сервопривода к ESP32

Сервомотор оснащен 3 проводами: для питания, заземления и передачи сигнала. Провод для питания, как правило, красный, для заземления – черный или коричневый, а для передачи сигнала – обычно желтый, оранжевый или белый.

Провод Цвет
Питание Красный
Заземление Черный или коричневый
Сигнал Желтый, оранжевый или белый

Если вы используете маленький сервопривод вроде S0009 (см. на фото ниже), его можно запитать напрямую от ESP32.

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

Если вы используете маленький сервопривод вроде S0009, его провода нужно подключить так:

  • Заземление (сервопривод) – к контакту GND (ESP32)
  • Питание (сервопривод) – к контакту VIN (ESP32)
  • Передача сигнала (сервопривод) – к GPIO13 или любому другому ШИМ-контакту (ESP32)
Примечание

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

Как управлять сервомотором?

Ось сервомотора можно расположить под углом от 0 до 180 градусов. Сервомоторы управляются с помощью широтно-импульсной модуляции (ШИМ). То есть ШИМ-сигнал, отправляемый сервомотору, будет определять позицию его оси.

Для управления сервоприводом используется способность ESP32 генерировать ШИМ-сигнал с 50 Гц и соответствующей шириной импульса.

Устанавливаем библиотеку «ESP32 Arduino Servo»

Библиотека «ESP32 Arduino Servo» упрощает управление сервоприводом при помощи ESP32 и IDE Arduino. Чтобы установить ее в IDE Arduino, проделайте следующее:

  1. Кликните тут, чтобы загрузить ZIP-архив библиотеки
  2. Распакуйте скачанный ZIP-архив. У вас должна получиться папка «ESP32-Arduino-Servo-Library-Master»
  3. Переименуйте ее на «ESP32_Arduino_Servo_Library»
  4. Переместите папку «ESP32_Arduino_Servo_Library» в папку «libraries», которая находится в папке, куда установлена ваша IDE Arduino
  5. Наконец, снова откройте IDE Arduino

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

Давайте начнем с разбора HTML-кода, который ESP32 будет отсылать вашему браузеру. Этот HTML-код также можно найти по этой ссылке.

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <style>
    body {
      text-align: center;
      font-family: "Trebuchet MS", Arial;
      margin-left:auto;
      margin-right:auto;
    }
    .slider {
      width: 300px;
    }
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
  <h1>ESP32 with Servo</h1>
  <p>Position: <span id="servoPos"></span></p>
  <input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>
  <script>
    var slider = document.getElementById("servoSlider");
    var servoP = document.getElementById("servoPos");
    servoP.innerHTML = slider.value;
    slider.oninput = function() {
      slider.value = this.value;
      servoP.innerHTML = this.value;
    }
    $.ajaxSetup({timeout:1000});
    function servo(pos) {
      $.get("/?value=" + pos + "&");
      {Connection: close};
    }
  </script>
</body>
</html>

Создаем ползунок

При создании этой веб-страницы нам нужно будет, помимо прочего, создать веб-компонент, известный как «ползунок». Для этого нам понадобится тег <input>. Он задает поле, в которое пользователь может ввести какие-либо данные.

Компоненты типа <input> бывают разными. Чтобы сделать ползунок, нам нужно воспользоваться атрибутом «type» и задать ему значение «range». Кроме того, для ползунка нужно задать минимальное и максимальное значения диапазона при помощи атрибутов «min» и «max».

<input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>

Для ползунка также нужно задать следующие атрибуты:

  • Атрибут «class», задающий CSS-стиль для ползунка
  • Атрибут «id», который обновляет текущую позицию, показываемую на веб-странице
  • Атрибут «onchange», при перемещении ползунка вызывающий функцию servo() для отправки HTTP-запроса на ESP32

Добавляем JavaScript-код в HTML-файл

Далее при помощи тегов <script> и </script> добавляем JS-код в HTML-файл. Фрагмент кода ниже обновляет позицию ползунка на веб-странице:

var slider = document.getElementById("servoSlider");
var servoP = document.getElementById("servoPos");
servoP.innerHTML = slider.value;
slider.oninput = function() {
 slider.value = this.value;
 servoP.innerHTML = this.value;
}

Фрагмент кода ниже делает HTTP-запрос GET на IP-адрес ESP32 со ссылкой «/?value=[SLIDER_POSITION]&».

$.ajaxSetup({timeout:1000});
function servo(pos) {
$.get("/?value=" + pos + "&");
{Connection: close};
}

К примеру, если ползунок будет на «0», мы сделаем HTTP-запрос GET с такой URL-ссылкой:

http://192.168.1.135/?value=0&

А если переместить ползунок на 180 градусов, URL-ссылка будет такой:

http://192.168.1.135/?value=180&

Таким образом, получая запрос GET, ESP32 также получает ссылку со значением для сервопривода, а затем перемещает ось сервопривода на позицию, заданную в этой ссылке.

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

Во-первых, подключаем библиотеку «Servo» и создаем экземпляр класса «Servo» под названием «myservo»:

#include <Servo.h>
Servo myservo;

Также создаем переменную, в которой будет храниться номер GPIO-контакта, к которому подключен сервопривод. В данном случае это GPIO13.

static const int servoPin = 13;

Не забудьте отредактировать две строчки кода ниже, вставив туда свои SSID и пароль:

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

Затем создаем несколько переменных, которые будут использоваться для считывания позиции ползунка из HTTP-запроса:

// несколько переменных для расшифровки значения в HTTP-запросе GET:
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;

setup()

В блоке setup() привязываем объект «servo» к GPIO-контакту, к которому подключен сервопривод. Делаем это при помощи функции myservo.attach().

myservo.attach(servoPin);   // привязываем сервопривод,
                            // подключенный к контакту «servoPin»,
                            // к объекту «myservo»

loop()

Вы должны быть уже знакомы с частью блока loop(), которая создает веб-сервер и отправляет HTML-код для показа веб-страницы, так что мы ее пропустим.

Фрагмент кода ниже извлекает из HTTP-запроса значение ползунка:

//GET /?value=180& HTTP/1.1
if(header.indexOf("GET /?value=")>=0) {
  pos1 = header.indexOf('=');
  pos2 = header.indexOf('&');
  valueString = header.substring(pos1+1, pos2);

Перемещая ползунок, вы делаете HTTP-запрос с URL-ссылкой, содержащей позицию ползунка между символами «=» и «&»:

http://ip-адрес-вашей-esp32/?value=[SLIDER_POSITION]&

Позиция ползунка сохраняется в переменную «valueString». Затем мы при помощи метода myservo.write() – и указав в его параметре значение «valueString» – задаем для сервомотора нужную позицию. Переменная «valueString» – это строка, поэтому нам также необходим метод toInt(), чтобы преобразовать ее в целое число, т.к. это тип данных, принимаемых методом write().

myservo.write(valueString.toInt());

Тестируем веб-сервер

Теперь проверяем, правильные ли в IDE Arduino выставлены COM-порт и плата, а также вписаны ли в код учетные данные (SSID и пароль) вашей сети. Затем загружаем код на ESP32 и открываем монитор порта на скорости 115200 бод.

Нажимаем на кнопку EN на ESP32, чтобы перезапустить плату, а затем копируем локальный IP-адрес, напечатанный платой в мониторе порта:

Открываем браузер, вставляем в адресную строку скопированный IP-адрес ESP32 и нажимаем на  ↵ Enter . В браузере должна появиться веб-страница, созданная нами ранее. Подвигайте ползунок, чтобы изменить положение оси сервопривода.

Примечание

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

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

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

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

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

Необходимое оборудование

Схема

Примечание

На данной схеме используется плата ESP32S-HiLetgo, если вы используете другую, сверьтесь с вашей распиновкой.

В нашем случае мы подключаем провод для передачи данных к контакту GPIO13. Схема подключения всех остальных компонентов показана ниже.

Код

/*********
  Руи Сантос
  Более подробно о проекте на: http://randomnerdtutorials.com  
*********/

#include <WiFi.h>
#include <Servo.h>

Servo myservo;  // создаем экземпляр класса «Servo»,
                // чтобы с его помощью управлять сервоприводом;
                // большинство плат позволяют
                // создать 12 объектов класса «Servo»

// GPIO-контакт, к которому подключен сервопривод:
static const int servoPin = 13;

// вставьте здесь учетные данные своей сети:
const char* ssid     = "";
const char* password = "";

// создаем веб-сервер на порте «80»:
WiFiServer server(80);

// переменная для хранения HTTP-запроса:
String header;

// несколько переменных для расшифровки значения в HTTP-запросе GET:
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;

void setup() {
  Serial.begin(115200);

  myservo.attach(servoPin);  // привязываем сервопривод,
                             // подключенный к контакту «servoPin»,
                             // к объекту «myservo»

  // подключаемся к WiFi при помощи заданных выше SSID и пароля: 
  Serial.print("Connecting to ");  //  "Подключаемся к "
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // печатаем локальный IP-адрес и запускаем веб-сервер:
  Serial.println("");
  Serial.println("WiFi connected.");  //  "WiFi подключен."
  Serial.println("IP address: ");     //  "IP-адрес: "
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  // начинаем прослушивать входящих клиентов:
  WiFiClient client = server.available();

  if (client) {                     // если подключился новый клиент,     
    Serial.println("New Client.");  // печатаем сообщение
                                    // «Новый клиент.»
                                    // в мониторе порта;
    String currentLine = "";        // создаем строку для хранения
                                    // входящих данных от клиента;
    while (client.connected()) {    // цикл while() будет работать
                                    // все то время, пока клиент
                                    // будет подключен к серверу;
      if (client.available()) {     // если у клиента есть данные,
                                    // которые можно прочесть, 
        char c = client.read();     // считываем байт, а затем    
        Serial.write(c);            // печатаем его в мониторе порта
        header += c;
        if (c == '\n') {            // если этим байтом является
                                    // символ новой строки
          // если получили два символа новой строки подряд,
          // то это значит, что текущая строчка пуста;
          // это конец HTTP-запроса клиента,
          // а значит – пора отправлять ответ:
          if (currentLine.length() == 0) {
            // HTTP-заголовки всегда начинаются
            // с кода ответа (например, «HTTP/1.1 200 OK»)
            // и информации о типе контента
            // (чтобы клиент понимал, что получает);
            // в конце пишем пустую строчку:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
                       //  "Соединение: отключено"
            client.println();

            // показываем веб-страницу:
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}");
            client.println(".slider { width: 300px; }</style>");
            client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");
                     
            // веб-страница:
            client.println("</head><body><h1>ESP32 with Servo</h1>");
                                        //  "Управление сервомотором
                                        //   с помощью платы ESP32"
            client.println("<p>Position: <span id=\"servoPos\"></span></p>");          
            client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""+valueString+"\"/>");
            
            client.println("<script>var slider = document.getElementById(\"servoSlider\");");
            client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");
            client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");
            client.println("$.ajaxSetup({timeout:1000}); function servo(pos) { ");
            client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}</script>");
           
            client.println("</body></html>");     
            
            //GET /?value=180& HTTP/1.1
            if(header.indexOf("GET /?value=")>=0) {
              pos1 = header.indexOf('=');
              pos2 = header.indexOf('&');
              valueString = header.substring(pos1+1, pos2);
              
              // вращаем ось сервомотора:
              myservo.write(valueString.toInt());
              Serial.println(valueString); 
            }         
            // конец HTTP-ответа задается 
            // с помощью дополнительной пустой строки:
            client.println();
            // выходим из цикла while(): 
            break;
          } else { // если получили символ новой строки,
                   // очищаем текущую строку «currentLine»:
            currentLine = "";
          }
        } else if (c != '\r') {  // если получили любые данные,
                                 // кроме символа возврата каретки,
          currentLine += c;      // добавляем эти данные 
                                 // в конец строки «currentLine»
        }
      }
    }
    // очищаем переменную «header»:
    header = "";
    // отключаем соединение:
    client.stop();
    Serial.println("Client disconnected.");
               //  "Клиент отключился."
    Serial.println("");
  }
}

См.также

Внешние ссылки