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

 
 
> 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

Сообщений в этой теме
- sigmaN   PID регулятор от Atmel   May 4 2010, 06:00
- - Dog Pawlowa   Цитата(sigmaN @ May 4 2010, 09:00) В обще...   May 4 2010, 06:54
- - MSprut   Делал регулятор для бензинового двигателя на атмел...   May 4 2010, 07:21
- - AHTOXA   Цитата(sigmaN @ May 4 2010, 12:00) Регуля...   May 4 2010, 07:56
- - sigmaN   ЦитатаДля успешной работы регулятора нужно иметь д...   May 4 2010, 17:54
- - kamil yaminov   Может еще посмотреть в сторону всяких апериодическ...   May 5 2010, 03:50
- - DL36   Заготовка с плавающей точкой   May 5 2010, 04:58
- - sigmaN   А почему в атмеловском примере нигде не учитываетс...   May 5 2010, 11:39
|- - SSerge   Цитата(sigmaN @ May 5 2010, 18:39) А поче...   May 5 2010, 12:27
- - sigmaN   ЦитатаУ них эта зависимость засунута в коэффициент...   May 5 2010, 12:36
|- - raf329   вызывать pid_Reset_Integrator() при error == 0 или...   May 24 2010, 10:32
|- - demiurg_spb   Цитата(raf329 @ May 24 2010, 14:32) вызыв...   May 24 2010, 11:14
|- - Tanya   Цитата(demiurg_spb @ May 24 2010, 15:14) ...   May 24 2010, 11:17
|- - demiurg_spb   Цитата(Tanya @ May 24 2010, 15:17) Не зна...   May 24 2010, 11:22
|- - raf329   c ПИД регулятором работаю впервые, так когда необх...   May 24 2010, 11:41
||- - demiurg_spb   Цитата(raf329 @ May 24 2010, 15:41) c ПИД...   May 24 2010, 12:08
|- - Tanya   Цитата(demiurg_spb @ May 24 2010, 15:22) ...   May 24 2010, 12:33
|- - demiurg_spb   Цитата(Tanya @ May 24 2010, 16:33) Предуп...   May 24 2010, 13:11
- - Jenyok2   Вот реализация ПИД алгоритма. В процедуре DoChart ...   Oct 9 2011, 16:40


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

 


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


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