PID pro mcu v C

Aleš Novák ales.novak@t-email.cz
Úterý Srpen 7 00:41:23 CEST 2007


Kdysi jsem delal regulaci teploty v terariu. Teplota se reguluje PI
regulatorem, ktere ma cidlo v prostoru teraria a vystup tohoto PI
regulatoru se zavadi jako setpoint druheho regulatoru (ON-OFF), ktery
reguluje teplotu topneho kamene (uvnitr kamene je dalsi cidlo).

Fragmenty kodu vypadaji takhle:
Neni to sice uplne ciste, ale jakmile to zacalo fungovat, uz jsem do
toho nevrtal. Pro spravnou funkci integracni casti je nutne volat
funkci PIRegProcess() jednou za sekundu.

#define ITIME 600       //integrační čas v sekundách
#define PGAIN 10        //zesílení (PGAIN=10 je zesílení 1.0) rozsah 0..100
#define OPMIN 150       //minimální výstup v desetinách st. C
#define OPMAX 450       //maximální výstup v desetinách st. C

data int PIRegSP;       //setpoint
data int PIRegOP;       //výstup

/* provádí celočíselné dělení a kumuluje zbytky
   v případě přetečení zbytku nad nebo pod Div
   upraví výsledek i zbytek
   Value - vstupní hodnota kterou chceme dělit
   Div - čím chceme dělit
   Rem - pointer na sumu zbytků
   return - výsledek dělení s přihlédnutím na nastřádané zbytky z dřívějška */
int DivRemCumul(int Value, int Div, int data *Rem){
  int vysl;
  vysl=Value/Div;       //výsledek dělení
  *Rem+=Value%Div;      //kumulace zbytků
  if((*Rem)>=Div){
      *Rem-=Div;        //zbytek přetekl
      vysl++;
    }
  if((*Rem)<=(-Div)){
    *Rem+=Div;          //zbytek podtekl
    vysl--;
  }
  return vysl;
}

/* volat jednou za sekundu
   PV - Process Value - skutečná hodnota
   OP - Output - výstup
   return - nová hodnota OP */
int PIRegProcess(int PV, int OP){
  static bit Start=1;
  static int OldDev=0;        //minulá odchylka od SP
  static int data MemoIRem=0; //paměť zbytků po dělení (I část)
  static int data MemoPRem=0; //paměť zbytků po dělení (P část)
  int Dev;
  int DDev;
  Dev=PV-PIRegSP;           //aktuální odchylka
  if (Start){
    Start=0;
    OldDev=Dev;
  }
  DDev=(Dev-OldDev)*PGAIN;  //aktuální změna odchylky*zesílení (PGAIN=10 je zesílení 1)
  OP-=DivRemCumul(DDev, 10, &MemoPRem);   //proporcionální změna
  OP-=DivRemCumul(Dev*PGAIN, ITIME*10, &MemoIRem); //integrační změna
  if(OP>OPMAX)
    OP=OPMAX;
  if(OP<(PV-20))   //spodní doraz výstupu je 2°C pod skutečnou hodnotou
    OP=PV-20;
  OldDev=Dev;
  return OP;
}
  Novalex

MM> Zdravim Vas,
MM> vim, ze toto tema bylo jiz v konferenci probirano, nicmene, vysledek 
MM> tehdy nepadl, proto je to tu zas :-) Chtel bych se zeptat, jestli nekde
MM> nekdo nema popis navrhu PID regulatoru pro mcu v C-ku (napr. pro Atmel),
MM> ktery funguje (tzn. probehla prakticka aplikace). Nekdy v 90. letech 
MM> vyslo presne tohle v softwarovych novinach, ale Bohuzel nejsem vlastnik,
MM> takze jestli nekdo Vi, tak at prosim poradi... Preju pekny slunecny 
MM> pondelek.
MM> Toz tak, Tyca.





Další informace o konferenci Hw-list