РЕШЕНО Пд для двух серво от джойстика

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

  1. Jogovskiy

    Jogovskiy Нерд

    серва просто в крайнее положение встала и бездействует
     
  2. akl

    akl Гуру

    Код (C++):
    #include <Servo.h>
    const int servo1 = 3; // первая серва
    const int servo2 = 4; // вторая серва
    const int joyH = 2; // выход L/R джойстика Parallax
    const int joyV = 3; // выход U/D джойстика Parallax
    int servoVal_1=90; // переменная для хранения данных с аналогового пина
    int servoVal_2=90;
    float N = 10.;
    Servo myservo1; // создаем объект Servo для управления первой сервой
    Servo myservo2; // создаем объект Servo для управления второй сервой
    unsigned long lastmillis=0;
    unsigned long ratemillis=50;
    int val_1=90;
    int val_2=90;
    void setup() {
      myservo1.attach(servo1); // подключаем серву
      myservo2.attach(servo2); // подключаем серву
      Serial.begin(9600);
    }
    void loop() {
      outputJoystick();
      val_1 = analogRead(joyH);
      val_1 = (map(val_1, 0, 1023, 0, 180));
      val_2 = analogRead(joyV);
      val_2 = (map(val_2, 0, 1023, 0, 180));
      if(millis()-lastmillis > ratemillis){
         lastmillis=millis();
         if(servoVal_1<val_1){
            servoVal_1+=1;
         }
         else if(servoVal_1>val_1){
            servoVal_1-=1;
         }
         myservo1.write(servoVal_1);
         if(servoVal_2<val_2){
            servoVal_2+=1;
         }
         else if(servoVal_2>val_2){
            servoVal_2-=1;
         }
         myservo2.write(servoVal_2);
      }
    }

    void outputJoystick() {
      Serial.print(analogRead(joyH));
      Serial.print ("---");
      Serial.print(analogRead(joyV));
      Serial.println ("----------------");
    }
     
    так лучше?
    ошибки могут быть, я не могу щас протестировать. но принцип прост тащемта

    вот как раз одну исправил только что.

    исходные значения servoVal лучше сделать 90
     
    Последнее редактирование: 8 июн 2020
  3. parovoZZ

    parovoZZ Гуру

    Составить таблицу кривой чувствительности джойстика. Значение на серву извлекать из этой таблицы, номер ячейки задавать джойстиком.
     
  4. akl

    akl Гуру

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

    И что за джойстик? может он сам по себе плохой?
     
  5. akl

    akl Гуру

    приделал некое уплавнение хода и замедление. типа пока рычаг отодвинут от положения сервы более чем на сколько-то, серва ускоряется. и наоборот
    Код (C++):

    #include <Servo.h>
    const int servo1 = 3; // первая серва
    const int servo2 = 4; // вторая серва
    const int joyH = 2; // выход L/R джойстика Parallax
    const int joyV = 3; // выход U/D джойстика Parallax
    int servoVal_1=90; // переменная для хранения данных с аналогового пина
    int servoVal_2=90;

    unsigned long lastmillis_1=0;
    unsigned char ratemillis_1=40;
    unsigned long lastmillis_2=0;
    unsigned char ratemillis_2=40;

    int val_1=90;
    int val_1_old=90;
    int val_2=90;
    int val_2_old=90;

    Servo myservo1; // создаем объект Servo для управления первой сервой
    Servo myservo2; // создаем объект Servo для управления второй сервой

    void setup() {
      myservo1.attach(servo1); // подключаем серву
      myservo2.attach(servo2); // подключаем серву
      Serial.begin(9600);
    }
    void loop() {
        val_1 = analogRead(joyH);
        val_1 = (map_(val_1, 0, 1023, 0, 180));
        if(millis()-lastmillis_1 > ratemillis_1){ //когда пришло время обновить серву
            lastmillis_1=millis();
            if(servoVal_1<val_1){ //если записываемое в серву значение меньше конечного
                servoVal_1+=1; //придвигаем серву на 1 градус
            }
            else if(servoVal_1>val_1){ //если больше конечного
                servoVal_1-=1; //придвигаем
            }
            //если серва приблизилась к конечному на 8 градусов или еще не отдалилась на 5 от предыдущего
            if(abs(servoVal_1-val_1)<8||abs(servoVal_1-val_1_old)<5){
                if(ratemillis_1<40){ratemillis_1+=5;} //сбавляем скорость (уменьшаем частоту обновления)
            }else if(ratemillis_1>10){//и если наоборот - увеличиваем
                ratemillis_1-=5;
            }
            if(servoVal_1==val_1){val_1_old=val_1;}//когда серва на конечном - запоминаем его как предыдущее конечное
            myservo1.write(servoVal_1);
        }
        val_2 = analogRead(joyV);
        val_2 = (map_(val_2, 0, 1023, 0, 180));
        if(millis()-lastmillis_2 > ratemillis_2){
            lastmillis_2=millis();
            if(servoVal_2<val_2){
                servoVal_2+=1;
            }
            else if(servoVal_2>val_2){
                servoVal_2-=1;
            }
            if(abs(servoVal_2-val_2)<8||abs(servoVal_2-val_2_old)<5){
                if(ratemillis_2<40){ratemillis_2+=5;}
            }else if(ratemillis_2>10){
                ratemillis_2-=5;
            }
            if(servoVal_2==val_2){val_2_old=val_2;}
            myservo2.write(servoVal_2);
        }
    }

     
    то есть типа если плавно двигать джойстик то серва будет двигаться 25 градусов в секунду, а если резко - будет разгоняться до 100 градусов в секунду (40 и 10 миллисекунд между обновлениями)
     
    Последнее редактирование: 9 июн 2020
    Jogovskiy нравится это.
  6. Jogovskiy

    Jogovskiy Нерд

    cекрета никакого нет! Воот, следующем сообщением скину код с ПИ регулятором, плюс и минус системы.
    [​IMG]
     
  7. Jogovskiy

    Jogovskiy Нерд

    Внедрили ПИД регулятор, через библиотеку, подобрал коэффициенты для ПИ
    И в одну сторону значения тормозят регулирует.
    Серва стоит на 90 изначально. При повороте до 180 быстро разгоняется. при возвращение к 90 идет замедленно.В другую сторону в 0 идет замедленно, к 90 возвращается быстро.
    Однако, это уже прогресс

    Код (C++):
    #include <Servo.h>
    #include "GyverPID.h"

    GyverPID regY(0.9, 0.0018, 0, 10);  // коэф. П, коэф. И, коэф. Д, период дискретизации dt (мс)
    GyverPID regX(0.9, 0.0018, 0, 10);  // коэф. П, коэф. И, коэф. Д, период дискретизации dt (мс)



    const int servo1 = 3; // первая серва
    const int servo2 = 4; // вторая серва
    const int joyH = 2; // выход L/R джойстика Parallax
    const int joyV = 3; // выход U/D джойстика Parallax
    int servoVal; // переменная для хранения данных с аналогового пина
    int servoVa2;
    int ValY, ValX; //для хранения угла поворота

    Servo myservo1; // создаем объект Servo для управления первой сервой
    Servo myservo2; // создаем объект Servo для управления второй сервой
    void setup() {
      myservo1.attach(servo1); // подключаем серву
      myservo2.attach(servo2); // подключаем серву

      Serial.begin(9600);

      regY.setDirection(NORMAL); // направление регулирования (NORMAL/REVERSE). ПО УМОЛЧАНИЮ СТОИТ NORMAL
      regY.setLimits(0, 180);    // пределы (ставим для 8 битного ШИМ). ПО УМОЛЧАНИЮ СТОЯТ 0 И 255
      regX.setDirection(NORMAL); // направление регулирования (NORMAL/REVERSE). ПО УМОЛЧАНИЮ СТОИТ NORMAL
      regX.setLimits(0, 180);    // пределы (ставим для 8 битного ШИМ). ПО УМОЛЧАНИЮ СТОЯТ 0 И 255

    }
    void loop() {
      servoVal = analogRead(joyH);
      servoVal = (map(servoVal, 0, 1023, 0, 180));
      regY.setpoint = servoVal;        // сообщаем регулятору градус, которую он должен поддерживать

      servoVa2 = analogRead(joyV);
      servoVa2 = map(servoVa2, 0, 1023, 0, 180);
      regX.setpoint = servoVa2;        // сообщаем регулятору градус, которую он должен поддерживать


      regY.input = ValY;
      regX.input = ValX;

      ValY = servoVal - regY.getResultTimer();
      ValX = servoVa2 - regX.getResultTimer();

      myservo1.write(ValY);
      myservo2.write(ValX);
      outputJoystick();
    }

    void outputJoystick() {
      Serial.print(analogRead(joyH));
      Serial.print ("---");
      Serial.print(analogRead(joyV));
      Serial.print("----------------");
      Serial.print(analogRead(ValY));
      Serial.print ("---");
      Serial.print(analogRead(ValX));
      Serial.println ("----------------");
    }
     
  8. b707

    b707 Гуру

    что за фигню вы написали? Вы результат регулятора подаете ему на вход? - и что это дает? :)
    Я же написал вам на прошлой странице, что без обратной связи никакой регулятор тут не поможет.
     
    parovoZZ нравится это.
  9. akl

    akl Гуру

    думаю, обратная связь тут и не нужна, как собственно и пид. Мой уплавненный код думаю должен норм работать. разве что конатанты временные там подогнать надо будет. Хотя пока не очень понятно зачем эту палку двигать, то и трудно предположить с какой скоростью и как она должна двигаться
     
    Jogovskiy нравится это.
  10. Jogovskiy

    Jogovskiy Нерд

    Вся трудность, что это не моя необходимость. а задание от руководителя. Вот и все
     
  11. akl

    akl Гуру

    если задание в том чтобы непременно использовать ПИД - то придется запариться с обратной связью - припручивать к сервам потенциометры или типа того
     
  12. Jogovskiy

    Jogovskiy Нерд

    Ваш код выполняет всю функциональность! Плавности, которой хотел я --- добились
    ПД(пид)-регулятор было задание от руководителя. Что я выложил выше(с пид),хотя оно работает и кривее, чем Ваш код
    Спасибо!
     
  13. Jogovskiy

    Jogovskiy Нерд

    Ну я с этой темой не сталкивался,а мониторинг теории, чаще показывал работу с температурой.
    Однако тема побеждена! Спасибо
     
  14. parovoZZ

    parovoZZ Гуру

    Без обратной связи работает только И регулятор (по факту - интегратор)! ПИД регулятор на такое не способен в принципе.
    Определение:
    Во всех слагаемых используется сигнал РАССОГЛАСОВАНИЯ. Это и есть обратная связь.
     
  15. b707

    b707 Гуру

    знал бы заранее, что двоешнику помогаю - ни слова бы не написал

    И, кстати, не забывайте, что вы обещали "бартер". Akl вам код написал, так что ....
     
    Последнее редактирование: 9 июн 2020
  16. akl

    akl Гуру

    требую взамен видео где эта палка работает в завершенном варианте всего проекта :mad:

    кстати у меня там опечатка
    val_1 = (map_(val_1, 0, 1023, 0, 180));
    map_ - должно быть без _
    хотя если работает то наверно и так исправили.
    просто я на виндосе тестировал, а там в стандартных библиотеках нету функции такой, а само слово map зеленым выделяется походу зарезервированное какое-то, вот я и сделал там себе функцию map_
     
  17. b707

    b707 Гуру

    думаю, мы больше его не увидим. Проект сдал чужими руками и теперь пиво пьет, хад
     
  18. Jogovskiy

    Jogovskiy Нерд


    Вот видео, ту опечатку после компиляции сразу исправил.
     
    b707 и akl нравится это.
  19. Jogovskiy

    Jogovskiy Нерд

    Проект был не учебный процессом, а дополнительно. А с программированием туго!! так что вы зря о том, что ушел пить пиво и остался неблагодарен)