MODULACIN Y DEMODULACIN IQ: APLICACIN A DATOS REALES
Fecha de entrega: hasta el 10 de febrero
Modulacin y demodulacin FM usando un modulador IQ Vamos a crear una seal FM a partir de una sencilla seal sinusoidal (con una frecuencia de 5 Hz), siguiendo la filosofa de un modulador IQ. Los datos se muestrearn con una frecuencia fs = 20000 Hz: fs = 20000; % Frecuencia muestreo % Seal a modular t = [0:1/fs:2]; % 2 sec @ fs muestras/segundo x = cos(2*pi*5*t); % 5 Hz baseband signal Lo primero es simular el procesador en banda base donde generamos las seales I y Q, como I = A cos(phi) y Q = A sin(phi). En modulacin FM la amplitud A es constante y la fase se construye como la integral de la seal x(t) multiplicada por una constante. En MATLAB podemos calcular numricamente la integral de la secuencia x[n] con la funcin cumsum() que suma acumulativamente los contenidos de una secuencia: A = 1; % amplitud constante k=0.05; phi = k*cumsum(x); % Integral de seal Las seales I y Q se generan ahora como: I = A*cos(phi); Q = A*sin(phi); % Construccin de las seales I y Q Con esto ya hemos concluido el procesado en banda base. Ahora solo resta combinar las seales I/Q con la portadora (cos/sin) para generar la seal IQ modulada (en este caso usando FM). Usaremos una frecuencia portadora de 2000 Hz: wc = 2*pi*2000; % Frecuencia 2000 Hz portadora IQ = I .* cos(wc*t) - Q .* sin(wc*t); % Seal IQ modulada en frecuencia Podemos escuchar dicha seal de audio usando: sound(IQ,fs); Cmo la describirais? ApeIIidos: Nombre: ApeIIidos: Nombre: Para ver visualmente cmo se altera la frecuencia de la portadora en funcin de la seal, podemos usar la funcin stft2d() que visualiza el espectrograma de una seal: figure; stft2d(IQ,512,fs); Dibujad la figura resultante. Se aprecia la forma de la seal original? Qu parmetro de la portadora varia con el tiempo? Cambiar la variable k por 0.1. Qu cambia en la imagen resultante? Qu influencia tiene la variable k en el ancho de banda de la seal FM? Consideremos ahora el problema de la demodulacin. Lo primero es recuperar las seales I y Q por separado despus de haberlas juntado. Para ello hemos escrito la funcin demodula_IQ que recibe como argumento la seal modulada IQ y devuelve las seales I y Q por separado: function [I,Q] = demodula_IQ(IQ,f_local,ph_local,fs) % Parametros de entrada: % IQ : seal modulada % f_local: frecuencia del oscilador local (en Hz) % ph_local: fase del oscilador local % fs: frecuencia de muestreo (Hz) % Parametros salida: % I,Q: seales I y Q demoduladas. Apliquemos esta funcin a la seal IQ obtenida anteriormente. En principio usaremos una frecuencia local de 2000 Hz y una fase de 0, que coinciden exactamente con las usadas al modular: [I_fm Q_fm]=demodula_IQ(IQ,2000,0.0,fs); Sabemos que la informacin de la seal est contenida en la fase (de hecho la derivada de la fase) de los nmeros complejos cuya parte real es I y parte imaginaria Q. Construyamos dichos nmeros: R = I_fm + i*Q_fm; En principio parecera que para recuperar la seal bastara calcular la fase de R (funcin angle en MATLAB) y diferenciarla: ph = angle(R); dph = ph(2:end)-ph(1:end-1); plot(dph) Recuperamos la seal original? Se os ocurre qu est pasando? El problema es que la fase devuelta por angle() est siempre entre -pi y pi. Imaginad que en la muestra n la fase esta creciendo y vale justo pi. Al instante siguiente n+1 la fase vale (pi + dx), pero la funcin angle() nos devuelve -pi+dx (volviendo a meterla en el intervalo -pi,pi), lo que es correcto trigonomtricamente hablando, pero estropea mi derivada. Nosotros esperbamos hallar la diferencia (pi+dx)-pi = dx y en lugar de eso calculamos la derivada como (-pi+dx)-pi = -2*pi + dx. Es posible corregir este efecto en nuestra seal dph. Cada vez que veamos un gran salto hacia abajo (caso anterior), sumamos 2pi (y recuperamos el valor deseado dx). Si el salto es hacia arriba, restamos 2pi. Esto es lo que se denomina phase unwrapping. Sin embargo hay otro mtodo ms automtico de arreglar las cosas. Consideremos R(n) = A(n) exp[i phi_n] y el valor anterior R(n-1) = A(n-1) exp[i phi(n-1)]. Multipliquemos R(n) por el conjugado de R(n-1): R(n) R(n-1)* = A(n) exp(i phi(n)) A(n-1) exp(-i phi(n-1)) = A(n) A(n-1) exp[i {phi(n)-phi(n-1)} ] Luego la fase de dicho nmero complejo es justo la diferencia de fases buscada {phi(n)-phi(n-1)} y adems no muestra los saltos de +/- 2pi de antes. Sabiendo que la funcin para calcular el conjugado es conj( ) en MATLAB, escribir el cdigo necesario para extraer la seal de esta forma (una lnea) y pintar la seal resultante. Se recupera ahora a la seal original? Una de las ventajas de una seal modulada FM es que es muy resistente a cambios en la frecuencia o fase del oscilador local. Repetir la demodulacin usando una frecuencia correcta de de 2000 Hz pero con una fase local de pi/2. Despus usar una frecuencia de 2200 Hz y la fase correcta (0.0): [I Q]=demodula_IQ(IQ,2000,pi/2,fs); [I Q]=demodula_IQ(IQ,2200,0.0,fs); Qu efecto tiene sobre la seal demodulada un desajuste de fase? Y de la frecuencia? OPCIONAL: en una hoja aparte, demostrar analticamente los efectos anteriores de un desajuste en frecuencia o fase del demodulador FM sobre la seal recuperada: Demodulacin de una seal BPSK: Examinaremos ahora la demodulacin de una seal binaria codificada con modulacin de fase binaria (bit 0 = fase 0, bit 1 = fase pi). En el archivo IQ_bpsk tenemos una seal binaria (16 bits, alternando 0 y 1) codificada sobre una portadora de 2000 Hz, usando la misma frecuencia de muestro (fs=20000 Hz) que antes. Cargar la seal y usar demodula_IQ para remodularla. En un principio usaremos una frecuencia y fase en perfecto ajuste con las usadas al modular: load IQ_bpsk; [I Q]=demodula_IQ(IQ,2000,0.0,fs); Sabemos que idealmente en una modulacin de este tipo los bits aparecen como 1's (bit = 0 -> fase = 0 -> cos(0) = 1) y -1's (bit = 1 -> fase = pi -> cos(pi) = -1) en el canal I, mientras que el canal Q debe mantenerse a cero. Comprobmoslo: figure; plot(I); hold on; plot(Q,'r'); hold off Se distinguen claramente los bits? En que rama? Otra forma muy ilustrativa de visualizar los resultados es dibujar Q frente a I como la parte real (X) e imaginaria (Y) de un nmero complejo: plot(I,Q,'b.','MarkerSize',1); set(gca,'Xlim',[-1 1],'Ylim',[-1 1]); Como se ve las muestras se concentran en la fase 0 y pi del plano complejo. Dibujar la figura resultante. A que se deben los puntos entre las zonas de acumulacin? La figura anterior muestra todas las muestras (I_n,Q_n) durante todo el tiempo, superponindolas en un solo grfico. Es muy instructivo ver como se veran dichas muestras en un osciloscopio segn van llegando. Para verlo usaremos la funcin show_IQ( ) que simula un osciloscopio, pintando sucesivas muestras de (I,Q) y borrando las anteriores: show_IQ(I,Q); Describid lo que veis en la pantalla: Vamos a repetir ahora lo que hicimos antes de utilizar un demodulador desajustado en frecuencia y/o fase. En primer lugar, veremos el efecto de un desajuste en frecuencias de 10 Hz: [I Q]=demodula_IQ(IQ,2010,0.0,fs); Pintad los canales I y Q como antes y adjuntad la imagen resultante: aparecen ahora claramente los bits? Observar ahora los canales (I,Q) con la funcin show_IQ(I,Q). Describid la evolucin de la seal en el plano (I,Q): Finalmente repetir con un desajuste en fase del modulador: [I Q]=demodula_IQ(IQ,2000,1.0,fs); Pintad los canales I y Q resultantes. Usad show_IQ() y describir el comportamiento de la seal (I,Q) resultante. Qu podemos concluir de lo crtico que es la correcta sintonizacin en este tipo de modulacin comparada con la modulacin FM anterior? Como curiosidad podis usar show_IQ( ) con las seales I,Q de la seal modulada FM anterior: show_IQ(I_fm,Q_fm); para ver el aspecto de una seal modulada FM en el plano IQ. Recordad que en la modulacin FM la informacin va en la derivada de la fase, es decir, en la velocidad de giro del vector IQ en el plano complejo. Demodulacin de estacin real FM: En el archivo IQdata_FM.mat hemos guardado los datos I y Q obtenidos a partir de una software radio (USRP) sintonizado a una emisora de radio en la banda de FM (aproximadamente 100 MHz). El ancho de banda de una emisin FM es de 100 KHz, y la frecuencia de muestreo usada es de 247.000 muestras/segundo, por encima del lmite e Nyquist. En total tenemos grabadas unas 2,400,000 muestras, casi 10 segundos de seal. load IQdata_FM Como antes, a partir de los datos I y Q construimos un array complejo cuya parte real sea I y la imaginaria Q: r = I+i*Q; Recordando la operacin realizada antes, para demodular una seal FM, podemos hallar la seal enviada: x = angle( r(2:end) .* conj(r(1:end-1)) ); % Phase difference x = 0.9*x/max(abs(x)); % Escalamos para "subir" volumen. Veamos si hemos recuperado el audio: sound(x,fs) Usando ver_tf podemos visualizar el aspecto del espectro de la seal demodulada: ver_tf(x,fs,'r','semi'); Representar el grfico que veis indicando los distintos componentes presentes en la seal x(t): Segn se aprecia en la TF anterior, la seal consta de varios otros componentes adems del audio en la banda base. Sin embargo, no hemos apreciado nada raro al escucharla. Por qu creis que sucede esto? Decodificacin del stream de datos RDS La seal demodulada anterior, adems del audio, contiene un stream de bits RDS (Radio Data System) en una sub-portadora a 57000 Hz, modulados con el sistema BiPhase Shift Keying Modulation, en el que cada bit enviado se codifica con uno de los siguientes smbolos: La seal resultante de la superposicin de los bits a enviar se usa para modular en amplitud la portadora de 57 KHz. Los bits enviados se mandan con una velocidad de 57000/48 = 1187.5 Hz, lo que corresponde a un periodo T = 842 milisegundos aproximadamente. A la velocidad de muestreo usada en esta prctica (247000 muestras/segundo) un bit corresponde exactamente a 247000/(57000/48) = 208 muestras. Como se ve, para decidir si un bit es un 0 o un 1 deberemos muestrear la seal en +-T/4 (correspondientes a 208/4 = 52 muestras) respecto al centro del bit y restar los valores obtenidos. Si dicha resta es positiva tendremos un bit 0, si es negativa un bit 1. Suponiendo que los bits de nuestro mensaje estn contenidos en el string data(), lo que en realidad mandamos es el resultado de una codificacin diferencial de dicho stream, donde el bit k mandado es un XOR entre el bit (k-1) previamente enviado y el bit k del mensaje original: sent(1) = data(1); for k=1:L, sent(k) = sent(k-1) XOR data(k); end La decodificacin del mensaje se lleva a cabo haciendo un XOR entre bits sucesivos del mensaje enviado: rec(k) = sent(k) XOR sent(k-1) La consecuencia de esta codificacin es que es irrelevante que durante el proceso de demodulacin y extraccin de los bits intercambiemos 0's por 1's. En ambos casos, tras pasar por el decodificador obtendremos el mismo mensaje. Comprobad en MATLAB esta propiedad. A partir de la cadena de bits sent = [0 1 0 1 1 1 0 0 1 0 1 0 1 1 0] , decodificar los bits del mensaje original (la funcin de MATLAB para XOR es bitxor()). Repetir usando como entrada los bits invertidos (1-sent). Escribir el cdigo usado (una sentencia) Listar ambas salidas. Son iguales? Cdigo: rec1 = rec2 = Esta ltima propiedad es importante porque como sabemos un filtro de tipo Costas puede "engancharse" a la seal en fase (dif_fase=0) o en contrafase (dif_fase=pi). En el segundo caso el signo de la seal recuperada se invierte, lo que supondra la inversin de los bits. El esquema diferencial anterior asegura que dicha eventualidad carezca de importancia. Lo primero que vamos a hacer es un filtrado pasobanda de la seal demodulada FM, centrado en 57 KHz y con un ancho de banda de +/- 3 KHz, para asegurarnos de que slo trabajamos con la seal RDS: [B A]=fir1(192,(57000+3000*[-1 1])/(fs/2)); % Filtro paso_banda 54 a 60 KHz rds = filter(B,A,x); % Filtramos x[n] Para no complicarnos la vida implementando un Costas que se ajuste a la frecuencia y fase de la portadora vamos a asumir que la frecuencia nominal de 57000 Hz es correcta y que la fase es 0. La recuperacin de los bits en la banda I ser: fc=57000.0; % Frecuencia del observador local N=length(rds); t=[0:N-1]/fs; % Base de tiempos I= rds.* cos(2*pi*fc*t); % Rama I del demodulador Finalmente, un filtrado pasobajo elimina la doble frecuencia (57000 x 2 = 114 KHz) introducida por la multiplicacin y slo deja pasar los bits en banda base: [b a]=fir1(192,2400/(fs/2)); % Filtro pasobajo @ 2400 Hz I = filter(b,a,I); Para observar el aspecto de los bits haremos lo mismo que en la prctica anterior: dibujar su eye-diagram. Para ello, sabiendo que el ancho de un bit es de 208 muestras y que nuestra seal contiene 11500 bits (un total de 208 x 11500 = 2392000 muestras), convertiremos nuestra array en una matriz de 208 filas y 11500 columnas usando reshape, para luego pintar todas esas columnas (bits) usando plot: Nbits=11500; BIT_SIZE=208; r=reshape(I,BIT_SIZE,Nbits); plot(r) Adjuntad la figura resultante. Creeis que se podrn decodificar los bits o tendremos altas probabilidades de error? La frecuencia usada de 57000 Hz es claramente no exacta. Tanteando he encontrado que una frecuencia de 56999.5 Hz es ms parecida a la que realmente nos est llegando. Repetir los pasos anteriores usando la frecuencia anterior y adjuntar el eye- diagram resultante. Podremos ahora decodificar los bits sin errores? Notad que an parece haber un corrimiento de los bits (el cuello parece que se va desplazando), lo que indica que la frecuencia usada no es totalmente correcta (o que la frecuencia del emisor o del receptor oscilaba ligeramente con el tiempo) Esto resalta la importancia de usar filtros como el Costas o similares que sean capaces de adaptarse a la frecuencia de la portadora. OPCIONAL: decodificacin del mensaje RDS Finalmente vamos a decodificar el mensaje contenido en esos 11500 bits. Lo primero es determinar el centro del bit en el eye diagram anterior A partir del eye-diagram determinar en que posicin cae el centro de cada bit (aproximadamente). Cul es el resultado? Justificar vuestra eleccin. Una vez decidido el centro del bit y recordando la figura anterior sobre la forma de los bits, sabemos que el paso siguiente es muestrear a +/- T/4 de dicho centro (T/4 equivalen a 208/4 = 52 muestras a la derecha e izquierda). Luego restaremos dichos valores y declarararemos un 1 si es positivo y 0 si es negativo (o viceversa, ya que sabemos que la inversin de bits no importa). Notad que al igual que hicimos en la prctica anterior, con la nueva disposicin de los datos muestraer en un instante de tiempo es simplemente extraer una columna de la matriz r. Escribir un par de lneas de cdigo que hagan las operaciones descritas anteriormente: Los datos as obtenidos son los enviados, pero no los del mensaje original. Para llegar al mensaje original debemos deshacer la codificacin diferencial de la forma explicada antes. Cul sera el cdigo a usar (1 lnea)? Por ltimo, para comprobar que todo ha salido correctamente mandaremos dichos datos a un parser RDS para ver si son decodificados correctamente. He escrito un sencillo programa rds_decoder que recibe un array de 1's y 0's como el que habis generado y descifra los principales mensajes. Aplicarlo. Os funciona? Qu tipo de mensajes recibimos? De qu emisora y frecuencia son los datos con los que hemos estado trabajando? Como ejercicio adicional podis intentar repetir el proceso con los datos obtenidos de la demodulacin con la frecuencia incorrecta de 57000 Hz. Se decodifican los datos? Hay errores? Las pruebas anteriores demuestran lo crtico que puede ser un desajuste de slo una fraccin de hertzio en un demodulador de frecuencia no ajustable. Para apreciar lo til que resulta un filtro de Costas (u otros filtros adaptativos similares) en la demodulacin de la seal RDS podis usar el programa rds_costas: Veris que los bits no se mueven, incluso aunque empecemos con una frecuencia local apartada algunos hertzios de la de la seal. Podis variar dicha frecuencia local para ver cual sera la zona de enganche del filtro de Costas y el tiempo que tarda en engancharse. Yo he probado hasta con una desviacin de unos 100 Hz (w_local = 57100) y el filtro termina enganchndose y pudiendo decodificar los bits. Podis tambin probar a usar slo un filtro de 1er orden (ajuste de frecuencia pero no de fase) o a desactivar el filtro de Costas para ver como poco a poco (dependiendo del error en frecuencia) se va desajustando la fase de la seal RDS y el oscilador local. El la figura adjunta podis ver un aspecto de la aplicacin, mostrando informacin sobre el desajuste en frecuencias, trmino de error del Costas, canales I y Q, mensaje decodificado, etc.