Arduino Arm с управлением через Ethernet

Добрый день, сейчас я пытаюсь написать код, который позволит пользователю подключаться к Arduino Mega через IP-адрес и управлять роботизированной рукой по осям X и Y, а также открывать и закрывать клешню. Я столкнулся с двумя проблемами и надеюсь, что кто-нибудь сможет мне помочь

  1. Когда он подключается, в течение первых нескольких секунд сервоприводы дергаются, и я не уверен, почему
  2. В моем текущем коде я считываю URL нажатой кнопки и перемещаю рычаг на 5 градусов каждый раз, но я хотел бы иметь возможность удерживать кнопку и перемещать рычаг, но я не уверен, как это сделать
/*
 Jamil Gaufr and Eva Santos
 Bridges Project @ SUNY Purchase
 Robotic Arm Control & Interface
 */

#include <SPI.h>
#include <Ethernet2.h>
#include <Servo.h>

//Представляет сервопривод для открытия/закрытия захвата
Servo microservo;
//Представляет сервопривод для движения вперед/назад
Servo Yax;
//Представляет сервопривод для поворота влево/вправо
Servo Xax;

int pos = 0;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };   //физический mac-адрес
EthernetServer server(80);                             //порт сервера
String readString;
String x = "x =";
String y = "y = ";
String cl = "claw  = "; 


void setup() {
  // Открываем последовательную связь и ждем открытия порта:
  Serial.begin(9600);
  Yax.attach(4);
  Xax.attach(5);
  microservo.attach(6);
  // запускаем Ethernet-соединение и сервер:
  Ethernet.begin(mac);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  //Инициализирует каждую ось, начиная с положения 45 градусов
  Yax.write(100);
  Xax.write(60);
  microservo.write(90);
  //задержка 1 секунда
  delay(1000);
}


