Web интерфейс управления сервоприводами ESP8266 есть скеч. цена в мере розумного
- Войдите на сайт для отправки комментариев
Вс, 24/05/2020 - 11:09
Подскажите что я делаю не так ? Позиция лево-право: undefined Позиция верх-вниз: работает нормально
За исправления кода скину $
Вот код можно компилировать.
1 |
#include <Servo.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
const char *ssid = "Aleksander";
const char *password = "11406080";
Servo myservo; // создаем экземпляр класса «Servo»,
Servo myservo1; // чтобы с его помощью управлять сервоприводом;
// большинство плат позволяют
// создать 12 объектов класса «Servo»
// GPIO-контакт, к которому подключен сервопривод:
static const int servoPin = 13;
static const int servo1Pin = 14;
// создаем веб-сервер на порте «80»:
WiFiServer server(80);
// переменная для хранения HTTP-запроса:
String header;
String header1;
// несколько переменных для расшифровки значения в HTTP-запросе GET:
String valueString = String(5);
String valueString1 = String(5);
int pos1 = 0;
int pos2 = 0;
int pos11 = 0;
int pos22 = 0;
void setup() {
Serial.begin(115200);
myservo.attach(servoPin); // привязываем сервопривод,
myservo.attach(servo1Pin); // подключенный к контакту «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("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
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>ESP8266 Управление сервомотором антенны</h1>");
// "Управление сервомотором
// с помощью платы ESP32"
client.println("<p>Позиция верх-вниз: <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("<p>Позиция лево-право: <span id=\"servoPos1\"></span></p>");
client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider1\" id=\"servoSlider1\" onchange=\"servo1(this.value1)\" value1=\""+valueString1+"\"/>");
client.println("<script>var slider = document.getElementById(\"servoSlider\");");
client.println("var slider1 = document.getElementById(\"servoSlider1\");");
client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");
client.println("var servoP1 = document.getElementById(\"servoPos1\"); servoP1.innerHTML = slider1.value1;");
client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");
client.println("slider1.oninput = function() { slider1.value1 = this.value1; servoP1.innerHTML = this.value1; }");
client.println("$.ajaxSetup({timeout:1000}); function servo(pos) { ");
client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}");
client.println("$.ajaxSetup({timeout:1000}); function servo1(pos1) { ");
client.println("$.get(\"/?value=\" + pos1 + \"&\"); {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('&');
pos11 = header1.indexOf('=');
pos22 = header1.indexOf('&');
valueString = header.substring(pos1+1, pos2);
valueString1 = header1.substring(pos11+1, pos22);
// вращаем ось сервомотора:
myservo.write(valueString.toInt());
Serial.println(valueString);
myservo1.write(valueString1.toInt());
Serial.println(valueString1);
}
// конец HTTP-ответа задается
// с помощью дополнительной пустой строки:
client.println();
// выходим из цикла while():
break;
} else { // если получили символ новой строки,
// очищаем текущую строку «currentLine»:
currentLine = "";
}
} else if (c != '\r') { // если получили любые данные,
// кроме символа возврата каретки,
currentLine += c; // добавляем эти данные
// в конец строки «currentLine»
}
}
}
// очищаем переменную «header[]»:
header = "";
header1 = "";
// отключаем соединение:
client.stop();
Serial.println("Client disconnected.");
// "Клиент отключился."
Serial.println("");
}
}
Если верх-вниз действительно работает, то поправлю скетч для лево-право за 500р, fridgetester@mail.ru
ЗЫ: оплата, разумеецца, вперёд.
zDimaBY - вставьте код правильно, с номерами строк, чтоб я мог указать вам ошибку
001
#include <Servo.h>
002
#include <ESP8266WiFi.h>
003
#include <WiFiClient.h>
004
#include <ESP8266WebServer.h>
005
#include <ESP8266mDNS.h>
006
007
const
char
*ssid =
"Aleksander"
;
008
const
char
*password =
"11406080"
;
009
010
Servo myservo;
// создаем экземпляр класса «Servo»,
011
Servo myservo1;
// чтобы с его помощью управлять сервоприводом;
012
// большинство плат позволяют
013
// создать 12 объектов класса «Servo»
014
015
// GPIO-контакт, к которому подключен сервопривод:
016
static
const
int
servoPin = 13;
017
static
const
int
servo1Pin = 14;
018
019
// создаем веб-сервер на порте «80»:
020
WiFiServer server(80);
021
022
// переменная для хранения HTTP-запроса:
023
String header;
024
String header1;
025
// несколько переменных для расшифровки значения в HTTP-запросе GET:
026
String valueString = String(5);
027
String valueString1 = String(5);
028
int
pos1 = 0;
029
int
pos2 = 0;
030
int
pos11 = 0;
031
int
pos22 = 0;
032
033
void
setup
() {
034
Serial
.begin(115200);
035
036
myservo.attach(servoPin);
// привязываем сервопривод,
037
myservo.attach(servo1Pin);
// подключенный к контакту «servoPin»,
038
// к объекту «myservo»
039
040
// подключаемся к WiFi при помощи заданных выше SSID и пароля:
041
Serial
.print(
"Connecting to "
);
// "Подключаемся к "
042
Serial
.println(ssid);
043
WiFi.begin(ssid, password);
044
while
(WiFi.status() != WL_CONNECTED) {
045
delay(500);
046
Serial
.print(
"."
);
047
}
048
// печатаем локальный IP-адрес и запускаем веб-сервер:
049
Serial
.println(
""
);
050
Serial
.println(
"WiFi connected."
);
// "WiFi подключен."
051
Serial
.println(
"IP address: "
);
// "IP-адрес: "
052
Serial
.println(WiFi.localIP());
053
server.begin();
054
}
055
056
void
loop
(){
057
// начинаем прослушивать входящих клиентов:
058
WiFiClient client = server.available();
059
060
if
(client) {
// если подключился новый клиент,
061
Serial
.println(
"New Client."
);
// печатаем сообщение
062
// «Новый клиент.»
063
// в мониторе порта;
064
String currentLine =
""
;
// создаем строку для хранения
065
// входящих данных от клиента;
066
while
(client.connected()) {
// цикл while() будет работать
067
// все то время, пока клиент
068
// будет подключен к серверу;
069
if
(client.available()) {
// если у клиента есть данные,
070
// которые можно прочесть,
071
char
c = client.read();
// считываем байт, а затем
072
Serial
.write(c);
// печатаем его в мониторе порта
073
header += c;
074
if
(c ==
'\n'
) {
// если этим байтом является
075
// символ новой строки
076
// если получили два символа новой строки подряд,
077
// то это значит, что текущая строчка пуста;
078
// это конец HTTP-запроса клиента,
079
// а значит – пора отправлять ответ:
080
if
(currentLine.length() == 0) {
081
// HTTP-заголовки всегда начинаются
082
// с кода ответа (например, «HTTP/1.1 200 OK»)
083
// и информации о типе контента
084
// (чтобы клиент понимал, что получает);
085
// в конце пишем пустую строчку:
086
client.println(
"HTTP/1.1 200 OK"
);
087
client.println(
"Content-type:text/html"
);
088
client.println(
"Connection: close"
);
089
// "Соединение: отключено"
090
client.println();
091
092
// показываем веб-страницу:
093
client.println(
"<!DOCTYPE html><html>"
);
094
client.println(
"<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
);
095
client.println(
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
);
096
client.println(
"<link rel=\"icon\" href=\"data:,\">"
);
097
client.println(
"<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}"
);
098
client.println(
".slider { width: 300px; }</style>"
);
099
client.println(
"<script src=\"<a href="
https:
//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js%5C" rel="nofollow">https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\</a>"></script>");
100
101
// веб-страница:
102
client.println(
"</head><body><h1>ESP8266 Управление сервомотором антенны</h1>"
);
103
// "Управление сервомотором
104
// с помощью платы ESP32"
105
client.println(
"<p>Позиция верх-вниз: <span id=\"servoPos\"></span></p>"
);
106
client.println(
"<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""
+valueString+
"\"/>"
);
107
client.println(
"<p>Позиция лево-право: <span id=\"servoPos1\"></span></p>"
);
108
client.println(
"<input type=\"range\" min=\"0\" max=\"180\" class=\"slider1\" id=\"servoSlider1\" onchange=\"servo1(this.value1)\" value1=\""
+valueString1+
"\"/>"
);
109
110
client.println(
"<script>var slider = document.getElementById(\"servoSlider\");"
);
111
client.println(
"var slider1 = document.getElementById(\"servoSlider1\");"
);
112
client.println(
"var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;"
);
113
client.println(
"var servoP1 = document.getElementById(\"servoPos1\"); servoP1.innerHTML = slider1.value1;"
);
114
client.println(
"slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }"
);
115
client.println(
"slider1.oninput = function() { slider1.value1 = this.value1; servoP1.innerHTML = this.value1; }"
);
116
client.println(
"$.ajaxSetup({timeout:1000}); function servo(pos) { "
);
117
client.println(
"$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}"
);
118
client.println(
"$.ajaxSetup({timeout:1000}); function servo1(pos1) { "
);
119
client.println(
"$.get(\"/?value=\" + pos1 + \"&\"); {Connection: close};}</script>"
);
120
121
client.println(
"</body></html>"
);
122
123
//GET /?value=180& HTTP/1.1
124
if
(header.indexOf(
"GET /?value="
)>=0) {
125
pos1 = header.indexOf(
'='
);
126
pos2 = header.indexOf(
'&'
);
127
pos11 = header1.indexOf(
'='
);
128
pos22 = header1.indexOf(
'&'
);
129
valueString = header.substring(pos1+1, pos2);
130
valueString1 = header1.substring(pos11+1, pos22);
131
// вращаем ось сервомотора:
132
myservo.write(valueString.toInt());
133
Serial
.println(valueString);
134
myservo1.write(valueString1.toInt());
135
Serial
.println(valueString1);
136
}
137
// конец HTTP-ответа задается
138
// с помощью дополнительной пустой строки:
139
client.println();
140
// выходим из цикла while():
141
break
;
142
}
else
{
// если получили символ новой строки,
143
// очищаем текущую строку «currentLine»:
144
currentLine =
""
;
145
}
146
}
else
if
(c !=
'\r'
) {
// если получили любые данные,
147
// кроме символа возврата каретки,
148
currentLine += c;
// добавляем эти данные
149
// в конец строки «currentLine»
150
}
151
}
152
}
153
// очищаем переменную «header[]»:
154
header =
""
;
155
header1 =
""
;
156
// отключаем соединение:
157
client.stop();
158
Serial
.println(
"Client disconnected."
);
159
// "Клиент отключился."
160
Serial
.println(
""
);
161
}
162
}
Через https://kwork.ru работаете ?
код списали что ли, ничего в нем не смыслите?
строка 36 и 37 - одна должна быть myservo.attach(), а вторая myservo1.attach() - а у вас обе строки для одного и того же серво
строка 36 и 37 это понимаю.. но не понимаю как брать запрос с 2-х ползунков один показывает значения undefined
Списал, смыслю но не все например с 124 до 130 не очень понимаю
строка 36 и 37 это понимаю..
так исправляйте, так работать заведомо не будет
Исправил. https://ibb.co/jvW830v но думаю на это ничего не повлияло имею виду "Позиция лево-право: undefined"
а, увидел, у вас еще код сайта неверный, строчки 116-119 видимо изначально брали из примера, где был один запрос, и тупо скопировали дважды? - так работать не будет.
И еще в строке 124 и дальше всунули какой-то header1, не понимая, что это значит.
В итоге у вас в коде передается только один параметр слайдера, не важно какой...
В общем, переписать это несложно, но уже выходит за рамки "помощи в форуме". Обращайтесь к фриджетестеру выше
fridgetester - помог, спасибо большое. Все решено.
А можно ли вместо запроса
1
GET /?value=45& HTTP/1.1
// например, угол поворота сервопривода 45.
2
использовать
3
GET /?value1=45&value2=90& HTTP/1.1
// угол поворота первого сервопривода 45, второго 90
а так написать можно?
1
client.println(
"$.ajaxSetup({timeout:1000}); function servo(pos_1, pos_2) { "
);
// принять два значения (позиция первого сервопривода и второго)
2
client.println(
"$.get(\"/?value1=\" + pos_1 + \"&value2=\" + pos_2 + \"&\");{Connection: close};}"
);
Или лучше всё-таки сделать отдельные функции для каждого сервопривода? И проверять на соответствие
1
if
(header.indexOf(
"GET /?value1="
)>=0)
// первый сервопривод
2
if
(header.indexOf(
"GET /?value2="
)>=0)
// второй
Подскажите пожалуйста, кто разбирается!
В 1 функцию.
01
<!doctype html>
02
<html dir=
"ltr"
lang=
"ru"
>
03
<head>
04
<meta charset=
"utf-8"
>
05
<title>Новая вкладка</title>
06
</head>
07
<body>
08
<script>
09
let header =
"GET /?value1=45&value2=90&value3=105& HTTP/1.1"
;
10
11
let positions =[];
// массив для позиций символов в строке
12
if
(header.indexOf(
"GET /?value"
)>=0) {
// если начало заголовка появилось...
13
let currentPos = header.indexOf(
'='
);
14
while
(currentPos != -1) {
15
positions.push(currentPos);
16
currentPos = header.indexOf(
'='
, currentPos+1);
17
}
18
19
currentPos = header.indexOf(
'&'
);
20
while
(currentPos != -1) {
21
positions.push(currentPos);
22
currentPos = header.indexOf(
'&'
, currentPos+1);
23
}
24
}
25
let valueString1 = header.substring(positions[0]+1, positions[3]);
26
let valueString2 = header.substring(positions[1]+1, positions[4]);
27
let valueString3 = header.substring(positions[2]+1, positions[5]);
28
console.
log
(valueString1);
29
console.
log
(valueString2);
30
console.
log
(valueString3);
31
console.
log
(positions);
32
</script>
33
</body>
34
</html>
в него "запихиваются" значения всех найденных позиций символа "=", а затем аналогичным образом, символа "&". Используется метод "push"
1
positions.push(currentPos);
// запихнуть текущую позицию в массив
2
currentPos = header.indexOf(
'='
, currentPos+1);
01
<!doctype html>
02
<html dir=
"ltr"
lang=
"ru"
>
03
<head>
04
<meta charset=
"utf-8"
>
05
<title>Новая вкладка</title>
06
</head>
07
<body>
08
<script>
09
let header =
"GET /?value1=45&value2=90&value3=105& HTTP/1.1"
;
10
11
let positions =[];
// массив для позиций символов в строке
12
if
(header.indexOf(
"GET /?value"
)>=0) {
// если начало заголовка появилось...
13
let currentLeftPos = header.indexOf(
'='
);
14
let currentRightPos = header.indexOf(
'&'
);
15
while
(currentLeftPos != -1 || currentRightPos != -1) {
16
positions.push(currentLeftPos);
// запихнуть левую позицию
17
positions.push(currentRightPos);
// запихнуть правую позицию
18
currentLeftPos = header.indexOf(
'='
, currentLeftPos+1);
19
currentRightPos = header.indexOf(
'&'
, currentRightPos+1);
20
}
21
}
22
let valueString1 = header.substring(positions[0]+1, positions[1]);
23
let valueString2 = header.substring(positions[2]+1, positions[3]);
24
let valueString3 = header.substring(positions[4]+1, positions[5]);
25
console.
log
(valueString1);
26
console.
log
(valueString2);
27
console.
log
(valueString3);
28
console.
log
(positions);
29
</script>
30
</body>
31
</html>
Не тоже самое. Операция ++ выполняется после того , как будет выполнено основное выражение, а +1 сначала будет прибавлено 1, а потом уже выполнено основное выражение.
Такова особенность выражения ++
Не забываем про наличие операции ++currentPos :)
Да с плюсами перед переменной работает! Однако странно, что в отладчике, НЕ видно как currentPos увеличивается на 1.
Как не пиши, хоть ++currentPos, хоть currentPos+1 все равно.
Что это? Глюк отладчика или так и должно быть?
А вот если написать так, видно!
1
positions.push(currentPos);
2
currentPos++;
3
currentPos = header.indexOf(
'='
, currentPos);
У вас же не си. Зависания это может быть проблема отладчика, брaузера, да всего чего угодно. Может у вас где то брейк установлен и срабатывает. Зачем вы вообще отлаживаете этот простейший код ? Проверьте без отладчика и двигайтесь дальше.
Вот смотрите строка
currentLeftPos = header.indexOf('=', currentLeftPos++);
Происходит следующее в момент работы header.indexOf значение currentLeftPos равно 12, по окончании работы оно увеличивается на единицу и становится 13, но поиск проводился с символа номер 12, а этот символ удовлетворяет условиям, поскольку вы присваиваете результат header.indexOf этой переменной, то она вновь становится 12
currentLeftPos = header.indexOf('=', currentLeftPos+1);
currentLeftPos = header.indexOf('=', ++currentLeftPos);
01
<!doctype html>
02
<html dir=
"ltr"
lang=
"ru"
>
03
<head>
04
<meta charset=
"utf-8"
>
05
<title>Новая вкладка</title>
06
</head>
07
<body>
08
<script>
09
let header =
"GET /?value1=45&value2=90&value3=105& HTTP/1.1"
;
10
11
let positions =[];
// массив для позиций символов в строке
12
if
(header.indexOf(
"GET /?value"
)>=0) {
// если начало заголовка появилось...
13
let currentLeftPos = header.indexOf(
'='
);
14
let currentRightPos = header.indexOf(
'&'
);
15
while
(currentLeftPos != -1 || currentRightPos != -1) {
16
alert(currentLeftPos+
' '
+currentRightPos);
17
positions.push(currentLeftPos);
// запихнуть левую позицию
18
positions.push(currentRightPos);
// запихнуть правую позицию
19
currentLeftPos = header.indexOf(
'='
, currentLeftPos++);
20
currentRightPos = header.indexOf(
'&'
, currentRightPos++);
21
}
22
}
23
let valueString1 = header.substring(positions[0]+1, positions[1]);
24
let valueString2 = header.substring(positions[2]+1, positions[3]);
25
let valueString3 = header.substring(positions[4]+1, positions[5]);
26
console.log(valueString1);
27
console.log(valueString2);
28
console.log(valueString3);
29
console.log(positions);
30
</script>
31
</body>
32
</html>
Большое спасибо Вам за детальное объяснение!
001
#include <Servo.h>
002
#include <ESP8266WiFi.h>
003
#include <WiFiClient.h>
004
#include <WiFiUdp.h>
005
#include <ESP8266WebServer.h>
006
#include <ESP8266mDNS.h>
007
#include <ArduinoOTA.h> // Библиотека для OTA-прошивки
008
const
char
*ssid =
"Aleksander"
;
//Имя сети вайфай
009
const
char
*password =
"11406080"
;
// пароль вайфай
010
Servo myservo;
// создаем экземпляр класса «Servo»,
011
Servo myservo1;
// чтобы с его помощью управлять сервоприводом;
012
// большинство плат позволяют
013
// создать 12 объектов класса «Servo»
014
// GPIO-контакт, к которому подключен сервопривод:
015
static
const
int
servoPin = 5;
016
static
const
int
servo1Pin = 4;
017
018
// создаем веб-сервер на порте «80»:
019
WiFiServer server(80);
020
021
// переменная для хранения HTTP-запроса:
022
String header;
023
// несколько переменных для расшифровки значения в HTTP-запросе GET:
024
String valueString = String(170);
025
String valueString1 = String(180);
026
int
pos1 = 0;
027
int
pos2 = 0;
028
029
void
setup
() {
030
Serial
.begin(115200);
031
032
myservo.attach(servoPin, 544, 1520);;
// привязываем сервопривод,
033
myservo1.attach(servo1Pin);
// подключенный к контакту «servoPin»,
034
// к объекту «myservo»
035
// подключаемся к WiFi при помощи заданных выше SSID и пароля:
036
Serial
.print(
"Connecting to "
);
// "Подключаемся к "
037
Serial
.println(ssid);
038
WiFi.begin(ssid, password);
039
while
(WiFi.status() != WL_CONNECTED) {
040
delay(500);
041
Serial
.print(
"."
);
042
}
043
ArduinoOTA.setHostname(
"ESP8266_Серво-привод_антенны"
);
// Задаем имя сетевого порта
044
//ArduinoOTA.setPassword((const char *)"0000"); // Задаем пароль доступа для удаленной прошивки
045
ArduinoOTA.begin();
// Инициализируем OTA
046
// печатаем локальный IP-адрес и запускаем веб-сервер:
047
Serial
.println(
""
);
048
Serial
.println(
"WiFi connected."
);
// "WiFi подключен."
049
Serial
.println(
"IP address: "
);
// "IP-адрес: "
050
Serial
.println(WiFi.localIP());
051
server.begin();
052
}
053
054
void
loop
(){
055
ArduinoOTA.handle();
// Всегда готовы к прошивке
056
// начинаем прослушивать входящих клиентов:
057
WiFiClient client = server.available();
058
059
if
(client) {
// если подключился новый клиент,
060
Serial
.println(
"New Client."
);
// печатаем сообщение
061
// «Новый клиент.»
062
// в мониторе порта;
063
String currentLine =
""
;
// создаем строку для хранения
064
// входящих данных от клиента;
065
while
(client.connected()) {
// цикл while() будет работать
066
// все то время, пока клиент
067
// будет подключен к серверу;
068
if
(client.available()) {
// если у клиента есть данные,
069
// которые можно прочесть,
070
char
c = client.read();
// считываем байт, а затем
071
Serial
.write(c);
// печатаем его в мониторе порта
072
header += c;
073
if
(c ==
'\n'
) {
// если этим байтом является
074
// символ новой строки
075
// если получили два символа новой строки подряд,
076
// то это значит, что текущая строчка пуста;
077
// это конец HTTP-запроса клиента,
078
// а значит – пора отправлять ответ:
079
if
(currentLine.length() == 0) {
080
// HTTP-заголовки всегда начинаются
081
// с кода ответа (например, «HTTP/1.1 200 OK»)
082
// и информации о типе контента
083
// (чтобы клиент понимал, что получает);
084
// в конце пишем пустую строчку:
085
client.println(
"HTTP/1.1 200 OK"
);
086
client.println(
"Content-type:text/html"
);
087
client.println(
"Connection: close"
);
088
// "Соединение: отключено"
089
client.println();
090
091
// показываем веб-страницу:
092
client.println(
"<!DOCTYPE html><html>"
);
093
client.println(
"<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
);
094
client.println(
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
);
095
client.println(
"<link rel=\"icon\" href=\"data:,\">"
);
096
client.println(
"<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}"
);
097
client.println(
".slider { width: 300px; }</style>"
);
098
client.println(
"<script src=\"<a href="
https:
//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js%5C" rel="nofollow">https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\</a>"></script>");
099
100
// веб-страница:
101
client.println(
"</head><body><h1>ESP8266 Управление сервомотором антенны</h1>"
);
102
// "Управление сервомотором
103
// с помощью платы ESP32"
104
client.println(
"<p>Позиция верх-вниз: <span id=\"servoPos\"></span></p>"
);
105
client.println(
"<input type=\"range\" min=\"70\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""
+valueString+
"\"/>"
);
106
client.println(
"<p>Позиция лево-право: <span id=\"servoPos1\"></span></p>"
);
107
client.println(
"<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider1\" onchange=\"servo1(this.value)\" value=\""
+valueString1+
"\"/>"
);
108
109
client.println(
"<script>var slider = document.getElementById(\"servoSlider\");"
);
110
client.println(
"var slider1 = document.getElementById(\"servoSlider1\");"
);
111
client.println(
"var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;"
);
112
client.println(
"var servoP1 = document.getElementById(\"servoPos1\"); servoP1.innerHTML = slider1.value;"
);
113
client.println(
"slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }"
);
114
client.println(
"slider1.oninput = function() { slider1.value = this.value; servoP1.innerHTML = this.value; }"
);
115
client.println(
"$.ajaxSetup({timeout:1000}); function servo(pos) { "
);
116
client.println(
"$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}"
);
117
client.println(
"function servo1(pos) { "
);
118
client.println(
"$.get(\"/?value1=\" + pos + \"&\"); {Connection: close};}</script>"
);
119
120
client.println(
"</body></html>"
);
121
122
//GET /?value=180& HTTP/1.1
123
if
(header.indexOf(
"GET /?value="
)>=0)
124
{
125
pos1 = header.indexOf(
'='
);
126
pos2 = header.indexOf(
'&'
);
127
valueString = header.substring(pos1+1, pos2);
128
129
//Rotate the servo
130
myservo.write(valueString.toInt());
131
Serial
.print(
"Got servro val: "
);
132
Serial
.println(valueString);
133
}
134
else
if
(header.indexOf(
"GET /?value1="
)>=0)
135
{
136
pos1 = header.indexOf(
'='
);
137
pos2 = header.indexOf(
'&'
);
138
valueString1 = header.substring(pos1+1, pos2);
139
140
//Rotate the servo
141
myservo1.write(valueString1.toInt());
142
Serial
.print(
"Got servro1 val: "
);
143
Serial
.println(valueString1);
144
}
145
146
// конец HTTP-ответа задается
147
// с помощью дополнительной пустой строки:
148
client.println();
149
// выходим из цикла while():
150
break
;
151
}
else
{
// если получили символ новой строки,
152
// очищаем текущую строку «currentLine»:
153
currentLine =
""
;
154
}
155
}
else
if
(c !=
'\r'
) {
// если получили любые данные,
156
// кроме символа возврата каретки,
157
currentLine += c;
// добавляем эти данные
158
// в конец строки «currentLine»
159
}
160
}
161
}
162
// очищаем переменную «header[]»:
163
header =
""
;
164
// отключаем соединение:
165
client.stop();
166
Serial
.println(
"Client disconnected."
);
167
// "Клиент отключился."
168
Serial
.println(
""
);
169
}
170
}
Готовый код. Кому нужно будет.
Готовый код. Кому нужно будет.
не взлетит, сайт ссылки ломает...к примеру 98 строка
Не ломает, открой код в отдельном окошке, там строка без переносов.
Не ломает, открой код в отдельном окошке, там строка без переносов.
у меня сломано (FIREFOX) поправил как надо:
client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");
Насколько я понял, это подгружается библиотека jQuery с какого-то удаленного сервера, и это значит, что без доступа к нему скетч нормально работать не будет! Интересно, как добавить её прямо в память модуля и использовать локально?
Если бы не куча дополнительных символов, то наверно просто вставить содержимое между тегами <script> </script> в которых стоит ссылка на источник.
На SPIFFS положить, если влезет.
84 килобайта, влезет. Только со SPIFFS грузится будет долго, нужно с кешированием шаманить. Только воз из этого скрипта могут быть обращения к другим ресурсам, это точно нужно проверять.
Браузер закэширует. Наврядли стоит ESP-шкой CDN заменять.
1
{
try
{
return
new
e.XMLHttpRequest}
// первое
2
(i[
"X-Requested-With"
]=
"XMLHttpRequest"
)
// второе
Ни к каким внешним ресурсам, насколько я понял, библиотека не обращается.
Значит файл с ней можно загрузить в файловую систему и просто указать на него ссылку?
И эта строка
client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");
01
bool
handleFileRead(String path){
// Функция работы с файловой системой
02
if
(path.endsWith(
"/"
)) path +=
"index.html"
;
// Если устройство вызывается по корневому адресу, то должен вызываться файл index.html (добавляем его в конец адреса)
03
else
if
(path.endsWith(
"/jquery.min.js"
)) path +=
"jquery.min.js"
;
// файл библиотеки
04
String contentType = getContentType(path);
// С помощью функции getContentType (описана ниже) определяем по типу файла (в адресе обращения) какой заголовок необходимо возвращать по его вызову
05
if
(SPIFFS.exists(path)){
// Если в файловой системе существует файл по адресу обращения
06
File file = SPIFFS.open(path,
"r"
);
// Открываем файл для чтения
07
size_t sent = HTTP.streamFile(file, contentType);
// Выводим содержимое файла по HTTP, указывая заголовок типа содержимого contentType
08
file.close();
// Закрываем файл
09
return
true
;
// Завершаем выполнение функции, возвращая результатом ее исполнения true (истина)
10
}
11
return
false
;
// Завершаем выполнение функции, возвращая результатом ее исполнения false (если не обработалось предыдущее условие)
12
}
13
// и еще нужна функция для возврата правильного заголовка
14
String getContentType(String filename){
// Функция, возвращающая необходимый заголовок типа содержимого в зависимости от расширения файла
15
if
(filename.endsWith(
".html"
))
return
"text/html"
;
// Если файл заканчивается на ".html", то возвращаем заголовок "text/html" и завершаем выполнение функции
16
else
if
(filename.endsWith(
".css"
))
return
"text/css"
;
// Если файл заканчивается на ".css", то возвращаем заголовок "text/css" и завершаем выполнение функции
17
else
if
(filename.endsWith(
".js"
))
return
"application/javascript"
;
// Если файл заканчивается на ".js", то возвращаем заголовок "application/javascript" и завершаем выполнение функции
18
else
if
(filename.endsWith(
".png"
))
return
"image/png"
;
// Если файл заканчивается на ".png", то возвращаем заголовок "image/png" и завершаем выполнение функции
19
else
if
(filename.endsWith(
".jpg"
))
return
"image/jpeg"
;
// Если файл заканчивается на ".jpg", то возвращаем заголовок "image/jpg" и завершаем выполнение функции
20
else
if
(filename.endsWith(
".gif"
))
return
"image/gif"
;
// Если файл заканчивается на ".gif", то возвращаем заголовок "image/gif" и завершаем выполнение функции
21
else
if
(filename.endsWith(
".ico"
))
return
"image/x-icon"
;
// Если файл заканчивается на ".ico", то возвращаем заголовок "image/x-icon" и завершаем выполнение функции
22
return
"text/plain"
;
// Если ни один из типов файла не совпал, то считаем что содержимое файла текстовое, отдаем соответствующий заголовок и завершаем выполнение функции
23
}
Нет конечно. Скорее всего нужно так:
if
(path.endsWith(
"/jquery.min.js"
)) path =
"/jquery.min.js"
;
Только вот , по моему, стандартный SPIFFS не поддерживает две точки в имени. Так что имя файлы нужно привести к нормальному виду. Более того конструкция
if
(path.endsWith(
"/"
)) path +=
"index.html"
не однозначна, например на запрос типа /blablabla/ она будет пытаться отправить файл /blablabla/index.html, которого , конечно, на диске не будет.Хранить в коде можно как угодно - как удобнее программе. Например в одном моём проекте, где нужно хранить много ссылок на разные HTTP-ресурсы, они хранятся в виде URL-ов без префикса протокола (http://). Протокол хранится отдельно - двоичным числом. Да и сами URL-ы хранятся в сжатом виде и тупым текстовым поиском их не найдёшь.
1
client.println(
"<script>"
);
// начало скрипта
2
jquery_min = SPIFFS.open(
"/jquery_min.txt"
,
"r"
);
// открыть файл с текстом скрипта и присвоить его содержимое jquery_min
3
if
(!jquery_min) {
Serial
.println(
"file open failed"
);}
// "открыть файл не удалось"
4
}
5
while
(jquery_min.available()) {
6
client.print(
char
(jquery_min.read()));
// вывод всех символов
7
}
8
jquery_min.close();
9
client.println(
"</script>"
);
//конец скрипта
Код целиком
001
#include <Servo.h>
002
#include <ESP8266WiFi.h>
003
#include <WiFiClient.h>
004
#include <WiFiUdp.h>
005
#include <ESP8266WebServer.h>
006
#include <ESP8266mDNS.h>
007
#include <FS.h> // Библиотека файловой системы
008
#include <ArduinoOTA.h> // Библиотека OTA-прошивки
009
const
char
*ssid =
"SSID"
;
//Имя сети вайфай
010
const
char
*password =
"password"
;
// пароль вайфай
011
File jquery_min;
// для чтения файла
012
Servo myservo;
// создаем экземпляр класса «Servo»,
013
Servo myservo1;
// чтобы с его помощью управлять сервоприводом;
014
// большинство плат позволяют
015
// создать 12 объектов класса «Servo»
016
// GPIO-контакт, к которому подключен сервопривод:
017
static
const
int
servoPin = 5;
018
static
const
int
servo1Pin = 4;
019
020
// создаем веб-сервер на порте «80»:
021
WiFiServer server(80);
022
023
// переменная для хранения HTTP-запроса:
024
String header;
025
String valueString = String(170);
026
String valueString1 = String(180);
027
int
pos1 = 0;
028
int
pos2 = 0;
029
030
void
setup
() {
031
Serial
.begin(115200);
032
SPIFFS.begin();
// инициализируем библиотеку для работы с файловой системой
033
Serial
.print(
"Connecting to "
);
034
myservo.attach(servoPin, 544, 1520);;
// привязываем сервопривод,
035
myservo1.attach(servo1Pin);
// подключенный к контакту «servoPin»,
036
// к объекту «myservo»
037
// подключаемся к WiFi при помощи заданных выше SSID и пароля:
038
Serial
.print(
"Connecting to "
);
// "Подключаемся к "
039
Serial
.println(ssid);
040
WiFi.begin(ssid, password);
041
while
(WiFi.status() != WL_CONNECTED) {
042
delay(500);
043
Serial
.print(
"."
);
044
}
045
ArduinoOTA.setHostname(
"ESP8266_Серво-привод_антенны"
);
// Задаем имя сетевого порта
046
//ArduinoOTA.setPassword((const char *)"0000"); // Задаем пароль доступа для удаленной прошивки
047
ArduinoOTA.begin();
// Инициализируем OTA
048
// печатаем локальный IP-адрес и запускаем веб-сервер:
049
Serial
.println(
""
);
050
Serial
.println(
"WiFi connected."
);
// "WiFi подключен."
051
Serial
.println(
"IP address: "
);
// "IP-адрес: "
052
Serial
.println(WiFi.localIP());
053
server.begin();
054
}
055
056
void
loop
() {
057
ArduinoOTA.handle();
// Всегда готовы к прошивке
058
// начинаем прослушивать входящих клиентов:
059
WiFiClient client = server.available();
060
061
if
(client) {
// если подключился новый клиент,
062
Serial
.println(
"New Client."
);
// печатаем сообщение
063
// «Новый клиент.»
064
// в мониторе порта;
065
String currentLine =
""
;
// создаем строку для хранения
066
// входящих данных от клиента;
067
while
(client.connected()) {
// цикл while() будет работать
068
// все то время, пока клиент
069
// будет подключен к серверу;
070
if
(client.available()) {
// если у клиента есть данные,
071
// которые можно прочесть,
072
char
c = client.read();
// считываем байт, а затем
073
Serial
.write(c);
// печатаем его в мониторе порта
074
header += c;
075
if
(c ==
'\n'
) {
// если этим байтом является
076
// символ новой строки
077
// если получили два символа новой строки подряд,
078
// то это значит, что текущая строчка пуста;
079
// это конец HTTP-запроса клиента,
080
// а значит – пора отправлять ответ:
081
if
(currentLine.length() == 0) {
082
// HTTP-заголовки всегда начинаются
083
// с кода ответа (например, «HTTP/1.1 200 OK»)
084
// и информации о типе контента
085
// (чтобы клиент понимал, что получает);
086
// в конце пишем пустую строчку:
087
client.println(
"HTTP/1.1 200 OK"
);
088
client.println(
"Content-type:text/html"
);
089
client.println(
"Connection: close"
);
090
// "Соединение: отключено"
091
client.println();
092
093
// показываем веб-страницу:
094
client.println(
"<!DOCTYPE html><html>"
);
095
client.println(
"<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
);
096
client.println(
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
);
097
client.println(
"<link rel=\"icon\" href=\"data:,\">"
);
098
client.println(
"<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}"
);
099
client.println(
".slider { width: 300px; }</style>"
);
100
client.println(
"<script>"
);
// начало скрипта
101
jquery_min = SPIFFS.open(
"/jquery_min.txt"
,
"r"
);
// открыть файл с текстом скрипта и присвоить его содержимое jquery_min
102
if
(!jquery_min) {
103
Serial
.println(
"file open failed"
);
// "открыть файл не удалось"
104
}
105
while
(jquery_min.available()) {
106
client.print(
char
(jquery_min.read()));
// вывод всех символов
107
}
108
jquery_min.close();
109
client.println(
"</script>"
);
//конец скрипта
110
111
// веб-страница:
112
client.println(
"</head><body><h1>ESP8266 Управление сервомотором антенны</h1>"
);
113
// "Управление сервомотором
114
// с помощью платы ESP32"
115
client.println(
"<p>Позиция верх-вниз: <span id=\"servoPos\"></span></p>"
);
116
client.println(
"<input type=\"range\" min=\"70\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""
+ valueString +
"\"/>"
);
117
client.println(
"<p>Позиция лево-право: <span id=\"servoPos1\"></span></p>"
);
118
client.println(
"<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider1\" onchange=\"servo1(this.value)\" value=\""
+ valueString1 +
"\"/>"
);
119
120
client.println(
"<script>var slider = document.getElementById(\"servoSlider\");"
);
121
client.println(
"var slider1 = document.getElementById(\"servoSlider1\");"
);
122
client.println(
"var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;"
);
123
client.println(
"var servoP1 = document.getElementById(\"servoPos1\"); servoP1.innerHTML = slider1.value;"
);
124
client.println(
"slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }"
);
125
client.println(
"slider1.oninput = function() { slider1.value = this.value; servoP1.innerHTML = this.value; }"
);
126
client.println(
"$.ajaxSetup({timeout:1000}); function servo(pos) { "
);
127
client.println(
"$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}"
);
128
client.println(
"function servo1(pos) { "
);
129
client.println(
"$.get(\"/?value1=\" + pos + \"&\"); {Connection: close};}</script>"
);
130
131
client.println(
"</body></html>"
);
132
133
//GET /?value=180& HTTP/1.1
134
if
(header.indexOf(
"GET /?value="
) >= 0)
135
{
136
pos1 = header.indexOf(
'='
);
137
pos2 = header.indexOf(
'&'
);
138
valueString = header.substring(pos1 + 1, pos2);
139
140
//Rotate the servo
141
myservo.write(valueString.toInt());
142
Serial
.print(
"Got servro val: "
);
143
Serial
.println(valueString);
144
}
145
else
if
(header.indexOf(
"GET /?value1="
) >= 0)
146
{
147
pos1 = header.indexOf(
'='
);
148
pos2 = header.indexOf(
'&'
);
149
valueString1 = header.substring(pos1 + 1, pos2);
150
151
//Rotate the servo
152
myservo1.write(valueString1.toInt());
153
Serial
.print(
"Got servro1 val: "
);
154
Serial
.println(valueString1);
155
}
156
157
// конец HTTP-ответа задается
158
// с помощью дополнительной пустой строки:
159
client.println();
160
// выходим из цикла while():
161
break
;
162
}
else
{
// если получили символ новой строки,
163
// очищаем текущую строку «currentLine»:
164
currentLine =
""
;
165
}
166
}
else
if
(c !=
'\r'
) {
// если получили любые данные,
167
// кроме символа возврата каретки,
168
currentLine += c;
// добавляем эти данные
169
// в конец строки «currentLine»
170
}
171
}
172
}
173
// очищаем переменную «header[]»:
174
header =
""
;
175
// отключаем соединение:
176
client.stop();
177
Serial
.println(
"Client disconnected."
);
178
// "Клиент отключился."
179
Serial
.println(
""
);
180
}
181
}
84 килобайта, влезет. Только со SPIFFS грузится будет долго, нужно с кешированием шаманить.
Да, Вы абсолютно правы! Эта простая страничка грузится почти 9 секунд! И даже реакция на перемещение ползунков примерно 1 секунда!
spiffs работает приемлемо. Веб-сервер медленный.
spiffs работает приемлемо. Веб-сервер медленный.
Переход на внешнюю SDшку с фатом дает прирост скорости в два раза.