Управление скоростью вращения вала сервопривода

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

  1. SnJon

    SnJon Нерд

    Всем доброго времени суток! В проекте потребовалось плавное управление сервоприводами. Нашел на просторах интернета функцию для управления одним серво:

    Код (C++):
    #include <Servo.h>
    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }
    void servoslow( Servo num, int pos, int time, int start)  // robotday.ru *** Функция для управления скоростью сервопривода ***
    {
      num.write(start);
     
      for ( int i=start; i<pos; i++)
          {  num.write(i);
             delay(time);
          }
    }
    void loop()
    {
       
    servoslow(myservo, 180, 10, 0);
    }
    Источник

    Это все хорошо, но как сделать управление сразу всеми серво, а не чтобы они по очереди двигались?

    К примеру, такое реализовано в данных контроллерах, где указывается время движения серво

    Код (C++):
    <ch> = Servo number, range 1~32 (decimal number)
    <pw> = Pulse width (servo position), range: 500~2500. Unit: us (microseconds)
    <time> = Time used to move to the position, effective for all servos.
    Гуру программирования, помогите пожалуйста =)
     
  2. vvr

    vvr Инженерище

    библиотека VarSpeedServo - контроль скорости вращения сервы
     
    SnJon нравится это.
  3. SnJon

    SnJon Нерд

    Спасибо! Только мне не совсем помогло. У меня стоит Multiservo Shield с библиотекой Multiservo. Может есть метод работы без библиотеки? Заранее благодарен
     
  4. vvr

    vvr Инженерище

    делаете небольшие интервалы через millis() и поворачиваете серву шажками
     
    SnJon нравится это.
  5. SnJon

    SnJon Нерд

    Ну с одной сервой это не проблема. Попробовал сделать с 6-ю, они по очереди устанавливаются в нужный угол с задержкой. А нужно чтобы все одновременно. В этом то вся и проблема
     
  6. vvr

    vvr Инженерище

    SnJon нравится это.
  7. SnJon

    SnJon Нерд

    В общем написал свой алгоритм, стало интересно решить задачу. Вот что из этого вышло:
    Код (C++):
    int targ[10];
    int nservo[10];

    void loop()
    {
         targ[0] = 51;
          targ[1] = 20;
          targ[2] = 125;
          targ[3] = 122;
          targ[4] = 145;
          targ[5] = 45;
         
          nservo[0] = 1;
          nservo[1] = 2;
          nservo[2] = 3;
          nservo[3] = 7;
          nservo[4] = 8;
          nservo[5] = 9;
                                                 
         servoslow(6, targ, nservo, 5);
         }
    }


    void servoslow (int C_SERVO,  int target[10], int numservo[10], int ms)
    {
         
           
            int bvalue[C_SERVO];                        
            int sread[C_SERVO];
            int newsread[C_SERVO];
           
            for (int i=0; i<C_SERVO; i++)
            {
                int temp = numservo[i];
                sread[i] = Servo[temp].read();
                newsread[i] = sread[i];
                bvalue[i] = abs(sread[i] - target[i]);
                 if (bvalue[i] > tmp)
                 {
                  tmp = bvalue[i];
                  wnum = i;
                 }
            }
           
        while (newsread[wnum] != target[wnum])
            {
                  for (int i = 0; i<C_SERVO; i++)
                  {
                      if ((sread[i]-target[i])>0)
                      {
                       int temp = numservo[i];                      
                       Servo[temp].write(newsread[i]-1);
                       if (newsread[i] != target[i])
                       newsread[i]-=1;
                     
                       Serial.print(newsread[i]);
                       Serial.print(" ");
                       }
                     
                       if ((sread[i]-target[i])<0)
                       {
                        int temp = numservo[i];
                        Servo[temp].write(newsread[i]+1);
                        if (newsread[i] != target[i])
                        newsread[i]+=1;
                       
                       Serial.print(newsread[i]);
                       Serial.print(" ");
                       }
           
             delay(ms);
            }
              Serial.println();                          
            }
            Serial.println("done!");
    }

     
    Одно не смог решить, как можно более удобно передавать массивы в функцию? На данном этапе придется каждый раз перезаписывать каждое значение массива - это не очень удобно
     
  8. Onkel

    Onkel Гуру

    в функцию передается не сам массив (в atmeg328 оперативки и так кот наплакал), а указатель на массив , и , если нужно, число элементов массива.
     
    SnJon нравится это.
  9. SnJon

    SnJon Нерд

    Ну это как я понимаю решит проблему с памятью, но не с удобством вызова функции?
     
  10. Onkel

    Onkel Гуру

    отнюдь. Нет под руками примера для ардуины, у меня в С примерно так:
    unsigned char buf[128] // Определяем массив buf 128 элементов

    пишем функцию , например
    void DoSomething(unsigned char *t, unsigned char q)
    {
    for (i=0;i<q;i++)
    DoSomethingElse(t+i)
    }

    а функцию вызываем
    DoSometnig(buf,128);

    but- он и указатель на массив тоже

    ...
     
    SnJon нравится это.
  11. SnJon

    SnJon Нерд

    Ну а как мне передать несколько однотипных данных в функцию? Для этого нужен отдельный массив видимо.

    Я про вот эти имею ввиду:

    Код (C++):
    targ[0] = 51;
          targ[1] = 20;
          targ[2] = 125;
          targ[3] = 122;
          targ[4] = 145;
          targ[5] = 45;
       
          nservo[0] = 1;
          nservo[1] = 2;
          nservo[2] = 3;
          nservo[3] = 7;
          nservo[4] = 8;
          nservo[5] = 9;
     
  12. Onkel

    Onkel Гуру

    сделайте эти массивы глобальными и передавайте указатель, например функция будет от targ и nservo, это и будут указатели на массивы
     
  13. SnJon

    SnJon Нерд

    В том то и дело что эти массивы будут индивидуальными для каждого вызова функции servoslow. Можно было бы их передавать как значение int. Создал функцию void f(int a) и при вызове указал f(6). Жаль с массивами не прокатит =(
     
  14. Onkel

    Onkel Гуру

    почему же не прокатит? А массив указателей на массивы?
     
  15. SnJon

    SnJon Нерд

    Можно пример, пожалуйста
     
  16. Onkel

    Onkel Гуру

    вместо targ[] и servo[] сделайте один массив data[2][5] и передавайте указатель на массив data и unsigned char номер элемента в массиве, с которого надо начать.
     
  17. В описании функции (из источника):

    Здесь используем функцию servoslow.

    Функция управления скоростью сервопривода использует следующие параметры:
    1. Имя сервопривода
    2. Конечная позиция сервопривода ( в градусах)
    3. Задержка между каждым поворотом в один градус ( чем больше значение, тем медленнее будет поворачиваться сервопривод)
    4. Начальная позиция сервопривода.
    Servonum,intpos,inttime,intstart

    Подскажите, как задать эти значения в виде переменных ? Если в зависимости от положения устройства (можно вычислить по скорости перемещения), угол должен меняться от начального к конечному углу,
    Т.е. Сначала задаётся начальный угол переменным резистором, запоминается, затем конечный так же. А задержка определяется скоростью перемещения устройства и если ОнО стоит, угол не меняется ?