Пример проектирования дискретного ПИД-регулятора


             

ЭТАП 4 - Написание программы ПИД-регулятора для ЦВМ


Не затрагивая вопрос выбора ЦВМ, скажем, что это может быть периферийный контроллер (PIC), микроЭВМ (8051, AVR, ...), ЭВМ (x86, ...), промышленный контроллер, DSP (ADSP-21xxx, TMS320, ...) или схема на жесткой логике. Составление программы выполняющей расчет рекурсивного уравнения (*) обычно не вызывает затруднений, если ЦВМ имеет команды деления и умножения чисел (желательно с большой мантиссой и плавающей точкой).

В табл. 1 и 2 представлены программы рекурсивного цифрового фильтра второго порядка. Они написаны на языках C++ и Паскале в средах разработки Borland C++Builder 4 и Borland Delphi 4 в соответствии с технологией создания моделей пользователя для программы VisSim. При трансляции получается файл pid.dll, главная функция которого "zW" может быть включена в модель программы VisSim с помощью блока "userFunction" (см. рис. 7). При записи коэффициентов РУ (*) в параметры блока и стробировании частотой 2000 Гц - это и будет модель искомого дискретного ПИД-регулятора.

Блок "userFunction", с помощью которого подключена библиотека pid.dll

Рис. 7

Таблица 1

Файл pid.cpp

#include <math.h>
#include <condefs.h>
#pragma hdrstop
#define EXPORT32 __declspec(dllexport)

//---------------------------------------------------------------------------
struct z_TF_INFO {
  double k;        // коэффициент усиления
  double b0,b1,b2; // коэффициенты полинома числителя
  double a0,a1,a2; // коэффициенты полинома знаменателя
};

//---------------------------------------------------------------------------
extern "C" {
  double buffer_x[2]={0,0}, buffer_y[]={0,0};
  double c, help_y;
//************ Функция размещения параметров ********************************
//************ Вызывается VisSim-ом при создании блока **********************
EXPORT32 long WINAPI zWPA(short FAR *ppCount){
  *ppCount=7; // число записываемых в файл vsm параметров модели пользователя
  return sizeof(z_TF_INFO);
}
//************ Процедура инициализации параметров ***************************
//************ Вызывается VisSim-ом после PA функции ************************
EXPORT32 void WINAPI zWPI(z_TF_INFO *zTF){
  zTF->k=31.9016459416667;
  zTF->b0=1;
  zTF->b1=-1.9894401341982;
  zTF->b2=0.98945592544195;
  zTF->a0=1;
  zTF->a1=-1.3333333333333;
  zTF->a2=0.33333333333333;
}
//************ Функция изменения параметров *********************************
//************ Вызывается VisSim-ом при нажатии правой клавиши мыши *********
EXPORT32 LPSTR WINAPI zWPC(z_TF_INFO *zTF){
  return "k;b0;b1;b2;a0;a1;a2";
}
//************ Процедура Simulation Start ***********************************
//************ Вызывается VisSim-ом на первом шаге моделирования ************
EXPORT32 long WINAPI zWSS(z_TF_INFO *zTF, long *runCount){
  buffer_x[0]=0; buffer_x[1]=0;
  buffer_y[0]=0; buffer_y[1]=0;
  help_y=0; c=0;
  return 0;
}
//************ Процедура Simulation End *************************************
//************ Вызывается VisSim-ом на последнем шаге моделирования *********
EXPORT32 long WINAPI zWSE(z_TF_INFO *zTF, long *runCount){
  return 0;
}
//************ Это базовая процедура в DLL **********************************
//************ Вызывается VisSim-ом на каждом шаге моделирования ************
EXPORT32 void WINAPI zW(z_TF_INFO *zTF, double FAR x[], double FAR y[]){
  if (x[0]==1 && c==0) {
  // Непосредственный алгоритм с двумя буферами
    help_y=(zTF->k*(x[1]*zTF->b0+buffer_x[0]*zTF->b1+buffer_x[1]*zTF->b2)
                -(buffer_y[0]*zTF->a1+buffer_y[1]*zTF->a2)) / zTF->a0;
    buffer_x[1]=buffer_x[0]; buffer_x[0]=x[1];
    buffer_y[1]=buffer_y[0]; buffer_y[0]=help_y;
  // Непосредственный алгоритм с одним буфером
  /* double help;
    help=(x[1]-(buffer_x[0]*zTF->a1+buffer_x[1]*zTF->a2))/zTF->a0;
    help_y=(help*zTF->b0+buffer_x[0]*zTF->b1+buffer_x[1]*zTF->b2)*zTF->k;
    buffer_x[1]=buffer_x[0]; buffer_x[0]=help;*/
  }
  y[0]=help_y;
  c=x[0]; // организованна синхронизация блока по фронту
};
//---------------------------------------------------------------------------
}// end extern "C" {
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*){
  return 1;
}
<


Содержание  Назад  Вперед