Вы находитесь на странице: 1из 10

UNIVERSIDAD AUTNOMA DE QUERTARO

FACULTAD DE INGENIERA

MAESTRA EN MECATRNICA

Nombre del alumno:


Carlos Andrs Prez Ramrez

Materia:
Control Avanzado

Prctica 2
Obtencin de la respuesta en frecuencia de una funcin discreta utilizando el
lenguaje C

Nombre del Catedrtico


Dr. Luis Morales Velzquez

San Juan del Rio, Quertaro. 4 de septiembre de 2013

Introduccin
La respuesta en frecuencia de una funcin en tiempo discreto permite
conocer tanto los cambios en la amplitud as como en la fase que sufrir una
seal al ser aplicada a dicha funcin. El conocimiento de estos parmetros es
necesario para poder realizar una correcta implementacin de la funcin en
una plataforma en hardware.
Adems, la evaluacin de los parmetros antes mencionados permite
saber si la funcin en cuestin tiene un comportamiento similar al de algn tipo
de filtro selectivo en frecuencia.

Objetivo
Realizar un programa en el lenguaje C para obtener la respuesta en
frecuencia de una funcin arbitraria discreta.

Metodologa
Supngase una funcin discreta (F(z)) formada por el cociente de dos
funciones en tiempo discreto, esto es:

F ( z)

A( z )
B( z )

(1)

donde A(z) y B(z) son polinomios de grado n. De esta manera la ecuacin (1) se
puede reescribir como

F (z)

an z n an1 z n 1 K a1 z1 a0
bm z m bm 1 z m 1 K b1 z1 b0

(2)

Para realizar la evaluacin de la respuesta en frecuencia de la funcin


F(z) es necesario evaluar sta usando una exponencial compleja, lo que da
como resultado

F ( z )|

z e jwTs

an (e jTs ) n an 1 (e jTs ) n 1 K a1 (e jTs )1 a0 (e jTs ) 0


bm (e jTs ) m bm 1 (e jTs ) m 1 K b1 (e jTs )1 b0 (e jTs ) 0

(3)

Si se emplea la identidad de Euler, adems de las leyes de los


exponentes, la ecuacin (3) puede expresarse empleado senos y cosenos, es
decir

F ( z)

an [cos( nw) j sin( nw)] K a1[cos( w) j sin( w)] a0 [cos(0) j sin(0)]


bm [cos(mw) j sin(mw)] K b1[cos( w) j sin( w)] b0 [cos(0) j sin(0)]

(4)

Como se aprecia en la ecuacin (4), las partes real e imaginaria pueden


ser sumadas para obtener el nmero complejo resultante tanto para el
numerador como para el denominador, obtenindose

F ( z)

i 0
m

i 0
m

ai cos(i ) j ai sin(i )
b cos(k ) j b sin(k )
k 0

k 0

(5)

Transformando tanto el numerador como el denominador a su forma


polar, el clculo de la magnitud y la fase, es decir, la respuesta en frecuencia,
se reduce a una divisin y una resta. Matemticamente es

F ( z )|
F ( z )|

z e jwTs

z e jwTs

| A( jTs ) | e jS A( jTs ) | A( jTs ) | j ( S A( jTs ) S B ( jTs ))

e
| B ( jTs ) | e jS B ( jTs ) | B( jTs ) |

| F ( jTs ) | e j ( S A( jTs )S B ( jTs ))

(6)

Para expresar la ganancia en dB, se calcula el logaritmo base 10 del


resultado del cociente y se multiplica por 20.

mag (dB ) 20 log | F ( j ) |

(7)

Desarrollo
La implementacin de las ecuaciones 5, 6 y 7 se realiza de la siguiente
manera. Es necesario generar una estructura que contenga un puntero del tipo
flotante para almacenar los coeficientes as como el orden del polinomio. La
estructura propuesta es
typedef struct Poly_Tag
{
float *coeff;
int grado;
}Poly
Para almacenar la fase y la magnitud del nmero complejo se propone
una estructura que contenga un par de variables flotantes que contengan a
stas. sta es
typedef struct cmpx_Tag

