Академический Документы
Профессиональный Документы
Культура Документы
FACULTAD DE INGENIERA
MAESTRA EN MECATRNICA
Materia:
Control Avanzado
Prctica 2
Obtencin de la respuesta en frecuencia de una funcin discreta utilizando el
lenguaje C
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)
F ( z )|
z e jwTs
(3)
F ( z)
(4)
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)
F ( z )|
F ( z )|
z e jwTs
z e jwTs
e
| B ( jTs ) | e jS B ( jTs ) | B( jTs ) |
(6)
(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.
F ( z)
0.5143 z
z 1.7826 z 0.8187
2
(8)
Frecuencia (rad)
29.3
580
1570
MATLAB (dB)
23.2
5.28
-10.8
Obtenido (dB)
23.16695
5.294331
-10.834454
MATLAB ()
-8.55
-159
-174
Obtenido ()
-8.540346
-159.18343
-174.18799
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
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;
}