Сделал управление радиоуправляемой машинкой, надо изменить веб часть-удержание, отпуск кнопки
- Войдите на сайт для отправки комментариев
Всем доброго!
Сделал вот по этому мануалу управление по wifi - машинкой-роботом.
Переделал скетч правда под свой драйвер двигателей.
код моего измененного скетча вот:
/********* Руи Сантос Более подробно о проекте на: http://randomnerdtutorials.com *********/ // загружаем библиотеку для WiFi: #include <WiFi.h> // вставляем ниже SSID и пароль для своей WiFi-сети: const char* ssid = "сюда SSID"; const char* password = "сюда пароль"; // создаем объект сервера и задаем ему порт «80»: WiFiServer server(80); // переменная для хранения HTTP-запроса: String header; // мотор 1: int motor1Pin1 = 18; int motor1Pin2 = 19; //int enable1Pin = 14; // мотор 2: int motor2Pin1 = 16; int motor2Pin2 = 17; //int enable2Pin = 32; // переменные для свойств широтно-импульсной модуляции (ШИМ) 1-двигателя: const int freq = 30000; const int pwmChannel = 0; const int resolution = 8; int dutyCycle = 0; // переменные для свойств широтно-импульсной модуляции (ШИМ) 2-двигателя: const int freq2 = 30000; const int pwmChannel2 = 1; const int resolution2 = 8; int dutyCycle2 = 0; // переменные для расшифровки HTTP-запроса GET: String valueString = String(5); int pos1 = 0; int pos2 = 0; void setup() { Serial.begin(115200); // переключаем контакты моторов в режим «OUTPUT»: pinMode(motor1Pin1, OUTPUT); pinMode(motor1Pin2, OUTPUT); pinMode(motor2Pin1, OUTPUT); pinMode(motor2Pin2, OUTPUT); // задаем настройки ШИМ-канала каждого из 2 двигателей: ledcSetup(pwmChannel, freq, resolution); // первый двигатель ledcSetup(pwmChannel2, freq2, resolution2); // второй двигатель // подключаем ШИМ-канал, к контактам для управления скоростью вращения каждого из 2 моторов: ledcAttachPin(motor1Pin1, pwmChannel); // первый двигатель ledcAttachPin(motor2Pin1, pwmChannel2); // второй двигатель // подаем на контакты ШИМ-сигнал с коэффициентом заполнения «0»: ledcWrite(pwmChannel, dutyCycle); ledcWrite(pwmChannel2, dutyCycle2); // подключаемся к 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(); // Этот код отвечает за управление контактами моторов // согласно тому, какие нажаты кнопки на веб-странице: if (header.indexOf("GET /forward") >= 0) { Serial.println("Forward"); // "Вперед" ledcWrite(pwmChannel, 0); ledcWrite(pwmChannel2, 0); digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, HIGH); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); } else if (header.indexOf("GET /left") >= 0) { Serial.println("Left"); // "Влево" ledcWrite(pwmChannel, 255); ledcWrite(pwmChannel2, 0); digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); } else if (header.indexOf("GET /stop") >= 0) { Serial.println("Stop"); // "Стоп" ledcWrite(pwmChannel, 0); ledcWrite(pwmChannel2, 0); digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, LOW); } else if (header.indexOf("GET /right") >= 0) { Serial.println("Right"); // "Вправо" ledcWrite(pwmChannel, 0); ledcWrite(pwmChannel2, 255); digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, HIGH); digitalWrite(motor2Pin1, HIGH); digitalWrite(motor2Pin2, LOW); } else if (header.indexOf("GET /reverse") >= 0) { Serial.println("Reverse"); // "Назад" ledcWrite(pwmChannel, 255); ledcWrite(pwmChannel2, 255); digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, HIGH); digitalWrite(motor2Pin2, LOW); } // Показываем веб-страницу: 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 задаем стиль кнопок. // Попробуйте поэкспериментировать // с атрибутами «background-color» и «font-size», // чтобы стилизовать кнопки согласно своим предпочтениям: client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}"); client.println(".button { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: #4CAF50;"); client.println("border: none; color: white; padding: 12px 28px; text-decoration: none; font-size: 26px; margin: 1px; cursor: pointer;}"); client.println(".button2 {background-color: #555555;}</style>"); client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script></head>"); // веб-страница: client.println("<p><button class=\"button\" onclick=\"moveForward()\">FORWARD</button></p>"); client.println("<div style=\"clear: both;\"><p><button class=\"button\" onclick=\"moveLeft()\">LEFT </button>"); client.println("<button class=\"button button2\" onclick=\"stopRobot()\">STOP</button>"); client.println("<button class=\"button\" onclick=\"moveRight()\">RIGHT</button></p></div>"); client.println("<p><button class=\"button\" onclick=\"moveReverse()\">REVERSE</button></p>"); // client.println("<p>Motor Speed: <span id=\"motorSpeed\"></span></p>"); // client.println("<input type=\"range\" min=\"0\" max=\"100\" step=\"25\" id=\"motorSlider\" onchange=\"motorSpeed(this.value)\" value=\"" + valueString + "\"/>"); client.println("<script>$.ajaxSetup({timeout:1000});"); client.println("function moveForward() { $.get(\"/forward\"); {Connection: close};}"); client.println("function moveLeft() { $.get(\"/left\"); {Connection: close};}"); client.println("function stopRobot() {$.get(\"/stop\"); {Connection: close};}"); client.println("function moveRight() { $.get(\"/right\"); {Connection: close};}"); client.println("function moveReverse() { $.get(\"/reverse\"); {Connection: close};}</script>"); // client.println("var slider = document.getElementById(\"motorSlider\");"); // client.println("var motorP = document.getElementById(\"motorSpeed\"); motorP.innerHTML = slider.value;"); // client.println("slider.oninput = function() { slider.value = this.value; motorP.innerHTML = this.value; }"); // client.println("function motorSpeed(pos) { $.get(\"/?value=\" + pos + \"&\"); {Connection: close};}</script>"); // client.println("<script>$.ajaxSetup({timeout:1000});"); // client.println("function moveForward() { $.get(\"/forward\"); {Connection: close};}"); // client.println("function moveLeft() { $.get(\"/left\"); {Connection: close};}"); // client.println("function stopRobot() {$.get(\"/stop\"); {Connection: close};}"); // client.println("function moveRight() { $.get(\"/right\"); {Connection: close};}"); // client.println("function moveReverse() { $.get(\"/reverse\"); {Connection: close};}"); // client.println("var slider = document.getElementById(\"motorSlider\");"); // client.println("var motorP = document.getElementById(\"motorSpeed\"); motorP.innerHTML = slider.value;"); // client.println("slider.oninput = function() { slider.value = this.value; motorP.innerHTML = this.value; }"); // client.println("function motorSpeed(pos) { $.get(\"/?value=\" + pos + \"&\"); {Connection: close};}</script>"); client.println("</html>"); // Пример HTTP-запроса: «GET /?value=100& HTTP/1.1»; // Он задает коэффициент заполнения ШИМ на 100% (255): // if(header.indexOf("GET /?value=")>=0) { // pos1 = header.indexOf('='); // pos2 = header.indexOf('&'); // valueString = header.substring(pos1+1, pos2); // // Задаем скорость мотора: // if (valueString == "0") { // ledcWrite(pwmChannel, 0); // digitalWrite(motor1Pin1, LOW); // digitalWrite(motor1Pin2, LOW); // digitalWrite(motor2Pin1, LOW); // digitalWrite(motor2Pin2, LOW); // } // else { // dutyCycle = map(valueString.toInt(), 25, 100, 200, 255); // ledcWrite(pwmChannel, dutyCycle); // 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(""); } }
В ЧЕМ СУТЬ ВОПРОСА:
в коде кнопки веб-сервера, запускаемого прямо на ESP32 - работают следующим образом: нажал и работает. Пока не будет нажато что-то другое. То есть, нажал "вперед" -и машинка лупит вперед, пока не нажмешь что-то еще. Это неудобно. Хочу сделать так, чтобы "нажал и держишь" - происходит событие. Отпустил кнопку- событие прекратилось. Понятно, что скорее всего и "не веб" часть кода придется допилить. Скажем, сейчас жмешь "вперед" - отсылается "forward". Придется допилить, чтобы при отпускании отсылалось скажем "forward stop". Или что то типа того. Это понятно. Непонятно другое-как сделать отслеживание удержания/отпускания?
Это вы не туда полезли. Всякие «события нажатия» или «удержания» или «отпускания» в общем все это обрабатывает операционная система. С чего вы там машиной управляете? С Андройд смартфона? Вот туда и нужно копать. Ну как копать, изучать и думать что с полученными знаниями делать.
А ардуинке то что? Ей пришла команда - она и лупит. )
Скорее всего и в ардуине придется менять. На мой взгляд вперед/стоп плохая идея, чтобы оно хорошо работало нужна хорошая связь и надежный протокол с подтверждением, проще долбить командами вперед чтобы ехал, нет команд - стоим.