Управление сервоприводом с использовнием PID .

ublon92
Offline
Зарегистрирован: 10.04.2020

Здравствуйте!

ublon92
Offline
Зарегистрирован: 10.04.2020

Здравствуйте! Помогите понять что я делаю не так, при работе с библиотекой PID_V1.h

Имеется камера PIXYcam, она выдает значения положения объекта, допустим по оси Х это от 0 до 320 ( в зависимости от того где находится объект относительно кадра по данной оси), собственно камера стоит на сервоприводе который может ее поворачивать по этой оси, я пытаюсь с использованием вышеуказанной библиотеки, организовать четкий и своевременный поворот камеры за перемещающейся меткой так чтобы объект был всегда в центре кадра, однако при любых значениях PID серва люто трясется (хоть и следуя за меткой.

Следует заметить что аналогичный пример с сайта PIXY на той же механике работает идеально https://docs.pixycam.com/wiki/doku.php?id=wiki:v1:run_the_pantilt_demo

#include <PID_v1.h>
#include <PixyI2C.h>
#include <Servo.h> 
#include <Wire.h>
PixyI2C pixy;
Servo servoX;
Servo servoY;

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
double Kp=100, Ki=0, Kd=0;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

void setup(){
  
   servoX.attach(9);
  pixy.init(); 
  //initialize the variables we're linked to
  //Input = analogRead(PIN_INPUT);
  Setpoint = 160;
  
  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
 double pan;
  double serv;
  int j;
  uint16_t blocks;
  char buf[32]; 
  blocks = pixy.getBlocks();
  if (blocks)
  {
   
  pan = pixy.blocks[0].x;  //это моя координата с камеры от 0 до 320
  Input = pan;   // Это я ее скармливаю регулятору на вход
  myPID.Compute(); // Тут происходит расчет регулирования
  serv=(map(Output,0,320,180,0));  
  servoX.write(serv); //это поворачивается серва на тот угол который ему говорит регулятор
}}

 

rkit
Offline
Зарегистрирован: 23.11.2016

Тут не нужен PID совсем.

ublon92
Offline
Зарегистрирован: 10.04.2020

У меня цель разобраться с библиотекой PID регулирования, в примере по ссылке P D  регулятор используется, в этой библиотеке я ведь могу отключать ненужные мне части выставляя их на 0.

Конкретно для этой задачи уже есть готовое хорошо работающее решение (по ссылке на сайте PIXY)...

b707
Offline
Зарегистрирован: 26.05.2017

ublon92 пишет:

У меня цель разобраться с библиотекой PID регулирования

как эта цель согласуется с вашим вопросом на форуме?

ublon92
Offline
Зарегистрирован: 10.04.2020

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

b707
Offline
Зарегистрирован: 26.05.2017

ublon92 пишет:

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

для начала я бы вывел на печать величины Input и Output и посмотрел, как они меняются при реальном использовании. Соответвует ли вход реальной координате x и получается ли на выходе из регулятора адекватный этому х угол поворота сервы.

Учитесь отлаживать код, кто это может сделать вместо вас?

ublon92
Offline
Зарегистрирован: 10.04.2020

Да я первым делом это сделал, координата Х соответствует реальному положению, а вот выход не похоже что пытается достичь цели

Вот так выглядит это при отключенном сервоприводе и перемещении метки с лева на право:

304 ---Input X...   
180 ---Output SERVO  ...
282 ---Input X...   
180 ---Output SERVO  ...
253 ---Input X...   
37 ---Output SERVO  ...
237 ---Input X...   
167 ---Output SERVO  ...
200 ---Input X...   
37 ---Output SERVO  ...
158 ---Input X...   
37 ---Output SERVO  ...
136 ---Input X...   
37 ---Output SERVO  ...
94 ---Input X...   
37 ---Output SERVO  ...
29 ---Input X...   
37 ---Output SERVO  ...
15 ---Input X...   
37 ---Output SERVO  ...
3 ---Input X...   
37 ---Output SERVO  ...
 
И наоборот с права налево :
 
16 ---Input X...   
37 ---Output SERVO  ...
45 ---Input X...   
180 ---Output SERVO  ...
63 ---Input X...   
144 ---Output SERVO  ...
105 ---Input X...   
180 ---Output SERVO  ...
149 ---Input X...   
180 ---Output SERVO  ...
171 ---Input X...   
180 ---Output SERVO  ...
215 ---Input X...   
180 ---Output SERVO  ...
255 ---Input X...   
180 ---Output SERVO  ...
303 ---Input X...   
180 ---Output SERVO  ...

 

ublon92
Offline
Зарегистрирован: 10.04.2020

Да я первым делом это сделал, координата Х соответствует реальному положению, а вот выход не похоже что пытается достичь цели

Вот так выглядит это при отключенном сервоприводе и перемещении метки с лева на право:

304 ---Input X...   
180 ---Output SERVO  ...
282 ---Input X...   
180 ---Output SERVO  ...
253 ---Input X...   
37 ---Output SERVO  ...
237 ---Input X...   
167 ---Output SERVO  ...
200 ---Input X...   
37 ---Output SERVO  ...
158 ---Input X...   
37 ---Output SERVO  ...
136 ---Input X...   
37 ---Output SERVO  ...
94 ---Input X...   
37 ---Output SERVO  ...
29 ---Input X...   
37 ---Output SERVO  ...
15 ---Input X...   
37 ---Output SERVO  ...
3 ---Input X...   
37 ---Output SERVO  ...

И наоборот с права налево :

16 ---Input X...   
37 ---Output SERVO  ...
45 ---Input X...   
180 ---Output SERVO  ...
63 ---Input X...   
144 ---Output SERVO  ...
105 ---Input X...   
180 ---Output SERVO  ...
149 ---Input X...   
180 ---Output SERVO  ...
171 ---Input X...   
180 ---Output SERVO  ...
215 ---Input X...   
180 ---Output SERVO  ...
255 ---Input X...   
180 ---Output SERVO  ...
303 ---Input X...   
180 ---Output SERVO  ...
 

 

b707
Offline
Зарегистрирован: 26.05.2017

ну вот и разбирайтесь. Непонятно еще, нафига у вас там функция map, библиотека ПИД позволяет своими средствами преобразовать выход в любом диапазон.

ublon92
Offline
Зарегистрирован: 10.04.2020

Ну вот я уже все перепробовал, втч средствами библиотеки, командой установки лимитов, пример с сайта PIXY прекрасно работает с функцией map

Вот он ниже:

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

PixyI2C pixy;
Servo servoX;
Servo servoY;
#define X_CENTER        ((PIXY_MAX_X-PIXY_MIN_X)/2)       
#define Y_CENTER        ((PIXY_MAX_Y-PIXY_MIN_Y)/2)

class ServoLoop
{
public:
  ServoLoop(int32_t pgain, int32_t dgain);

  void update(int32_t error);
   
  int32_t m_pos;
  int32_t m_prevError;
  int32_t m_pgain;
  int32_t m_dgain;
};


ServoLoop panLoop(450, 600);
ServoLoop tiltLoop(300,600);

ServoLoop::ServoLoop(int32_t pgain, int32_t dgain)
{
  m_pos = PIXY_RCS_CENTER_POS;
  m_pgain = pgain;
  m_dgain = dgain;
  m_prevError = 0x80000000L;
}

void ServoLoop::update(int32_t error)
{
  long int vel;
  char buf[32];
  if (m_prevError!=0x80000000)
  {	
    vel = (error*m_pgain + (error - m_prevError)*m_dgain)>>10;
    //sprintf(buf, "%ld\n", vel);
    //Serial.print(buf);
    m_pos += vel;
    if (m_pos>PIXY_RCS_MAX_POS) 
      m_pos = PIXY_RCS_MAX_POS; 
    else if (m_pos<PIXY_RCS_MIN_POS) 
      m_pos = PIXY_RCS_MIN_POS;
  }
  m_prevError = error;
}

void setup()
{
  servoX.attach(9);
  servoY.attach(10);
 
  pixy.init();
}

void loop()
{ 
  static int i = 0;
  int j;
  uint16_t blocks;
  char buf[32]; 
  int32_t panError, tiltError;
  
  blocks = pixy.getBlocks();
  
  if (blocks)
  {
    panError = pixy.blocks[0].x-X_CENTER;
    tiltError = Y_CENTER-pixy.blocks[0].y;
    
    panLoop.update(panError);
    tiltLoop.update(tiltError);

      
     servoX.write(map(panLoop.m_pos,0,1000,0,180)); 
     servoY.write(map(tiltLoop.m_pos,0,1000,0,180));
    i++;
    

  }  
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Что бы не тряслось, программы использующие ПИД рекомендуется отлаживать на маленьком стенде, состоящим из термодатчика резистора нагрева и стакана воды. Меняя заданную температуру можно смотреть как ПИД реагирует на разные коэффициенты. Меняя количество воды можно исследовать, как параметры системы влияют на эффективность ПИД. Это конечно если интересует научится настраивать ПИД правильно. А так, вообще, ПИД здесь лишний. Если уж нужно точно стоять в центре то достаточно ПИ. А если просто следить, то просто П  даст вполне приемлемый результат.   

ublon92
Offline
Зарегистрирован: 10.04.2020

Цель не научиться настраивать PID а для начала научиться пользоваться библиотекой в принципе, чего у меня на данный момент не выходит.

По настройке на нагревателе я тренировался на 3д принтере, все получилось, плюс опять таки в примере с сайта PIXY используется P D, регулятор, он работает четко, по всем описанным в литературе правилам настройки PID (на той же механике, на том же питании и.п.)...

А с использованием библиотек трясет при любых раскладах!

Я где-то допускаю ошибку при использовании этих библиотек...

b707
Offline
Зарегистрирован: 26.05.2017

ublon92 - сразу не заметил - вы же библиотеку ПИД используете категорически неверно. Вы для начала разберитесь, что такое Input и SetPoint. Вы Сетпойнт вообще не задаете, а в Инпут пихаете точку, куда хотите повернуть серву.

А вообще вашу задачку не только что МОЖНО решить без ПИД - ее как раз НУЖНО решать без ПИД.

ПИД плохо работает на системах, где уставка хаотически меняется во время регулировки,. Если вы это затеяли только для обучения - выберите другой пример для тестирования ПИД

rkit
Offline
Зарегистрирован: 23.11.2016

ublon92 пишет:

Код приведенный в моем посте не работает,

И не будет. Потому что ты пытаешься забить шуруп молотком. Разбирайся на другой задаче.

ublon92
Offline
Зарегистрирован: 10.04.2020


void setup(){ 

Setpoint = 160;

Так вот же я задаю Setpoint, у меня 320 это максимальное число по ширине соотв середина кадра это 160

А в Input я подаю точку где в текущий момент находится метка (это же и есть обратная связь)

Хорошо, а если камера находится скажем на квадрокоптере (или на ином тяжелом транспортном средстве) и нужно его сориентировать центром камеры относительно метки, там тоже можно без PID обойтись? 

И в чем проблема на этом примере отключить любую ненужную составляющею, поставив ее в 0 ? 

 

Про "шурупы молотком", пример с P D регулятором на сайте камеры же идеально работает? Почему не будет то?

Я ведь коэфф I и D выставляю на 0, соотв они не участвуют в расчетах...

Остается только пропорциональный регулятор.

nik182
Offline
Зарегистрирован: 04.05.2015

И дергается? Значит слишком быстро управляешь. Поставь простой делэй, для проверки, милисекунд на 200 - 2000 и посмотри когда дёргаться перестанет.и Зависит от скорости отработки машинки. 

rkit
Offline
Зарегистрирован: 23.11.2016

ublon92 пишет:

Остается только пропорциональный регулятор.

Который НЕ НУЖЕН. Нужно просто посчитать абсолютные координаты. Всё. Никакой импульсной величины тут нет. Эту задачу уже решает внутренняя электроника серво.

b707
Offline
Зарегистрирован: 26.05.2017

ublon92 пишет:
Остается только пропорциональный регулятор.

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

Думаю. что ты все-таки путаешься в исходных данных. но не видя камеры - не вполне уверен, что у тебя Инпут, а что Сетпойнт.

И, кстати, Kp =100 - это офигеть как много. пропорциональный коэфф обычно берут в районе единицы, максимум 3-5

ublon92
Offline
Зарегистрирован: 10.04.2020

Метка нелинейно перемещается, задача получить максимальную скорость отслеживания этой метки. 

По этой же причине задержка тут не подходит

 

ublon92
Offline
Зарегистрирован: 10.04.2020

Кр я ставил от 0.1 до 1000 с разным шагом, если ставлю 0.1 то он его перестает отслеживать.

Однако если я тот же P в примере с PIXY камеры ставлю в 0.1 то происходит то что должно происходить, камера оооооочень медленно и плавно движется за меткой, увеличиваю Кр до 450 камера все быстрее и быстрее начинает реагировать на перемещение метки, если ставлю P 600 и выше то при резких перемещениях камера начинает сама собой раскачиваться (как и в теории любого PID или PD, регулятора, соотв коэффициентом D, потом я убираю небольшой промах при высоких значениях P (400-450)) Но это в коде из примера (который так же в моем посте выше)

А в моем варианте кода она дрожит всегда

 

Что конкретно нужно видеть в камере вам?

Вот описание ее работы с ардуиной:

https://docs.pixycam.com/wiki/doku.php?id=wiki:v1:arduino_api

 

Инпут это текущая координата метки (ее дает камера от 0 (левый  край) до 320 (правый край))

Сетпоинт это то куда я хочу камеру повернуть, ровно центр 320/2=160

nik182
Offline
Зарегистрирован: 04.05.2015

Задержка нужна для того, что бы время механического перемещения сервы не влияло на расчет ПИД. Если ты этого не понимаешь, то настроить ПИД без дерганий не сможешь. Есть понятие постоянная времени системы. Если управляющее воздействие быстрее постоянной времени то в расчёт ПИД вносится дополнительная ошибка. Быстрее от этого система работать не станет. Хуже работать регулятор - да. 

ublon92
Offline
Зарегистрирован: 10.04.2020

Для чистоты эксперимента сейчас попробовал ставить задержу:

5, 10, 20, 30, 100, 200, 500, мс

При значении 500мс, при виде метки камера просто отворачивается от нее, (без  задержки вовсе следит не теряя из виду, но люто раскачиваясь в стороны)

Чем больше задержка в общем тем больше успевает камера повернуться в сторону от метки...

b707
Offline
Зарегистрирован: 26.05.2017

ublon92 пишет:

Однако если я тот же P в примере с PIXY камеры ставлю в 0.1 то происходит то что должно происходить, камера оооооочень медленно и плавно движется за меткой, увеличиваю Кр до 450 камера все быстрее и быстрее начинает реагировать на перемещение метки,

слушай. ну есть же у тебя готовый пример ПИД в этом коде от PIXY. Ну вот и сравни, как одни и те же входные данные работают там и как они работают в твоем ПИДе.

И разберись в чем разница. Математика-то простая. пятого класса максимум. Кто это должен за тебя делать?

nik182
Offline
Зарегистрирован: 04.05.2015

ublon92 пишет:

Для чистоты эксперимента сейчас попробовал ставить задержу:

5, 10, 20, 30, 100, 200, 500, мс

При значении 500мс, при виде метки камера просто отворачивается от нее, (без  задержки вовсе следит не теряя из виду, но люто раскачиваясь в стороны)

Чем больше задержка в общем тем больше успевает камера повернуться в сторону от метки...

Значит, как и говорил b707,  не правильно вводятся данные в ПИД. Поменяй знак в управлении. Если едет в другую сторону, значит команда дает поворот не в ту сторону. Надо найти и исправить. 

ublon92
Offline
Зарегистрирован: 10.04.2020

Я и не говорю что тут кто, то что то мне должен!

Прошу людей кто разбирается и у кого есть ЖЕЛАНИЕ помочь (а иначе для чего тут вообще разводить дискуссии?) посмотреть что я не правильно делаю, потом у кого нибудь возникнет подобный вопрос и он сможет прочитать материал по делу!

А не балаган про гвозди с молотком и рассуждения зачем мне это вообще надо.

Пример с сайта PIXY на P D регуляторе же сделан, и хорошо работает (отсюда могу сделать вывод что такая реализация вопроса следования камеры за меткой вполне возможна...)

Естественно если я меняю знак (команда дает поворот не в ту сторону) то камера сразу отворачивается от метки, я же добился чтобы она таки за меткой следила, но вот незадача камера постоянно дергается, (в процессе перемещения метки она плавно следует за ней, но когда дело подходит к центру начинается раскачка)

С математикой я пока еще не разбирался, но чую что скоро начну, на данном этапе хочу воспользоваться готовой библиотекой для этого мероприятия, зачем мне заново изобретать колесо? Когда оно уже есть готовое.

Вы же не идете каждый раз изобретать транспортное средство когда вам нужно переместиться из пункта А в пункт Б, верно? 

nik182
Offline
Зарегистрирован: 04.05.2015

Ну вот. Новые вводные. Написать нужно много, а лень. Если в двух словах то, если дёргаться начинает на походе, то менять знак надо не у всего воздействия, а у интегрального. Он работает при малых отклонениях от цели. Диф работает при больших. Я б выводил в сериал все три компаненты ПИД и проанализировал, какая глючит. С ней и разбирался. Ее величина будет больше, чем разность между текущем положением и целью. Вообще библиотеки это зло. ПИД это 6 строчек кода. Я не встечал сторонней библиотеки которая бы была написана корректно. Никто не заморачивается оптимизацией.