{
double Mag,Ph;
}cmpx;
Una vez propuestas las estructuras, es necesario proponer las funciones
que interactuarn con stas. Para inicializar la estructura que contiene al
polinomio se usa la funcin createPoly, cuya sintaxis es
void createPoly(Poly *a);
La funcin recibe un puntero a la estructura poly, para acceder a los
miembros de sta. Se pregunta por el orden del polinomio; con este valor se
reserva memoria para n+1 coeficientes. Una vez que se reserva la memoria, se
procede a solicitar al usuario los valores de los coeficientes, empezando desde
el menos significativo (el trmino independiente). Esto se realiza con la funcin
fillPoly, cuya sintaxis es
void fillPoly(Poly *a);
Posteriormente, se calcula la respuesta en frecuencia del polinomio
empleando la funcin respFrec. La sintaxis de esta funcin es:
void respFrec(Poly *a,cmpx *b,float frec,float fs);
En esta funcin se realiza la implementacin de la ecuacin 5 y se
resume como sigue: se emplea un ciclo iterativo que inicia desde 0 hasta el
orden del polinomio y se calcula tanto el seno y el coseno de la frecuencia
normalizada (multiplicada por el periodo de muestreo). Una vez finalizado el
ciclo, se calcula la magnitud del nmero y la fase empleando la funcin atan2
(toma en cuenta la ubicacin en los cuadrantes) y almacena estos parmetros
la estructura b. Todas las estructuras se pasan a la funcin usando punteros.
La implementacin de la ecuacin 6 se hace con la funcin respFrecFun,
cuya sintaxis es
void respFrecFun(cmpx *a,cmpx *b,cmpx *c);
y consiste , para el clculo de la magnitud de la funcin, en la divisin de la
magnitud a (representa al numerador) entre la magnitud de b (representa al
denominador); para la fase, se resta la fase de a menos la de b utilizando una
funcin para el ajuste de fase, adjPhase. Los parmetros se pasan a la funcin
empleando punteros.
Para realizar el ajuste de fase se utiliza la funcin adjPhase(float a, float
b), cuya sintaxis es
float adjPhase(float a, float b);
Esta funcin usa los valores calculados dentro de respFrecFun y calcula el
ngulo segn el signo de las partes real e imaginaria; se utilizan variables
flotantes como entrada y salida.

Para imprimir el resultado se emplea la funcin printCpmx, cuya sintaxis


es
void printCmpx(cmpx *a);
y consiste en el uso de la funcin printf para imprimir en pantalla los
parmetros del nmero complejo a. Si se desea conocer la magnitud en dB, se
emplea la funcin printCmpxdB, cuya sintaxis es la misma que la anterior; el
funcionamiento de sta vara de la previa dado que implementa la ecuacin 7,
empleando la funcin logaritmo base 10.
Resultados
Para realizar la comprobacin de la funcin, se utiliz el polinomio
definido en la ecuacin (8)

F ( z)

0.5143 z
z 1.7826 z 0.8187
2

(8)

Con este polinomio, se procedi a graficar, con la ayuda de la funcin


bode de MATLAB, la grfica de la respuesta en frecuencia de la funcin
mostrada en la ecuacin 8, que se ilustra en la figura 1.
Cabe aclarar que el periodo de muestreo utilizado fue de 1 kHz. sta se
expresa en Hz. La frecuencia de evaluacin es expresada en radianes.

Figura 1. Respuesta en frecuencia para la funcin propuesta.

Una vez definido el periodo de muestreo as como la obtencin de los


valores de referencia, se procedi a evaluar las funciones propuestas empleado
3 valores de frecuencia, expresados en radianes. La salida de cada evaluacin
est expresada en dB para realizar una correcta comparacin. La tabla 1
resume los resultados obtenidos

Frecuencia (rad)
29.3
580
1570

MATLAB (dB)
23.2
5.28
-10.8

Obtenido (dB)
23.16695
5.294331
-10.834454

Tabla 1. Magnitud obtenida

En la tabla 2 se muestra la fase obtenida para cada frecuencia con el


programa propuesto as como las obtenidas con MATLAB
Frecuencia (rad)
29.3
580
1570

MATLAB ()
-8.55
-159
-174

Obtenido ()
-8.540346
-159.18343
-174.18799

Tabla 2. Fase obtenida

Como se aprecia, en el caso de la magnitud se tiene que los valores


obtenidos con el cdigo propuesto corresponden uno con otro. La pequea
diferencia se debe al nmero de decimales que toma cada programa para
realizar sus operaciones. En el caso de la fase, como ya se mencion, el uso del
compensador de fase permite reportar correctamente sta, pues los rangos de
operacin de atan de pi/2 a pi/2 y para atan2 de pi a pi, lo que es claramente
inapropiado. Los valores obtenidos en ambas plataformas coinciden el uno con
el otro. La figura 1 muestra el cdigo en ejecucin.

Figura 1. Programa en operacin

