реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> PID регулятор от Atmel, как-то не радует он меня. А должен.
sigmaN
сообщение May 4 2010, 06:00
Сообщение #1


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



В общем-то ПИД регулятор применяю впервые.

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

Ну, задача известная: поддерживать заданную частоту вращения ротора безколлекторного двигателя постоянного тока.

После внимательного изучения всей учёной части я таки впал в искушение и не стал кодить сам, а скачал атмеловскую аппноту AVR221

Код регулятора:
Код
#define SCALING_FACTOR  128

//Needed to avoid sign/overflow problems
// Maximum value of variables
#define MAX_INT         INT16_MAX
#define MAX_LONG        INT32_MAX
#define MAX_I_TERM      (MAX_LONG / 2)

typedef struct PID_DATA{
  //! Last process value, used to find derivative of process value.
  int16_t lastProcessValue;
  //! Summation of errors, used for integrate calculations
  int32_t sumError;
  //! The Proportional tuning constant, multiplied with SCALING_FACTOR
  int16_t P_Factor;
  //! The Integral tuning constant, multiplied with SCALING_FACTOR
  int16_t I_Factor;
  //! The Derivative tuning constant, multiplied with SCALING_FACTOR
  int16_t D_Factor;
  //! Maximum allowed error, avoid overflow
  int16_t maxError;
  //! Maximum allowed sumerror, avoid overflow
  int32_t maxSumError;
} pidData_t;
//===========================================================

void pid_Init(int16_t p_factor, int16_t i_factor, int16_t d_factor, struct PID_DATA *pid)
// Set up PID controller parameters
{
  // Start values for PID controller
  pid->sumError = 0;
  pid->lastProcessValue = 0;
  // Tuning constants for PID loop
  pid->P_Factor = p_factor;
  pid->I_Factor = i_factor;
  pid->D_Factor = d_factor;
  // Limits to avoid overflow
  pid->maxError = MAX_INT / (pid->P_Factor + 1);
  pid->maxSumError = MAX_I_TERM / (pid->I_Factor + 1);
}
//===========================================================

int16_t pid_Controller(int16_t setPoint, int16_t processValue, struct PID_DATA *pid_st)
{
  int16_t error, p_term, d_term;
  int32_t i_term, ret, temp;

  error = setPoint - processValue;

  // Calculate Pterm and limit error overflow
  if (error > pid_st->maxError){
    p_term = MAX_INT;
  }
  else if (error < -pid_st->maxError){
    p_term = -MAX_INT;
  }
  else{
    p_term = pid_st->P_Factor * error;
  }

  // Calculate Iterm and limit integral runaway
  temp = pid_st->sumError + error;
  if(temp > pid_st->maxSumError){
    i_term = MAX_I_TERM;
    pid_st->sumError = pid_st->maxSumError;
  }
  else if(temp < -pid_st->maxSumError){
    i_term = -MAX_I_TERM;
    pid_st->sumError = -pid_st->maxSumError;
  }
  else{
    pid_st->sumError = temp;
    i_term = pid_st->I_Factor * pid_st->sumError;
  }

  // Calculate Dterm
  d_term = pid_st->D_Factor * (pid_st->lastProcessValue - processValue);

  pid_st->lastProcessValue = processValue;

  ret = (p_term + i_term + d_term) / SCALING_FACTOR;
  if(ret > MAX_INT){
    ret = MAX_INT;
  }
  else if(ret < -MAX_INT){
    ret = -MAX_INT;
  }

  return((int16_t)ret);
}


ШИМ у меня 8бит.
каждые 250ms делаю так
Код
int16_t regOut;
        cooler = coolers.collection[i];
        regOut = pid_Controller(cooler->rpm_goal, cooler_get_rpm(cooler->id), &cooler->pid );
        regOut += cooler->current_pwm_duty;
        if( regOut > 255 )
            regOut = 255;
        if( regOut < 0 )
            regOut = 0;
        cooler->current_pwm_duty = regOut;
        cooler->setPWM( cooler->current_pwm_duty );

