Сделал управление радиоуправляемой машинкой, надо изменить веб часть-удержание, отпуск кнопки

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Всем доброго!

Сделал вот по этому мануалу управление по 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". Или что то типа того. Это понятно. Непонятно другое-как сделать отслеживание удержания/отпускания?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Это вы не туда полезли. Всякие «события нажатия» или «удержания» или «отпускания» в общем все это обрабатывает операционная система. С чего вы там машиной управляете? С Андройд смартфона? Вот туда и нужно копать. Ну как копать, изучать и думать что с полученными знаниями делать. 
А ардуинке то что? Ей пришла команда - она и лупит. )

Morroc
Offline
Зарегистрирован: 24.10.2016

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