Conclusin
Se propuso un programa, desarrollado en el lenguaje C, capaz de
calcular la respuesta en frecuencia de una funcin discreta. El programa
consiste en la solicitud al usuario de la frecuencia de muestreo, la frecuencia a
evaluar as como los rdenes de los polinomios del numerador y denominador.
Con estos valores se procede a reservar dinmicamente la memoria para
almacenar los coeficientes. Tomando ventaja de la identidad de Euler, adems
de la forma polar de un nmero complejo, se aproxima la respuesta de la
funcin como una suma de senos y cosenos. El poder reservar dinmicamente
la memoria da al algoritmo propuesto la flexibilidad de poder trabajar con
rdenes diferentes tanto para el denominador como el numerador. Los

resultados obtenidos muestran que el algoritmo propuesto realiza de manera


satisfactoria la operacin requerida. Como trabajo a futuro se plantea la
codificacin del algoritmo propuesto en el lenguaje C++, ya que se podrn
crear operadores nicos sin la necesidad de generar funciones para cada
operacin requerida.

Anexos
Anexo 1. Cdigo utilizado para la elaboracin de la prctica
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define pi 3.141592653589793
typedef struct Poly_Tag
{
float *coeff;
int grado;
}Poly;
typedef struct cmpx_Tag
{
double Mag,Ph;
}cmpx;
void createPoly(Poly *a);
void fillPoly(Poly *a);
void printCmpx(cmpx *a);
void printCmpxdB(cmpx *a);
void respFrec(Poly *a,cmpx *b,float frec,float fs);
void respFrecFun(cmpx *a,cmpx *b,cmpx *c);
float adjPhase(float a, float b);
int main(void)
{

float fs=0,frec=0;
Poly Num,Den;
cmpx RF_Num,RF_Den,RF;
printf("Frecuencia de meustreo:");
scanf("%f",&fs);
printf("Frecuencia a evaluar:");
scanf("%f",&frec);
printf("\nNumerador\n");
createPoly(&Num);
fillPoly(&Num);
printf("\nDenominador\n");
createPoly(&Den);
fillPoly(&Den);
respFrec(&Num,&RF_Num,frec,1/fs);
respFrec(&Den,&RF_Den,frec,1/fs);
respFrecFun(&RF_Num,&RF_Den,&RF);
printCmpxdB(&RF);
free(Num.coeff);
free(Den.coeff);
fflush(stdin);
getchar();
return 0;
}
void createPoly(Poly *a)
{
int f;
printf("Orden del polinomio:");
scanf("%d",&f);
a->grado=f;
a->coeff=(float*)malloc((a->grado+1)*sizeof(float));
if(a->coeff==NULL)
{
printf("Error, no se pudo reservar memoria");
fflush(stdin);
getchar();
exit(1);
}
}
void fillPoly(Poly *a)
{
int i;
float tmp;
fflush(stdin);
for(i=0;i<=a->grado;i++)
{
printf("\n Coeficiente [%i]: ",i);
scanf("%f",&tmp);
a->coeff[i]=tmp;

}
printf("\n");
}
void printCmpx(cmpx *a)
{
printf("Magnitud:%f\nFase(rad):%f\nFase(deg):%f\n\n",a->Mag,a->Ph,((a>Ph)*180)/pi);
}
void printCmpxdB(cmpx *a)
{
printf("Magnitud:%f\nFase:%f\nFase(deg):%f\n\n",20*log10(a->Mag),a>Ph,((a->Ph)*180)/pi);
}
void respFrec(Poly *a,cmpx *b,float frec,float fs)
{
int i=0;
float tmp_real=0,tmp_img=0,tmp_frec=0;
for(i=0;i<=a->grado;i++)
{
tmp_frec=frec*i*fs;
tmp_real=tmp_real+a->coeff[i]*cos(tmp_frec);
tmp_img=tmp_img+a->coeff[i]*sin(tmp_frec);
//printf("\n %f %f %f",tmp_frec,tmp_real,tmp_img);
}
b->Mag=sqrt((tmp_real*tmp_real)+(tmp_img*tmp_img));
b->Ph=adjPhase(tmp_real, tmp_img);
}
void respFrecFun(cmpx *a,cmpx *b,cmpx *c)
{
c->Mag=(a->Mag)/(b->Mag);
c->Ph=(a->Ph)-(b->Ph);
}
float adjPhase(float a, float b)
{
float c;
if(a>0&&b>0)
{
c=atan(b/a);
}
else if(a<0&&b>0)
{
c=pi-atan(b/abs(a));
}
else if(a<0&&b<0)

{
c=pi+atan(b/a);
}
else
{
c=2*pi-atan(abs(b)/a);
}
return c;
}

Вам также может понравиться