Регулятор в целом работает, но скверно. Его невозможно настроить.
передаваемые в pid_Init() p_factor i_factor d_factor имеют слишком большой эффект.
p_factor 1 работает, но реакция медленная. А уже при 2 колеблется достаточно сильно. При 3 - 5 уже полный абзац.
i_factor вообще лучше не трогать. Там даже 1 всё ломает. )
d_factor туда-сюда +/-5 - 10 ещё терпимо, но толку это не даёт

Также, заметил очень большой "зазор". Регулятор считает, что всё хорошо, хотя на самом деле обороты от заданных могут отличаться на 200 - 300(при 1100 заданных).

Мне не нравится что здесь всё как то уж больно целочисленно делается.
Есть идея переписать это дело под фиксированную точку, чтобы коэффициенты можно было задавать с шагом хотя-бы 0.1 вместо нынешней единицы.
Однако чувствую, что просто чего-то ещё не понял и того-же эффекта можно достичь другими методами.
Может быть мне стоит разделить входные setPoint и processValue на 2(а может и на 4), тем самым уменьшу ошибку и диапазон коэффициентов расширится?

Ещё вопрос как быть с частотой регулирования: как выбрать её оптимальной?

А ещё есть функция pid_Reset_Integrator(), которая сбрасывает сумму ошибок в 0. Когда её вызывать?


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение May 4 2010, 06:54
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(sigmaN @ May 4 2010, 09:00) *
В общем-то ПИД регулятор применяю впервые.

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


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
MSprut
сообщение May 4 2010, 07:21
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 225
Регистрация: 25-04-06
Из: Украина, Луганск
Пользователь №: 16 476



Делал регулятор для бензинового двигателя на атмеловской ПИД-заготовке. Управлял заслонкой карбюратора через ШД и редуктор. Время отклика системы где-то 1-2сек, сделал измерение оборотов 10 раз/сек и одновременно пересчет управляющего воздействия. Работает вполне сносно, только i_factor очень маленький получился иначе время реакции снижается. Фактически не ПИД, а ПД регулятор получился.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 4 2010, 07:56
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sigmaN @ May 4 2010, 12:00) *
Регулятор в целом работает, но скверно. Его невозможно настроить.
передаваемые в pid_Init() p_factor i_factor d_factor имеют слишком большой эффект.
p_factor 1 работает, но реакция медленная. А уже при 2 колеблется достаточно сильно. При 3 - 5 уже полный абзац.

Не может быть. Там же всё делится на SCALING_FACTOR, который равен 128. То есть, при ошибке менее 128 и p_factor=1 отклик будет нулевым. То же и при p_factor=2 и ошибке 64.

Цитата
Также, заметил очень большой "зазор". Регулятор считает, что всё хорошо, хотя на самом деле обороты от заданных могут отличаться на 200 - 300(при 1100 заданных).


Вот это как раз по указанной мной причине. Увеличивайте коэффициенты, не бойтесь.

Цитата
Мне не нравится что здесь всё как то уж больно целочисленно делается.
Есть идея переписать это дело под фиксированную точку, чтобы коэффициенты можно было задавать с шагом хотя-бы 0.1 вместо нынешней единицы.


Там сейчас шаг 1/128 smile.gif

ЗЫ. Советую для тренировки сделать всё на плавучке, так гораздо легче почувствовать поведение системы. Оптимизировать всегда успеете.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sigmaN
сообщение May 4 2010, 17:54
Сообщение #5


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
Для успешной работы регулятора нужно иметь достаточную частоту отсчетов, иначе никакими коэффициентами невозможно регулировать.
А Вы даже не объяснили, что на входе регулятора, что на выходе.
На входе заданные обороты(об/мин) и измеренные в данный момент времени.
Измерение происходит каждый оборот кулера.
Вызов функции регулятора - каждые ~250ms

Про выход думал будет понятно из кода.
В общем воздействую я на систему путем изменения скважности ШИМ.

