home *** CD-ROM | disk | FTP | other *** search
- PROGRAM BODE ;
-
- { Program to calculate the frequency response plot (bode diagram)
- for a transfer function provided to the program in terms of
- numerator and denominator polynominal coefficients of the
- Laplace transfer function. The order of the polynominals must
- be less than or equal to 20.
-
- First revision completed by Mike Secord on 10/23/84
- The program was written to try to optimize the execution speed.
- Second revision -- fix bugs 11/15/84
- Revision 2.1 -- display program description when executed 8/34/85 }
- CONST
- VERSION='VERSION 2.1' ;
- MAXSTEPS=100;
- NATLOG=2.302585093;
-
- TYPE
- NUMFREQ=ARRAY[1..MAXSTEPS] OF REAL;
- COEF_ARRAY = ARRAY [0..20] OF REAL ;
- NAME = ARRAY [1..11] OF CHAR ;
-
- VAR FREQVAL:NUMFREQ;
- NSTEP,I:INTEGER;
- M : INTEGER ; { ORDER OF NUMERATOR POLYNOMIAL }
- N : INTEGER ; { ORDER OF DENOMINATOR POLYNOMIAL}
- PN : COEF_ARRAY ; { ARRAY OF NUMERATOR POLYNOMIAL COEFFICIENTS }
- PD : COEF_ARRAY ; { ARRAY OF DENOMINATOR POLYNOMIAL COEFFICIENTS }
- INTYPE : NAME ; { NAME FOR TYPE OF INPUT (DENOM OR NUM) }
- KGAIN, W, MAGN, MAGD, PHASEN, PHASED, MAGNITUDE, LOGMAG, PHASE : REAL ;
- ANS : CHAR ;
-
- PROCEDURE TRANFUNC(INTYPE :NAME ; VAR O : INTEGER; VAR C : COEF_ARRAY) ;
- {procedure to input the transfer function (pole and zero) information
- for the BODE program.}
-
- VAR
- L : INTEGER ;
-
- BEGIN
- WRITELN ;
- WRITE(' Enter the order of the ',INTYPE,' polynomial (20 Max) : ') ;
- READLN(O) ;
- WRITELN ;
- WRITELN(' Enter the coefficients of the ',INTYPE,' polynomial in ') ;
- WRITELN(' desending order (PLEASE ENTER ZERO COEFFICIENTS ALSO). ') ;
- WRITELN(' ',INTYPE,' coefficients : ') ;
- FOR L := O DOWNTO 0 DO
- BEGIN
- WRITE(' S',L,': ') ;
- READ(C[L]) ;
- IF( (O-L) MOD 4 = 0) AND (L <> O) THEN WRITELN ;
- END ;
- WRITELN ; WRITELN ;
- END ;
-
- PROCEDURE CALCFREQ(VAR FREQ:NUMFREQ;VAR V:INTEGER);
- {calculate series of frequencies to be used for bode plot}
- VAR INITIALFREQ:REAL;
- FINALFREQ:REAL;
- LOGDECADE_STEP:INTEGER;
- STARTFREQ:REAL;
- ENDFREQ:REAL;
- TRUNCFREQ:INTEGER;
- DIFF:REAL;
- LOGSTEP:REAL;
- LOGFREQ:REAL;
-
- BEGIN {input initial frequency,final frequency,and number of steps per decade}
- WRITELN ;
- WRITE(' Type initial frequency desired in output: ');
- READLN(INITIALFREQ);
- INITIALFREQ := INITIALFREQ - INITIALFREQ/1000.0 ; {Allow for trunc}
- WRITE(' Type final frequency desired in output: ');
- READLN(FINALFREQ);
- FINALFREQ := FINALFREQ + FINALFREQ/1000.0 ; {Allow for truncation}
- WRITE(' Type no. of log steps desired for each decade of output: ');
- READLN(LOGDECADE_STEP);
- {calculate log of input frequencies and frequency steps}
- STARTFREQ:=(1/NATLOG)*LN(INITIALFREQ);
- ENDFREQ:=(1/NATLOG)*LN(FINALFREQ);
- TRUNCFREQ:=TRUNC(STARTFREQ);
- DIFF:=STARTFREQ-TRUNCFREQ;
- LOGSTEP:=1/LOGDECADE_STEP;
- LOGFREQ:=((TRUNC(DIFF/LOGSTEP))/LOGDECADE_STEP)+TRUNCFREQ;
- V:=0;
- {calculate series of frequencies and put into array}
- WHILE LOGFREQ<=ENDFREQ DO
- BEGIN
- V:=V+1;
- FREQ[V]:=EXP(NATLOG*LOGFREQ);
- LOGFREQ:=LOGFREQ+LOGSTEP;
- END;
- END;
-
- PROCEDURE CALC(ORDER : INTEGER; C : COEF_ARRAY; VAR MAG, ANGLE : REAL;
- W : REAL) ;
- { Procedure to calculate the magnitude and phase response for the numerator
- or denominator as called. The total response will be calculated in the
- main body of the program. }
-
- FUNCTION CMULT(W,K : REAL; EXPON : INTEGER) : REAL ;
- { This function calculates the w terms to the respective powers as called
- and was faster than using EXP(U*LN(A)).}
-
- VAR
- P : INTEGER ;
- TEMP2, MPLICND : REAL ;
-
- BEGIN
- MPLICND := W ; TEMP2 := W ;
- CASE EXPON OF
- 0 : CMULT := K ;
- 1 : CMULT := W*K ;
- 2..20 : BEGIN { 20 needs to be changed for more than 20th order}
- FOR P := 2 TO EXPON DO TEMP2 := TEMP2*MPLICND ;
- CMULT := K*TEMP2 ;
- END ;
- END ; {case}
- END ; {function CMULT }
-
- VAR
- TEMP, RCMULT, ICMULT : REAL ;
- I1 : INTEGER ;
-
- BEGIN
- RCMULT := 0.0 ; ICMULT := 0.0 ;
- FOR I1 := 0 TO ORDER DO
- BEGIN
- { NOTE: These sets for the case statement have to be added to
- in increments of 4 if the procedure is
- to calculate the response of a polynominal > 20. }
- CASE I1 OF
- 0,4,8,12,16,20 : RCMULT := RCMULT + CMULT(W,C[I1],I1) ;
- 1,5,9,13,17 : ICMULT := ICMULT + CMULT(W,C[I1],I1) ;
- 2,6,10,14,18 : RCMULT := RCMULT - CMULT(W,C[I1],I1) ;
- 3,7,11,15,19 : ICMULT := ICMULT - CMULT(W,C[I1],I1) ;
- END ; {case}
- END ; {for}
- MAG := SQRT(RCMULT*RCMULT + ICMULT*ICMULT) ;
- IF (RCMULT = 0.0) AND (ICMULT > 0.0) THEN ANGLE := PI/2.0 ;
- IF (RCMULT = 0.0) AND (ICMULT < 0.0) THEN ANGLE := -PI/2.0 ;
- IF (ICMULT = 0.0) AND (RCMULT < 0.0) THEN ANGLE := PI ;
- IF RCMULT > 0.0 THEN ANGLE := ARCTAN(ICMULT/RCMULT) ;
- IF (RCMULT < 0.0) AND (ICMULT > 0.0) THEN
- ANGLE := ARCTAN(ICMULT/RCMULT) + PI ;
- IF (RCMULT < 0.0) AND (ICMULT < 0.0) THEN
- ANGLE := ARCTAN(ICMULT/RCMULT) - PI ;
- END ; { procedure ccalc }
-
- {*************** MAIN PROGRAM ****************************************}
-
- BEGIN
- CLRSCR ;
- GOTOXY(15,8) ;
- WRITE('********** PROGRAM BODE **********') ;
- GOTOXY(26,9) ;
- WRITE(VERSION) ;
- GOTOXY(1,11) ;
- WRITELN(' Program to calculate the frequency response plot (Bode diagram)');
- WRITELN(' for a transfer function provided to the program in terms of');
- WRITELN(' numerator and denominator polynominal coefficients of the');
- WRITELN(' Laplace transfer function. The order of the polynominals must');
- WRITELN(' be less than or equal to 20.');
- WRITELN ;
- WRITELN(' Enter data when prompted (Do NOT forget the zero coefficients)');
- WRITELN ; WRITELN ;
- INTYPE := ' numerator ' ;
- TRANFUNC(INTYPE,M,PN) ;
- INTYPE :='denominator' ;
- TRANFUNC(INTYPE,N,PD) ;
- WRITELN ;
- WRITE(' Enter the gain coefficient (Enter 1 if there is none) : ') ;
- READLN(KGAIN) ;
- CALCFREQ(FREQVAL,NSTEP);
- WRITELN ; WRITELN ;
- WRITELN(' FREQUENCY MAGNITUDE MAGNITUDE DB PHASE DEG ') ;
- WRITELN ;
- FOR I:= 1 TO NSTEP DO
- BEGIN
- W := FREQVAL[I]*2.0*PI ;
- CALC(M,PN,MAGN,PHASEN,W) ; {Calculate the numerator respsonse}
- CALC(N,PD,MAGD,PHASED,W) ; {Calculate the denominator response}
- MAGNITUDE := KGAIN* MAGN/MAGD ;
- LOGMAG := (20.0/NATLOG)*LN(MAGNITUDE) ; {Magnitude in DB}
- PHASE :=(PHASEN - PHASED)*180.0/PI ; {Phase in degrees}
- WRITELN(' ',FREQVAL[I]:12,' ',MAGNITUDE:12,' ',LOGMAG:12,
- ' ',PHASE:12);
- END;
-
- {Part of program to print to printer on request}
- WRITELN;
- WRITE(' Would you like the output directed to the printer (Y or N) : ') ;
- READLN(ANS) ;
- IF ANS ='Y' THEN
- BEGIN
- WRITELN(LST) ; WRITELN(LST) ;
- WRITELN(LST,' FREQUENCY MAGNITUDE MAGNITUDE DB PHASE DEG ');
- WRITELN(LST) ;
- FOR I:= 1 TO NSTEP DO
- BEGIN
- W := FREQVAL[I]*2.0*PI ;
- CALC(M,PN,MAGN,PHASEN,W) ; {Calculate the numerator respsonse}
- CALC(N,PD,MAGD,PHASED,W) ; {Calculate the denominator response}
- MAGNITUDE := KGAIN* MAGN/MAGD ;
- LOGMAG := (20.0/NATLOG)*LN(MAGNITUDE) ; {Magnitude in DB}
- PHASE :=(PHASEN - PHASED)*180.0/PI ; {Phase in degrees}
- WRITELN(LST,FREQVAL[I]:12,' ',MAGNITUDE:12,' ',LOGMAG:12,
- ' ',PHASE:12);
- END; {FOR}
- END ; {END PRINTER IF}
- END. {BODE}