BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 1 av 8 Hensikt. Programmet er laget for å vise bruk av diskret inkrementell PID regulator og hvordan en kan lage en grafisk trend med flere kurver samtidig. Programmet skal kunne brukes som et utgangspunkt for forandringer.
BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 2 av 8 // BITMAP.CPP A.Lunde april 1993 med utgangspunkt i Heiny: ch6xmpl.cpp #define WIN31 #define STRICT #include <owl.h> #include <WindowsX.h> #include <math.h> #include <string.h> #include <stdio.h> #include <button.h> const BufLen=200; char s1[100]; const TIMER=100; const WORD BTN_START = 101; const WORD BTN_STOP = 102; */ //**************KLASSER****************** // lagring av utskriftdsata // brukes til debug-utskrift. // 100 millisekunder pr. oppdatering. class TExampleApp : public TApplication public: TExampleApp(LPSTR AName, HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) : TApplication(AName, hinstance, hprevinstance, lpcmdline, ncmdshow); virtual void InitInstance(); virtual void InitMainWindow(); ; class TExampleWindow : public TWindow public: // til intern bruk int i,j,marker; LONG tid; int dtimerflag; TButton *bstart, *bstopp ; // For grafisk fremstilling HPEN penr,peny,peng,penb,penm,penold,penw,penstiple; HBRUSH hbrw,hbrlg,hbrb,hbry; RECT rect,rect2; // Data for modellen double din,dout,darea,dheight,h; // data for regulatoren double T; // samplingstid her 0.1 double Kp; // Proporsjonal forsterkning double Ti; // integrasjonstid Her 10 double Td; // derivasjonstiden Her setter vi den til 0 double e; // denne error: forskjell mellom skal og er double e_1; // forrige error: double e_2; // error før forrige double u; // de i sender ut nå. Regulatorpådrag double u_1; // det vi sendte forrige gang double du; // forandring i regulatorpådrag double C1; // T/2*Ti double C2; // Td/T double y; // tilbakelest fra prosessen ( er verdi) double R; // referanse (skal verdi)
BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 3 av 8 double x1,x2,x3; //de enkelte leddene // lagring av utskrift-data typedef struct tagtrenddata LONG f1; LONG f2; LONG f3; LONG f4; LONG f5; LONG f6; TrendData; TrendData Trend[BufLen]; // Ved oppstart TExampleWindow(PTWindowsObject AParent, LPSTR ATitle); virtual void TInitModel(); virtual void Create_Pens_and_Brushes(); virtual void TInitRegulator(); // Under kjøring virtual void WMTimer(RTMessage Msg) = [WM_FIRST + WM_TIMER]; virtual void Paint(HDC hdc, PAINTSTRUCT&); virtual void Regulator(); virtual void UpdateModel(); virtual void HandleButton1Msg(RTMessage Msg) = [ID_FIRST + BTN_START]; virtual void HandleButton2Msg(RTMessage Msg) = [ID_FIRST + BTN_STOP]; // Ved avsluttning ~TExampleWindow(); virtual void Delete_Pens_and_Brushes(); ; void TExampleApp::InitMainWindow() MainWindow = new TExampleWindow(NULL, "TREND: alfaversjon: Kjør fra ProgMan"); void TExampleApp::InitInstance() // HWND hwnd; TApplication::InitInstance(); if (!SetTimer(MainWindow->HWindow, 1, TIMER, NULL)) MessageBox(NULL, "For mange timere!", Name, MB_ICONEXCLAMATION MB_OK); MainWindow->ShutDownWindow(); MainWindow->Show(SW_SHOW); void TExampleWindow::Create_Pens_and_Brushes() hbrb=createsolidbrush(rgb(0,0,0xff)); hbrlg=createsolidbrush(rgb(128,255,64)); hbrw= CreateSolidBrush(RGB(255,255,255)); hbry= CreateSolidBrush(RGB(255,0,255)); penr=createpen(ps_solid,1,rgb(255,0,0)); peny=createpen(ps_solid,1,rgb(64,64,0)); peng=createpen(ps_solid,1,rgb(0,255,0)); penb=createpen(ps_solid,1,rgb(0,0,255));
BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 4 av 8 penm=createpen(ps_solid,1,rgb(255,0,255)); penw=createpen(ps_solid,1,rgb(127,255,255)); penstiple=createpen(ps_solid,1,rgb(127,127,127)); void TExampleWindow::Delete_Pens_and_Brushes() DeleteObject(hbrLG); DeleteObject(hbrB); DeleteObject(hbrW); DeleteObject(hbrY); DeleteObject(penR); DeleteObject(penY); DeleteObject(penG); DeleteObject(penB); DeleteObject(penM); DeleteObject(penW); DeleteObject(penStiple); //*************CONSTRUCTOR**************************** TExampleWindow::TExampleWindow(PTWindowsObject AParent, LPSTR ATitle) : TWindow(AParent, ATitle) Attr.X=5; Attr.Y=5; Attr.W=630; Attr.H=470; tid=0; rect2.left=attr.x+5;rect2.top= Attr.Y+5; rect2.right= 615;rect2.bottom=435; rect.left = 0;rect.top = 0; rect.right = 300; rect.bottom =350; Create_Pens_and_Brushes();// lag disse! for(i=0;i<buflen;i++) Trend[i].f1=0; Trend[i].f2=0; Trend[i].f3=0; Trend[i].f4=0; Trend[i].f5=0; Trend[i].f6=0; j=0; marker=buflen-1; bstart=new TButton(this, BTN_START, "Start",430,400,65,25, FALSE); bstopp=new TButton(this, BTN_STOP, "Stopp", 510, 400, 65, 25, FALSE); dtimerflag=true; TInitModel(); TInitRegulator(); TExampleWindow::~TExampleWindow() Delete_Pens_and_Brushes(); // Vi fjerner i hvert fall disse.
BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 5 av 8 void TExampleWindow::Paint(HDC hdc, PAINTSTRUCT&) double x;char s[10]; HBITMAP h2bitmap; HDC h2memdc = CreateCompatibleDC(hDC); h2bitmap = CreateCompatibleBitmap(hDC,295, 350); SelectObject(h2MemDC, h2bitmap); FillRect(h2MemDC, &rect, (HBRUSH) GetStockObject(LTGRAY_BRUSH)); SetTextColor(h2MemDC,RGB(255,0,0)); SetBkMode(h2MemDC,TRANSPARENT); //tekst TextOut(h2MemDC,5,20,"100",3); TextOut(h2MemDC,5,120," 50",3); TextOut(h2MemDC,5,220," 0",3); TextOut(h2MemDC,5,320,"-50",3); //hvit firkant SelectBrush(h2MemDC,hbrW); penold=selectpen(h2memdc,penr); Rectangle(h2MemDC,50,10,BufLen+61,340); //loddrett SelectPen(h2MemDC,penStiple); MoveTo (h2memdc,55+marker,230); LineTo(h2MemDC,55+marker,20); marker--; if(marker <0) marker=buflen-1; //vannrette akser MoveTo (h2memdc,55,230); LineTo(h2MemDC,55+BufLen,230); //nr1 SelectPen(h2MemDC,penB); MoveTo (h2memdc,55,-2*trend[0].f1+230); LineTo(h2MemDC,i+55,-2*Trend[i].f1+230); //nr2 SelectPen(h2MemDC,penG); MoveTo (h2memdc,55,-2*trend[0].f2+230); LineTo(h2MemDC,i+55,-2*Trend[i].f2+230); //nr3 SelectPen(h2MemDC,penG); MoveTo (h2memdc,55,-2*trend[0].f3+230); LineTo(h2MemDC,i+55,-2*Trend[i].f3+230); //nr 4 SelectPen(h2MemDC,penM); MoveTo (h2memdc,55,-2*trend[0].f4+230); LineTo(h2MemDC,i+55,-2*Trend[i].f4+230); //nr5 SelectPen(h2MemDC,penR); MoveTo (h2memdc,55,-2*trend[0].f5+230); LineTo(h2MemDC,i+55,-2*Trend[i].f5+230); //nr6 SelectPen(h2MemDC,penY); MoveTo (h2memdc,55,-2*trend[0].f6+230); LineTo(h2MemDC,i+55,-2*Trend[i].f6+230); //(-?)positiv Y retning nedover.
BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 6 av 8 SelectObject(h2MemDC,penOld); /* DEBUG sprintf(s1,"x1=(%03d) x2(%03d) x3(%03d) u(%03d) y(%03d)du(%03d)", (int)x1,(int)x2,(int)x3,(int)u,(int)y,(int)du); */ sprintf(s1,"%3ld",tid ); TextOut(h2MemDC,5,5,s1,strlen(s1)); BitBlt(hDC, 50, 5, 295, 350, h2memdc, 0, 0, SRCCOPY); DeleteDC(h2MemDC); DeleteObject(h2Bitmap); HDC hmemdc = CreateCompatibleDC(hDC); HBITMAP hbitmap; hbitmap = CreateCompatibleBitmap(hDC,100, 200); SelectObject(hMemDC, hbitmap); SelectPen(hMemDC,penR); SelectBrush(hMemDC,hbrW); Rectangle(hMemDC,0,0,100,200); SelectPen(hMemDC,penB); SelectBrush(hMemDC,hbrB); Rectangle(hMemDC,1,199-2*Trend[BufLen-1].f1,99,199); SetTextColor(hMemDC,RGB(255,0,255)); SetBkMode(h2MemDC,TRANSPARENT); itoa((int)trend[buflen-1].f1,s,10); TextOut(hMemDC,45,100,s,strlen(s)); BitBlt(hDC, 400, 100, 100, 200, hmemdc, 0, 0, SRCCOPY); DeleteDC(hMemDC); DeleteObject(hBitmap); void TExampleWindow::TInitRegulator() Kp=2; // Proporsjonal forsterkning T=0.1; Ti=0.5;C1=T/(2*Ti); Td=0.2; C2=Td/T; // Vi tar med derivatvirkningen. y=h; // Vi leser tilbake R=y; // Vi initialiserer med samme verdi. e_2=e_1=e=0; u_1=u=0; //Ikke noe ut. x1=x2=x3=0; void TExampleWindow::WMTimer(RTMessage Msg) if (dtimerflag==true) tid++; Regulator(); UpdateModel(); InvalidateRect(HWindow,NULL,FALSE); void TExampleWindow::Regulator()
BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 7 av 8 // Sampling av inndata y=h ; // Beregning e_2=e_1; // farfar e_1=e; // far e=r-y; // sønn x1= Kp*(e - e_1); // proporsjonal-leddet x2=kp*c1*(e + e_1); // integral-leddet x3=kp*c2*(e - 2*e_1 +e_2); // derivat-leddet du=x1+x2+x3; // foranding i pådrag if (du >4) du=4; // Setter "som eksempel" 4 som maks grense if (du <-4) du=-4; // for forandring. u_1=u; // tar vare på gammel verdi u=u+du; if(u<0) u=0; // ventil stengt. if(u>100) u=100; // Ventil fullt åpen //****************MODELLEN********************** void TExampleWindow::TInitModel() din=0;dout=0;h=0; // Full åpning din 100% skal gi 1 enhet inn pr. sampl. // Full åpning dout 100% skal gi 1 enhet ut pr. sampl. void TExampleWindow::UpdateModel() din=u; if(j==20) R=40; if(j==400) R=75; if(j==200)dout=30; for (i=1;i<buflen; i++) Trend[i-1]=Trend[i]; H=H+(1.0/100)*dIn -(1.0/100)*dOut; if (H>100) H=100; if (H<0) H=0; Trend[BufLen-1].f1=y; Trend[BufLen-1].f2=u; Trend[BufLen-1].f3=R; Trend[BufLen-1].f4=e; Trend[BufLen-1].f5=dOut; Trend[BufLen-1].f6=H; j++; if (j==600) j=0; // blå //grønn //grønn //magenta //rød //gul //*** HandleButton1Msg void TExampleWindow::HandleButton1Msg(RTMessage) dtimerflag=true;
BORLAND C++ ver. 3.1 PID regulator og TREND kurver side 8 av 8 //*** HandleButton2Msg void TExampleWindow::HandleButton2Msg(RTMessage) dtimerflag=false; //********************************************** int PASCAL WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) TExampleApp ExampleApp("EXAMPLE", hinstance, hprevinstance, lpcmdline, ncmdshow); ExampleApp.Run(); return ExampleApp.Status; Kommentar Programmet er ikke ferdiglaget (alfa-versjon). Ta hensyn til dette i ditt bruk av programmet. Programmet er beregnet til bruk på elektronikkavdelingen HSV (i faget digitale systemer) der det senere kan forandres og tilpasses (samt rettes opp hvis feil). Forandringer Anbefalte forandringer: Brukeren bør ha tilgang til prosessen uten å rekompilere programmet. Brukeren bør også kunne sette PID data uten å rekompilere. En del av programmet kan forenkles. Blant annet kan det lages objekter for trend og ev. PID. Videre arbeider Datalogging til fil kan være aktuelt. Vedlegg Artikkelen Fredrik Skatvedt: En diskret inkrementell PID-regulator Elektro bd 96 nr.14 18 aug-83 Kontroller og prosess. Som kontroller benytter vi en inkrementell PID regulator som beskrevet i vedlegget. Som prosess har vi benyttet et kar. Væskestrøm til karet er regulert ved PID regulatoren. Væskestrøm ut av karet er regulert ved en pumpe.