задаем угол для 2-х сервоприводов по очереди

Тема в разделе "Моторы, сервоприводы, робототехника", создана пользователем Антоха, 19 июл 2016.

  1. Антоха

    Антоха Нуб

    такое дело, подключено у меня 2 сервопривода к ардуинке, через компьютер хотел задавать угол на выбранный сервопривод, не могу решить проблему связанную с тем, что при выборе одного из 2-х моторов цикл проходит 1 раз и не ждет, когда я введу значение... вот код:

    #include <Servo.h>
    Servo servo;
    Servo servo2;
    String message = "";
    String message2 = "";
    void setup(){
    servo.attach(6);
    servo2.attach(9);
    Serial.begin(9600);
    }

    void loop(){
    if (Serial.available() > 0) {
    int var = Serial.read() - 48;
    switch (var) {
    case 1:
    Serial.println ("azimuth =");
    while (Serial.available()) {
    char inc = Serial.read();
    delay(100);
    Serial.print(inc);
    if (inc >= '0' && inc <= '9') {
    // если пришёл символ-цифра, добавляем его к сообщению
    message += inc; }
    else if (inc == ' ') {
    // если пришел пробел, то поворачиваем серво на заданный угол
    int agle = message.toInt();
    if(agle > 180){agle = 180;}
    if(agle < 0){agle = 0;}
    servo.write(agle);
    message = "";
    }
    }
    break;
    case 2:
    Serial.println("height =");
    while (Serial.available()) {
    char inc2 = Serial.read();
    delay(100);
    Serial.print(inc2);
    if (inc2 >= '0' && inc2 <= '9') {
    // если пришёл символ-цифра, добавляем его к сообщению
    message2 += inc2; }
    else if (inc2 == ' ') {
    // если пришел пробел, то поворачиваем серво на заданный угол
    int agle2 = message2.toInt();
    if(agle2 > 180){agle2 = 180;}
    if(agle2 < 0){agle2 = 0;}
    servo2.write(agle2);
    message2 = "";
    }
    }
    break;
    default:
    Serial.println("azimuth-1, heigh-2");
    }
    }
    }
     
  2. DIYMan

    DIYMan Guest

    Оформите, пожалуйста, код как следует, а то читать невозможно. На панели инструментов при добавлении/редактировании сообщения есть кнопочка "code".
     
  3. Антоха

    Антоха Нуб

    Код (C++):
     #include <Servo.h>
        Servo servo;
        Servo servo2;
        String message = "";
        String message2 = "";
        void setup(){
         servo.attach(6);
         servo2.attach(9);
         Serial.begin(9600);
        }
       
        void loop(){
          if (Serial.available() > 0) {
          int var = Serial.read() - 48;
            switch (var) {
              case 1:
                Serial.println ("azimuth =");
                while (Serial.available()) {
                char inc = Serial.read();
                delay(100);
                Serial.print(inc);    
                if (inc >= '0' && inc <= '9') {
                  // если пришёл символ-цифра, добавляем его к сообщению
                  message += inc; }
                    else if (inc == ' ') {
                    // если пришел пробел, то поворачиваем серво на заданный угол
                    int agle = message.toInt();
                    if(agle > 180){agle = 180;}
                    if(agle < 0){agle = 0;}
                    servo.write(agle);
                    message = "";
                  }
                }
                break;
              case 2:
                Serial.println("height =");
                while (Serial.available()) {
                  char inc2 = Serial.read();
                  delay(100);
                  Serial.print(inc2);
                  if (inc2 >= '0' && inc2 <= '9') {
                    // если пришёл символ-цифра, добавляем его к сообщению
                    message2 += inc2; }
                    else if (inc2 == ' ') {
                      // если пришел пробел, то поворачиваем серво на заданный угол
                      int agle2 = message2.toInt();
                      if(agle2 > 180){agle2 = 180;}
                      if(agle2 < 0){agle2 = 0;}
                      servo2.write(agle2);
                      message2 = "";
                    }  
                }
                break;
                default:
                Serial.println("azimuth-1, heigh-2");
        }
          }
        }
     
    думаю так будет лучше
     
  4. DIYMan

    DIYMan Guest

    Проблема в понимании работы с Serial. Ответьте на вопрос: что будет, если в приёмном буфере UART на момент проверки
    Код (C++):
    if (Serial.available() > 0) {
          int var = Serial.read() - 48;
    будет всего один символ? Отработают ли у вас при этом строчки
    Код (C++):
     while (Serial.available()) {
    ? Думаю, я ответил на вопрос "проблему связанную с тем, что при выборе одного из 2-х моторов цикл проходит 1 раз и не ждет, когда я введу значение".
     
  5. Антоха

    Антоха Нуб

    к сожалению я не совсем понимаю свою ошибку, когда я ввожу 1 или 2 мне выдает azimuth или heigh, при попытке ввести например 45 после ввода 1 или 2, мне выдаст ("azimuth-1, heigh-2");
    т.е. я не могу ввести угол
     
    Последнее редактирование: 19 июл 2016
  6. DIYMan

    DIYMan Guest

    Ещё раз: ответьте на вопрос: как отработает ваш код, если в приёмном буфере Serial всего один байт? Пока вы не поймёте логику работы вашего кода - вы не увидите в нём ошибки.
     
  7. Антоха

    Антоха Нуб

    а зачем больше ? программа прекрасно работат в вот таком виде
    Код (C++):
    #include <Servo.h>
        Servo servo;  
        String message = "";
        void setup(){
         servo.attach(6);
         Serial.begin(9600);
        }
       
        void loop(){
                while (Serial.available()) {
                char inc = Serial.read();
                Serial.print(inc);    
                if (inc >= '0' && inc <= '9') {
                  // если пришёл символ-цифра, добавляем его к сообщению
                  message += inc; }
                    else if (inc == ' ') {
                    // если пришел пробел, то поворачиваем серво на заданный угол
                    int agle = message.toInt();
                    if(agle > 180){agle = 180;}
                    if(agle < 0){agle = 0;}
                    servo.write(agle);
                    message = "";
                  }
                }
    }

             
     
  8. DIYMan

    DIYMan Guest

    Ну так если прекрасно работает - в чём проблема?
     
  9. Антоха

    Антоха Нуб

    ну это одиночкая программа, а сделать так чтобы вводить угол для одного из сервоприводов у меня не получается
     
  10. DIYMan

    DIYMan Guest

    Ещё раз: что будет, если на момент вычитывания байта из Serial - он там единственный и, например, имеет значение 2? Отработает ваш код по вычитыванию height или нет? И на следующем проходе loop - что будет?

    Пока вы не разберётесь в логике работы вашего кода - вы сколько угодно можете склеивать скетчи и утверждать, что всё работает правильно - но ошибки так и не увидите. Вы хотите, чтобы я вам на неё указал? Я и указываю, говоря вам - код работает неправильно.

    Что именно неправильно? Вот представьте: в буфере Serial лежит один байт со значением 2. Вы получаете этот байт, попадаете в case 2, там пытаетесь читать из буфера, а в буфере - фигушки. Вы вываливаетесь из loop, в это время в буфер попадает следующий байт, пришедший извне, вы в новом проходе loop читаете этот байт, и - пытаетесь сделать что? Правильно - вы ищете там 1 или 2, в то время как этот свежепришедший байт предназначен для сохранения параметра height.

    Алгоритм у вас построен неправильно.
     
  11. Антоха

    Антоха Нуб

    ошибку свою понял, но как исправить не понимаю, попробую поискать готовые коды для примера
     
  12. DIYMan

    DIYMan Guest

    Исправить - просто: нужен конечный автомат. Т.е. вы должны сохранять состояние между вызовами loop, чтобы понимать, что в данный текущий момент вы ждёте из Serial - это команда? Или этот байт надо записать как параметр команды? Или это пришёл признак конца команды, и надо сбросить состояние в начальное ожидание новой команды?
     
  13. Антоха

    Антоха Нуб

    это то понятно было с самого начала, вы можете показать небольшой пример ?
     
  14. DIYMan

    DIYMan Guest

    Ок, вот вам небольшой пример, учтите, что это псевдокод, а не готовое рабочее решение:

    Код (C++):

    typedef enum {SLEEP, WANT_COMMAND, WANT_PARAM} MACHINE_STATE;
    MACHINE_STATE state;
    String commandBuffer, paramBuffer;

    void loop()
    {
        while(Serial.available())
        {
            char ch = Serial.read();
           
            if(ch == '\r') // пропускаем ненужные символы
                continue;
               
            switch(state)
            {
                case SLEEP: // ничего не делаем
                {
                    state = WANT_COMMAND; // ждём команды
                    commandBuffer += ch;
                }
                break;
               
                case WANT_COMMAND: // ждём конца команды
                {
                    if(commandBuffer.length() == 2) // у нас команда из двух символов всегда
                    {
                        state = WANT_PARAM; // будем ждать параметра
                    }
                }
                break;
               
                case WANT_PARAM:
                {
                    if(ch == '\n') // параметр пришёл полностью
                    {
                        state = SLEEP; // вываливаемся на ожидание
                       
                        // тут смотрим, чего у нас за команда в commandBuffer
                        // и чего у нас за параметр в paramBuffer,
                        // по факту чего-то делаем
                    }
                    else
                    {
                        paramBuffer += ch; // складываем в буфер для параметра символы
                    }
                   
                }
                break;
            }
        }
    }
     
     
    ИгорьК нравится это.
  15. ИгорьК

    ИгорьК Гуру

    Тут кто-то утверждал, что языка Ардуино не существует. Вот он, типичный образец ;)