void loop() {
  // Создать клиентское соединение
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //посимвольное чтение HTTP-запроса
        if (readString.length() < 100) {
          //сохранить символы в строке
          readString += c;
          //Серийный.печать(c);
        }

        //если HTTP-запрос завершен
        if (c == '\n') {
          //Serial.println(readString); //вывести на последовательный монитор для отладки

          client.println("HTTP/1.1 200 OK"); //отправить новую страницу
          client.println("Content-Type: text/html");
          client.println();
          //начинает html-код
          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Bridges Program </TITLE>");
          //CSS-код стиля для кнопок
          client.println("<STYLE>");
          client.println(".button { ");
          client.println("background-color: #4CAF50;");
          client.println("border: none;");
          client.println("color: white;");
          client.println("padding: 15px 32px;");
          client.println("text-align: center;");
          client.println("display: inline-block;");
          client.println("font-size: 16px;");
          client.println("margin: 4px 2px;");
          client.println("cursor: pointer;");
          client.println("}");
          client.println("</STYLE>");
          //конец CSS-кода
          client.println("</HEAD>");
          client.println("<BODY>");
          //Заголовок страницы
          client.println("<H1>Welcome to Robo-Farm!</H1>");
          client.println("<hr />");
          client.println("<br />");
          //Подзаголовок
          client.println("<H2>Robotic Arm</H2>");
          client.println("<br />");
          //Создает кнопки и соответствующее расширение URL
          client.println("<a href=\"/?button1on\"\" class = \"button\">Close Claw</a>");
          client.println("<a href=\"/?button1off\"\" class = \"button\">Open Claw</a><br />");
          client.println("<br />");
          client.println("<br />");
          //Создает кнопки и соответствующее расширение URL
          client.println("<a href=\"/?button2on\"\" class = \"button\">Move forward</a>");
          client.println("<a href=\"/?button2off\"\" class = \"button\">Move Away</a><br />");
          client.println("<br />");
          client.println("<br />");
          //Создает кнопки и соответствующее расширение URL для IP-адреса
          client.println("<a href=\"/?button3on\"\" class = \"button\">Swivle left</a>");
          client.println("<a href=\"/?button3off\"\" class = \"button\" >Swivle right</a><br />");
          client.println("<br />");
          client.println("<br />");
          //Текст нижнего колонтитула
          client.println("<p>Created by Gafur & Santos.</p>");
          client.println("<br />");
          client.println("</BODY>");
          client.println("</HTML>");
          //конец html-файла
          delay(1);
          //остановка клиента
          client.stop();
          //управляет Arduino, если вы нажимаете кнопки
          //анализирует URL на предмет соответствующего расширения
          if (readString.indexOf("?button1on") > 0 && microservo.read() <= 175) { // кнопка button1 включена, это замыкающий коготь
            microservo.write(microservo.read() + 5);  // приказать сервоприводу перейти в позицию, указанную в переменной 'pos'
            delay(15);                        // ждет 15 мс, пока сервопривод достигнет положения
            Serial.println(cl + microservo.read());
          }
          if (readString.indexOf("?button1off") > 0&& microservo.read() >= 95) { // закрыть коготь
            microservo.write(microservo.read() - 5);  // приказать сервоприводу перейти в позицию, указанную в переменной 'pos'
            delay(15);                                // ждет 15 мс, пока сервопривод достигнет положения
            Serial.println(cl +microservo.read());
          }
          if (readString.indexOf("?button2on") > 0 && Yax.read() < 150 ) { // кнопка 2 включена — перемещение вперед по оси y (к сервоприводу на когте)
            Yax.write(Yax.read() - 5);                // приказать сервоприводу перейти в позицию, указанную в переменной 'pos'
            delay(15);                                // ждет 15 мс, пока сервопривод достигнет положения
            Serial.println(y + Yax.read());
          }
          if (readString.indexOf("?button2off") > 0&& Yax.read() > 70 ) {
            Yax.write(Yax.read() + 5);                // приказать сервоприводу перейти в позицию, указанную в переменной 'pos'
            delay(15);                // ждет 15 мс, пока сервопривод достигнет положения
            Serial.println(y + Yax.read());
          }
          if (readString.indexOf("?button3on") > 0 ) { // button3 поворачивается в направлении наклейки
            Xax.write(Xax.read() - 3);                // сообщаем сервоприводу перейти в позицию, указанную в переменной 'pos'
            delay(15);                                // ждет 15 мс, пока сервопривод достигнет положения
            Serial.println(x + Xax.read());
          }
          if (readString.indexOf("?button3off") > 0) {
            Xax.write(Xax.read() + 3);                // приказать сервоприводу перейти в позицию, указанную в переменной 'pos' S
            delay(15);                // ждет 15 мс, пока сервопривод достигнет положения
            Serial.println(x + Xax.read());
          }
          //очистка строки для следующего чтения
          readString = "";

        }
      }
    }
  }
}

, 👍0


1 ответ


1

Для ответа на вопрос 1 потребуется больше информации о вашем коде и проводке руки.

Вопрос 2: на самом деле, тут не так много информации, но я предположу, что вы отправляете одно сообщение на сервер arm при каждом нажатии кнопки - ? Я бы попробовал вместо этого отправлять еще одно сообщение каждые 't', начиная с (.75 * t) от message-1, где 't' - это время, необходимое для перемещения arm на 5 градусов. Это совершенно дикая догадка, основанная на необоснованных предположениях о том, что происходит сейчас, и какая часть 't', я полагаю, имела бы смысл, но это был бы мой первый, очень экспериментальный подход. И даже в этом случае, учитывая недетерминированность времени прибытия интернет-пакетов, я бы не стал делать ставку на получение очень плавного движения или мгновенной остановки при отпускании кнопки.

Мой следующий эксперимент будет заключаться в отправке на руку команд «Начать движение/Продолжить движение» при нажатии кнопки и «Остановить движение» при отпускании кнопки, при этом контроллер руки будет достаточно умен, чтобы 1) остановиться в любом случае после некоторого короткого периода отсутствия сообщений или достижения предела, и 2) не допускать накопления команд (иначе рука будет продолжать движение до тех пор, пока не достигнет предела).

Обновление:
Да, если вы используете эмулятор терминала, который может отправлять каждое нажатие клавиши, а не построчно, и не подавляет повторение клавиш. Как и выше, не накапливайте входящие нажатия клавиш, но когда вы ищете еще одно, сначала опустошите буфер, а затем ищите входящее. Если вы не нашли его в течение <TIMEOUT>, прекратите движение. <TIMEOUT> должен быть немного длиннее интервала повторения клавиш.

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

,