Веб-сервер ESP32 для управления сервомотором в Arduino IDE
В этом руководстве вы узнаете, как создать веб-сервер на ESP32, который управляет положением вала сервомотора с помощью ползунка. Сначала мы кратко рассмотрим, как управлять сервомотором с помощью ESP32, а затем создадим веб-сервер.
Обновлено 13 июня 2024 г.
Необходимые компоненты
Для выполнения этого руководства вам потребуются следующие компоненты:
Вы можете использовать ссылки выше или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!
Подключение сервомотора к ESP32
Сервомоторы имеют три провода: питание, земля и сигнал. Провод питания обычно красный, провод GND — чёрный или коричневый, а сигнальный провод обычно жёлтый, оранжевый или белый.
Провод |
Цвет |
|---|---|
Питание |
Красный |
GND |
Чёрный или коричневый |
Сигнал |
Жёлтый, оранжевый или белый |
При использовании небольшого сервомотора, такого как S0009, показанного на рисунке ниже, вы можете питать его напрямую от ESP32.
Но если вы используете несколько сервомоторов или другую модель, вам, вероятно, потребуется запитать сервомоторы от внешнего источника питания.
Если вы используете небольшой сервомотор, такой как S0009, вам нужно подключить:
GND -> вывод GND на ESP32;
Питание -> вывод VIN на ESP32;
Сигнал -> GPIO 13 (или любой вывод с поддержкой ШИМ).
Примечание: в данном случае вы можете использовать любой GPIO ESP32, потому что любой GPIO может генерировать сигнал ШИМ. Однако мы не рекомендуем использовать GPIO 9, 10 и 11, которые подключены к встроенной SPI-флеш-памяти и не рекомендуются для других целей.
Рекомендуем прочитать: :doc:`Справочник по выводам ESP32: Какие GPIO выводы следует использовать? <../esp32-pinout-reference-gpios/index>`_
Схема подключения
В наших примерах мы подключим сигнальный провод к GPIO 13. Поэтому вы можете следовать приведённой ниже схеме для подключения вашего сервомотора.
(На этой схеме используется модуль ESP32 DEVKIT V1 с 36 GPIO — если вы используете другую модель, пожалуйста, проверьте распиновку для вашей платы.)
Как управлять сервомотором?
Вы можете установить вал сервомотора в различные положения от 0 до 180 градусов. Сервомоторами управляют с помощью сигнала широтно-импульсной модуляции (ШИМ). Коэффициент заполнения ШИМ-сигнала, отправляемого на мотор, определяет положение вала.
Для управления мотором вы можете просто использовать возможности ШИМ ESP32, отправляя сигнал 50 Гц с соответствующей шириной импульса. Или вы можете использовать библиотеку, чтобы значительно упростить эту задачу.
Подготовка Arduino IDE
Перед началом работы убедитесь, что вы установили платы ESP32 в Arduino IDE и библиотеку ESP32Servo.
ESP32 в Arduino IDE
Мы будем программировать ESP32 с помощью Arduino IDE. Поэтому убедитесь, что у вас установлен аддон для ESP32. Если вы ещё этого не сделали, следуйте следующему руководству:
Также вы можете захотеть программировать ESP32 с помощью VS Code и расширения PlatformIO:
Установка библиотеки ESP32Servo
Библиотека ESP32Servo упрощает управление сервомотором с помощью ESP32 в Arduino IDE. Выполните следующие шаги для установки библиотеки в Arduino IDE:
Перейдите в Sketch > Include Library > Manage Libraries…
Найдите ESP32Servo.
Установите библиотеку.
Тестирование примера
После установки библиотеки откройте Arduino IDE и скопируйте следующий код.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-servo-motor-web-server-arduino-ide/
Based on the ESP32Servo Sweep Example
*********/
#include <ESP32Servo.h>
static const int servoPin = 13;
Servo servo1;
void setup() {
Serial.begin(115200);
servo1.attach(servoPin);
}
void loop() {
for(int posDegrees = 0; posDegrees <= 180; posDegrees++) {
servo1.write(posDegrees);
Serial.println(posDegrees);
delay(20);
}
for(int posDegrees = 180; posDegrees >= 0; posDegrees--) {
servo1.write(posDegrees);
Serial.println(posDegrees);
delay(20);
}
}
Разбор кода
Этот скетч поворачивает сервомотор на 180 градусов в одну сторону и на 180 градусов в другую. Давайте разберёмся, как он работает.
Сначала нужно подключить библиотеку Servo:
#include <ESP32Servo.h>
Определите вывод, подключённый к сигнальному контакту сервомотора. В данном случае мы подключаем к GPIO 13, но вы можете использовать любой другой подходящий вывод.
static const int servoPin = 13;
Узнайте больше о GPIO ESP32: :doc:`Справочник по выводам ESP32: Какие GPIO выводы следует использовать? <../esp32-pinout-reference-gpios/index>`_
Затем нужно создать объект Servo. В данном случае он называется servo1.
Servo servo1;
setup()
В функции setup() мы инициализируем последовательное соединение для отладки и привязываем GPIO 13 к объекту servo.
void setup() {
Serial.begin(115200);
servo1.attach(servoPin);
}
loop()
В функции loop() мы меняем положение вала мотора от 0 до 180 градусов, а затем от 180 до 0 градусов. Чтобы установить вал в определённое положение, нужно просто использовать метод write() для объекта Servo. В качестве аргумента передаётся целое число с указанием позиции в градусах.
myservo.write(pos);
Тестирование скетча
Загрузите код на ESP32. После загрузки кода вы должны увидеть, как вал мотора вращается в одну сторону, а затем в другую.
Создание веб-сервера ESP32
Теперь, когда вы знаете, как управлять сервомотором с помощью ESP32, давайте создадим веб-сервер для управления им. Веб-сервер, который мы создадим:
Содержит ползунок от 0 до 180, который вы можете настраивать для управления положением вала сервомотора;
Текущее значение ползунка автоматически обновляется на веб-странице без необходимости её обновления. Для этого мы используем AJAX для отправки HTTP-запросов к ESP32 в фоновом режиме;
Обновление веб-страницы не изменяет значение ползунка и положение вала.
Создание HTML-страницы
Давайте начнём с рассмотрения HTML-текста, который ESP32 должен отправить в ваш браузер.
<!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>
Создание ползунка
HTML-страница для этого проекта включает создание ползунка. Чтобы создать ползунок в HTML, используется тег <input>. Тег <input> определяет поле, в которое пользователь может ввести данные.
Существует множество типов элементов ввода. Чтобы определить ползунок, используйте атрибут «type» со значением «range». Для ползунка также необходимо определить минимальный и максимальный диапазон с помощью атрибутов «min» и «max».
<input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>
Вам также нужно определить другие атрибуты, такие как:
class — для стилизации ползунка
id — для обновления текущей позиции, отображаемой на веб-странице
И, наконец, onchange — для вызова функции servo при отправке HTTP-запроса к ESP32 при перемещении ползунка.
Добавление JavaScript в HTML-файл
Далее вам нужно добавить JavaScript-код в ваш HTML-файл, используя теги <script> и </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;
}
А следующие строки выполняют HTTP GET-запрос по IP-адресу ESP с конкретным URL-путём /?value=[ПОЗИЦИЯ_ПОЛЗУНКА]&.
$.ajaxSetup({timeout:1000});
function servo(pos) {
$.get("/?value=" + pos + "&");
}
Например, когда ползунок находится на отметке 0, выполняется HTTP GET-запрос по следующему URL:
http://192.168.1.135/?value=0&
А когда ползунок находится на отметке 180 градусов, запрос будет выглядеть следующим образом:
http://192.168.1.135/?value=180&
Таким образом, когда ESP32 получает GET-запрос, он может извлечь значение параметра из URL и переместить сервомотор в соответствующее положение.
Код
Теперь нам нужно включить предыдущий HTML-текст в скетч и поворачивать сервомотор соответствующим образом. Следующий скетч делает именно это.
Скопируйте следующий код в Arduino IDE, но пока не загружайте его. Сначала мы кратко рассмотрим, как он работает.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-servo-motor-web-server-arduino-ide/
*********/
#include <WiFi.h>
#include <ESP32Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
// GPIO the servo is attached to
static const int servoPin = 13;
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Decode HTTP GET value
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup() {
Serial.begin(115200);
myservo.attach(servoPin); // attaches the servo on the servoPin to the servo object
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Display the HTML web page
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:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
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>");
// Web Page
client.println("</head><body><h1>ESP32 with Servo</h1>");
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);
//Rotate the servo
myservo.write(valueString.toInt());
Serial.println(valueString);
}
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
Как работает код
Сначала мы подключаем библиотеку Servo и создаём объект Servo с именем myservo.
#include <ESP32Servo.h>
Servo myservo; // create servo object to control a servo
Мы также создаём переменную для хранения номера GPIO, к которому подключён сервомотор. В данном случае — GPIO13.
const int servoPin = 13;
Не забудьте изменить следующие две строки, чтобы указать ваши сетевые данные.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Затем создаём переменные, которые будут использоваться для извлечения позиции ползунка из HTTP-запроса.
// Decode HTTP GET value
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;
setup()
В функции setup() необходимо привязать сервомотор к GPIO, к которому он подключён, с помощью myservo.attach().
myservo.attach(servoPin); // attaches the servo on the servoPin to the servo object
loop()
Первая часть функции loop() создаёт веб-сервер и отправляет HTML-текст для отображения веб-страницы. Мы используем тот же метод, что и в :doc:`этом проекте веб-сервера <../esp32-web-server-arduino-ide/index>`_.
Следующая часть кода извлекает значение ползунка из 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://your-esp-ip-address/?value=[SLIDER_POSITION]&
Значение позиции ползунка сохраняется в переменной valueString.
Затем мы устанавливаем сервомотор в определённое положение с помощью myservo.write(), передавая переменную valueString в качестве аргумента. Переменная valueString является строкой, поэтому нам нужно использовать метод toInt() для преобразования её в целое число — тип данных, принимаемый методом write().
myservo.write(valueString.toInt());
Тестирование веб-сервера
Теперь вы можете загрузить код на ESP32 — убедитесь, что вы выбрали правильную плату и COM-порт. Также не забудьте изменить код, чтобы указать ваши сетевые данные.
После загрузки кода откройте монитор порта на скорости 115200 бод. Нажмите кнопку EN/RST на ESP32, чтобы перезагрузить плату, и скопируйте IP-адрес ESP32, который отображается в мониторе порта.
Откройте браузер, вставьте IP-адрес ESP и вы должны увидеть веб-страницу, которую вы создали ранее. Перемещайте ползунок для управления сервомотором.
В мониторе порта вы также можете видеть HTTP-запросы, которые вы отправляете на ESP32 при перемещении ползунка.
Поэкспериментируйте с вашим веб-сервером некоторое время, чтобы убедиться, что он работает правильно.
Смотрите видеоурок
Это руководство доступно в видеоформате (смотрите ниже) и в текстовом формате (продолжайте читать).
Заключение
Подводя итог, в этом руководстве вы узнали, как управлять сервомотором с помощью ESP32 и как создать веб-сервер с ползунком для управления его положением.
Это лишь пример управления сервомотором. Вместо ползунка вы можете использовать текстовое поле ввода, несколько кнопок с предустановленными углами или любые другие подходящие элементы ввода.
У нас есть руководства по подключению других моторов к ESP32:
Узнайте больше об ESP32 и создании веб-серверов из наших ресурсов:
Надеемся, что это руководство было для вас полезным.
Спасибо за чтение.