Цитата
Не может быть. Там же всё делится на SCALING_FACTOR, который равен 128. То есть, при ошибке менее 128 и p_factor=1 отклик будет нулевым. То же и при p_factor=2 и ошибке 64.
Логично. SCALING_FACTOR я что-то не учел.
Цитата
Вот это как раз по указанной мной причине. Увеличивайте коэффициенты, не бойтесь.
Ситуация немного прояснилась, спасибо.


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
kamil_yaminov
сообщение May 5 2010, 03:50
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 395
Регистрация: 15-02-08
Из: Новосибирск
Пользователь №: 35 064



Может еще посмотреть в сторону всяких апериодических звеньев в качестве регулятора? Гибкость не такая как у ПИД, зато реализация проще некуда. Да и проще они в настройке.
Go to the top of the page
 
+Quote Post
DL36
сообщение May 5 2010, 04:58
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 460
Регистрация: 5-10-06
Из: Херсон
Пользователь №: 21 006



Заготовка с плавающей точкой

Сообщение отредактировал rezident - May 5 2010, 18:26
Причина редактирования: Нарушение п.3.4 Правил форума.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение May 5 2010, 11:39
Сообщение #8


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



А почему в атмеловском примере нигде не учитывается частота вызова функции?
А в приведеннем примере наоборот есть real tauQuant // период квантования (реальный!!! период запуска функции регулятора), размерность - секунды


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
SSerge
сообщение May 5 2010, 12:27
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(sigmaN @ May 5 2010, 18:39) *
А почему в атмеловском примере нигде не учитывается частота вызова функции?

У них эта зависимость засунута в коэффициенты I_Factor и D_Factor. при изменении частоты дискретизации эти коэффициенты нужно будет пересчитать.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение May 5 2010, 12:36
Сообщение #10


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
У них эта зависимость засунута в коэффициенты I_Factor и D_Factor.
Понятно. В общем один раз выбрал частоту, настроил коэффициенты и забыл smile.gif)))

Кстати, а что там с частотой? Как её правильно выбрать?

вот нашел
Цитата
Есть простое правило для цифровых управляющих систем, которое гласит, что продолжительность итерации управляющего цикла должна быть между 1/10 и 1/100 желаемого времени стабилизации системы в новом положении.
1/10 и 1/100 - неплохой зазорчик )) Подозреваю, что тут нужно учитывать инерционность системы. Потому что если у меня будет желаемое время стабилизации 0.5с а двигатель здоровенный и тупой, реагирует на команды через 3секунды, то наверное ничего хорошего не выйдет из того, что я буду вызывать регулятор каждые 5ms smile.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
raf329
сообщение May 24 2010, 10:32
Сообщение #11





Группа: Участник
Сообщений: 8
Регистрация: 16-12-08
Пользователь №: 42 519



вызывать pid_Reset_Integrator() при error == 0 или когда???

Сообщение отредактировал raf329 - May 24 2010, 10:32
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 24 2010, 11:14
Сообщение #12


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(raf329 @ May 24 2010, 14:32) *
вызывать pid_Reset_Integrator() при error == 0 или когда???
А Вы сами-то что об этом думает?
Когда ошибка равна нулю - это значит что регулятор вышел на установившуюся мощность и зачем его лишать интегральной составляющую в этом момент (вдруг он плохо настроен и только на ней и теплится)?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Tanya
сообщение May 24 2010, 11:17
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883



Цитата(demiurg_spb @ May 24 2010, 15:14) *
Когда ошибка равна нулю - это значит что регулятор вышел на установившуюся мощность

Не значит.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 24 2010, 11:22
Сообщение #14


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Tanya @ May 24 2010, 15:17) *
Не значит.
Может значить, а может и нет (я утрировал).


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
raf329
сообщение May 24 2010, 11:41
Сообщение #15





Группа: Участник
Сообщений: 8
Регистрация: 16-12-08
Пользователь №: 42 519



c ПИД регулятором работаю впервые, так когда необходимо вызывать данную ф-ию?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 00:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01518 секунд с 7
ELECTRONIX ©2004-2016