You are on page 1of 15

Pontificia Universidad Catlica de Chile Departamento de Ingeniera Elctrica

IEE 2682 LABORATORIO DE CONTROL AUTOMATICO APUNTES EXPERIENCIA ADQUISICION Y DESPLIEGUE DE DATOS

1.

RESUMEN

Estos apuntes detallan los aspectos ms importantes de la implementacin de un conjunto de rutinas de software desarrolladas para el manejo de una tarjeta digitalizadora de seales utilizando las herramientas de programacin provistas por Matlab. Las rutinas acceden a las funciones de la tarjeta digitalizadora desde el ambiente de trabajo de Matlab, lo que facilita, entre otras cosas, el despliegue grfico y procesamiento de los datos obtenidos con la ayuda de Matlab.

2. 2.1

CARACTERISTICAS DE LA TARJETA DIGITALIZADORA Parmetros de operacin de la tarjeta digitalizadora

La tarjeta digitalizadora est concebida para la adquisicin de datos y la conversin analgica/digital y digital/analgica de seales. Para ello, cuenta con el siguiente conjunto de entradas y salidas: 8 entradas analgicas 2 entradas/salidas digitales de 8 bits 1 salida analgica Terminales para seales de clock y trigger externos.

El rango de tensin para las seales de entrada es de -10 a 10 volts o de 0 a 20 volts, mientras que para las seales de salida es de -10 a 10 o 0 a 10 volts. El rango de las seales de salida es modificable dentro de estos extremos mediante un par de jumpers accesibles dentro de la tarjeta. Tanto para la conversin A/D como la D/A, la precisin de los conversores internos de la tarjeta es de 12 bits, lo que se traduce a una precisin de salida de 4.8 mV para el rango mximo de [-10,10] volts. 2.2 Operacin de la tarjeta digitalizadora

Para acceder a las entradas y salidas de la tarjeta digitalizadora, sta se conecta a un circuito impreso montado de manera de proporcionar acceso a las entradas y salidas con cables estndar de laboratorio, al mismo tiempo que proporciona las tierras adecuadas para las seales. En la figura 1 se muestra un esquema de la disposicin de los terminales en el circuito impreso.

GND CLK GND TRIG

GND DA1 GND DA0

GND DI7 DI6 DI5 DI4 DI3

DI2

DI1 DI0

GND DII7 DII6 DII5 DII4 DII3 DII2 DII1 DII0

SE15 SE14 SE13 SE12 SE11 SE10 SE9 SE8 SE7 SE6 SE5 SE4 SE3 SE2 SE1 SE0

GND

Figura 1: Esquema de terminales de acceso a la tarjeta digitalizadora

2 Los terminales DA0 o DA1 corresponden a las salidas analgicas de la tarjeta. Los terminales DI o DII pueden funcionar como entradas o salidas digitales dependiendo como se configuren ciertos registros del computador. Como los terminales digitales pueden funcionar bidireccionalmente se debe tener mucho cuidado en las conexiones que se realicen para no daar los registros internos en la tarjeta. Los terminales SE0 a SE7 son las entradas analgicas, el resto (SE8 a SE15) no cumplen ninguna funcione en este modelo de tarjeta de adquisicin de datos. CLK y TRIG son los terminales de clock y trigger externos, respectivamente. Para modificar el rango de la tensin de salida se deben modificar las posiciones de los jumpers designados JP1 y JP4. A continuacin se detallan los rangos obtenidos para distintas posiciones de los jumpers; las posiciones que se sealan son relativas al observar la tarjeta con los terminales de conexin al computador puestos hacia el observador. Por ejemplo, JP1: R se refiere al jumper 1 con el pin central cortocircuitado con el pin de la derecha.

JP1 : L Rango : [0,10] volts JP4 : L

JP1 : R Rango : [-10,10] volts JP4 : R

La comunicacin entre el programa que maneja la tarjeta y sta se realiza al leer y escribir valores en un conjunto de direcciones de puertas que estn definidas para este propsito. Los procedimientos para escribir y leer seales de la tarjeta se implementan de una manera estndar, la que se detalla a continuacin. La implementacin que se muestra est programada en Pascal, la que puede traducirse sin mayor problema a cualquier lenguaje de programacin de uso comn, como Basic, C o Fortran. Escritura en la tarjeta Para hacer ms legible el cdigo del programa, conviene definir como constantes al inicio del programa las distintas direcciones de puertas a accesar, tanto para las instrucciones de lectura como de escritura en la tarjeta. De esta manera, los valores hexadecimales de direcciones de puertas quedan definidos de la siguiente manera: const dummy_code ad_ready ad_sel ad_sts da_sel ext_event da_dat_l ad_dat_l da_dat_h ad_dat_h da_start ad_start dio dio_in dio_out = $0; = $fe; = $2f0; = $2f0; = $2f1; = $2f1; = $2f2; = $2f2; = $2f3; = $2f3; = $2f4; = $2f4; = $2f5; = $2f6; = $2f7;

Para iniciar el procedimiento de escritura en la tarjeta, se deben seleccionar los canales de salida y de entrada para esta operacin, mediante las siguientes instrucciones: Port[ ad_sel ] := byte(in_canal); Port[ da_sel ] := byte(out_canal); Define el canal de entrada Define el canal de salida

El canal de entrada se define en la variable in_canal, la cual puede tomar valores entre 0 y 7, seleccionando un canal entre SE0 y SE7, respectivamente. Por otra parte, la variable out_canal determina el canal de salida tomando valores entre 0 y 3 ; cada uno de estos valores implica alguna de estas situaciones: out_canal = 0 outchanel = 1, 2, 3 : Ningn canal habilitado : Canal 0 (DA0) y Canal 1 (DA1) habilitados

A continuacin se procede a realizar la escritura del valor de tensin deseado en la tarjeta. Dado que el conversor D/A de la tarjeta tiene una resolucin de 12 bits, los valores de entrada al conversor son nmeros binarios en el

3 rango [0,4095], los cuales son transformados al valor de tensin deseado de acuerdo al rango de salida definido por los jumpers. La escala de conversin D/A es lineal inversa, es decir, el valor de entrada binario 4095 produce que la tensin de salida sea la menor del rango. Por ejemplo, si el rango de tensin de salida se defini como [0,10] volts, la conversin binaria-tensin para la entrada es la siguiente: salida = 0 salida = 4095 voltaje = 10 volts voltaje = 0 volts

Se supone que en el programa existe una variable denominada salida que contiene el valor de tensin que se quiere generar de la tarjeta. Los valores de esta variable debieran encontrarse en el mismo rango que se ha definido para la tensin de salida. Luego, deben incluirse una serie de instrucciones que transformen el valor de la variable salida a un valor dentro del rango [0,4095] para ser puesto en la entrada del conversor D/A. La conversin se logra con las siguientes instrucciones: aux := 4095 * (salida / 10); Out := 4095 - round(aux); Out es el valor que se entrega al conversor D/A. A continuacin el programa debe escribir el valor de salida en la tarjeta. Pasando Out a representacin binaria, el programa debe escribir los 8 bits ms significativos en la direccin de puerta da_dat_h, mientras que los 4 bits restantes son los 4 bits ms significativos del byte que se escribe en la direccin de puerta da_dat_l. Las instrucciones que realizan las anteriores operatorias son las siguientes: Port[da_dat_h]:=trunc(Out/16); Port[da_dat_l]:=16*(Out-trunc(Out/16)*16); Escribe los 8 bits ms significativos Escribe los 4 bits restantes

El registro de 8 bits "da_dat_h" en la direccin de memoria 2f3hex, almacena los 8 bits ms significativos de valor de Out. "da_dat_l" almacena los 4 bits menos sinificativos de Out en los 4 bits ms significativos en la direccin de memoria 2f2hex. Por ltimo, el procedimiento de escritura se concluye siempre con la siguiente serie de instrucciones: Port[da_sel]:=byte(3); Port[da_start]:=dummy_code; dummy_var:=Port[ad_start]; La constante dummy_code se define como cero, mientras que la variable dummy_var solo se utiliza para leer la direccin de puerta ad_start. Lectura de la tarjeta El procedimiento de lectura se inicia de la misma manera que el de escritura, seleccionando los canales de entrada y salida: Port[ ad_sel ] : = byte(in_canal); Port[ da_sel ] : = byte(out_canal). Define el canal de entrada Define el canal de salida

Las especificaciones de la tarjeta indican que a continuacin debe leerse la direccin de puerta ad_start: dummy_var:= Port[ad_start]; A continuacin debe esperarse a que la tarjeta realice la conversin A/D para luego leer el valor binario una vez que la conversin ha sido completada. La literatura que acompaa a la tarjeta especifica que este momento se indica cuando las direcciones de puerta ad_ready y ad_sts entregan un determinado valor. Sin embargo, al medir en laboratorio los valores ledos en estas puertas, estos no experimentan ningn cambio, lo que puede atribuirse a que la tarjeta esta diseada para funcionar en computadores con un clock lento tipo 8086 u 80286. Por lo tanto, se debe usar otro procedimiento para indicar que la conversin A/D ha sido completada. El procedimiento recomendado

4 consiste en ejecutar un loop vaco por un periodo de que idealmente debiera ser el que la tarjeta demora en realizar la conversin. Lo anterior se implementa de la siguiente forma: i := 750; while i>0 do i :=i-1; El valor inicial de 750 es un valor obtenido empricamente y que resulta razonablemente breve para no alargar el tiempo de proceso (depender de la rapidez del computador utilizado). Una alternativa ms sencilla y que genera buenos resultados consiste simplemente en agregar la instruccin: delay(1); Finalmente, corresponde incluir la instruccin que lee los bytes de las puertas ad_dat_h y ad_dat_l y convierte los 12 bits de entrada en un valor de tensin para ser manejado por el programa: entrada := 10*(Port[ad_dat_h]*16 + trunc(port[ad_dat_l]/16))/4095; La variable entrada es el valor de tensin de entrada que lee la tarjeta y se ubica en el rango [0,10] volts definido para la seal de entrada.

3. 3.1.

IMPLEMENTACION DE RUTINAS EN MATLAB Concepto general de la implementacin

La implementacin se realiz considerando una rutina o serie de rutinas que fueran capaces de: Escribir en la salida analgica de la tarjeta digitalizadora una seal de tensin definida por un vector, el cual contiene una serie de valores correspondiente a muestras de esta seal obtenidas a una cierta tasa de muestreo. Esta seal de salida entra a un proceso cualquiera. Leer desde la entrada de la tarjeta una serie de muestras a la misma tasa de muestreo que para la seal de salida, correspondiendo estas muestras a la salida del proceso que se est controlando.

Todas estas operaciones deberan ser implementadas y ejecutadas en el ambiente de Matlab o Simulink, de manera de obtener el mayor provecho de las caractersticas de despliegue grfico y manejo de matrices. Sobre esta concepcin bsica inicial, se postul que la implementacin originada a partir de los requerimientos anteriores es una funcin de Matlab que se utiliza de la siguiente forma: >> salida = nombre_de_funcin (tiempo_de_ muestreo, entrada) Donde: salida: entrada: tiempo_de_muestreo: vector de datos ledos por la tarjeta desde el proceso vector de datos escritos por la tarjeta en la entrada del proceso tasa de muestreo a la que se manejan los valores de entrada y salida en la tarjeta.

A partir de esta rudimentaria abstraccin inicial de la solucin es posible identificar las funcionalidades bsicas que deben estar contenidas en esta funcin: Una funcin bsica de lectura de la entrada de la tarjeta que se invoca para leer una muestra de la seal de entrada cada vez que transcurre el tiempo de muestreo. Una funcin bsica de escritura en la tarjeta que pone una muestra de la seal de entrada al proceso en la salida de la tarjeta cada vez que transcurre el tiempo de muestreo. Una funcin que es capaz de monitorear el paso del tiempo a partir de un reloj, por ejemplo el timer interno del computador, y que ejecuta las dos funciones anteriores cuando se verifica que ha transcurrido el tiempo de muestreo especificado por el usuario.

5 Al implementar cada una de estas funcionalidades en mdulos de software por separado, es relativamente sencillo construir las dos implementaciones que son el resultado final de este trabajo: una funcin para Matlab y un conjunto de bloques para el ambiente grfico de Simulink. Como se explicar posteriormente, cada una de estas implementaciones tiene ventajas y desventajas. 3.2. Construccin de funciones de Matlab programadas en C

A partir de la definicin anterior, las funciones de manejo de la tarjeta deben ser funciones propias del ambiente Matlab, con la particularidad de que pueden manejar escritura y lectura de valores en direcciones de puertas, que son funcionalidades que pueden ser implementadas en lenguajes como Pascal, C o Fortran. Matlab provee un mecanismo para implementar funciones ejecutables cualquier otra funcin de Matlab, pero que son programadas en C o Fortran. Estas funciones se denominan archivos MEX, y se caracterizan con su terminacin .mex. Gracias a esta herramienta, es posible generar funciones que se ejecutan a una velocidad considerablemente mayor que si hubiesen sido programadas con instrucciones propias de Matlab, o acceder a funcionalidades que no incluye Matlab, como es en esta caso leer y escribir en direcciones de puertas. Para generar archivos MEX, Matlab proporciona dos elementos. El primero es el archivo cmex.bat, el cual ejecuta los pasos de compilacin y linking necesarios para generar el archivo MEX a partir del cdigo programado en C, adaptndose automticamente al compilador de C que el usuario tiene instalado. El segundo elemento es el archivo mex.h, que debe ser incluido al comienzo del cdigo en C. El archivo mex.h incluye todas las funciones necesarias para hacer posible la interaccin de las estructuras de datos propias de Matlab y el cdigo compilado. El cdigo en C de un archivo MEX que posee una estructura fija que no vara significativamente para cualquier implementacin. Como mnimo, debe contener dos funciones bsicas: Una funcin que siempre se nombre mexFunction, que traduce las estructuras de datos de entrada de Matlab a un vector de punteros que contiene las direcciones de memoria donde se almacenan estas variables. Por otra parte, se encarga de crear la variable que contendr el valor de salida de la funcin. Por ltimo invoca a una funcin que es la que propiamente ejecuta las operaciones de la funcin. Una funcin que recibe como parmetros los punteros a las variables de entrada y salida, que es invocada por mexFunction. Esta funcin contiene las operaciones para las que se define la funcin.

Para una explicacin ms detallada de como se implementan los archivos MEX, se recomienda consultar la External Interface Guide, que forma parte de la documentacin incluida con la versin 4.0 de Matlab. 3.3. Implementacin de las funciones bsicas de manejo de la tarjeta digitalizadora

A partir de la definicin de funcionalidades bsicas descrita anteriormente, tanto la funcin de Matlab como los bloques de Simulink comparten las mismas funciones bsicas de escritura y lectura de la tarjeta digitalizadora, mientras que cada versin tiene su forma especfica de implementar la funcionalidad de monitoreo temporal. Siendo las piedras angulares de ambas implementaciones, conviene mostrar en detalle la forma en que ambas funciones se encuentran programadas. Funcin de escritura en la tarjeta Esta funcin se encuentra implementada por el archivo MEX escribe.mex. Esta funcin se utiliza en la ventana de comando de Matlab de la siguiente manera: >> escribe(x) Al ejecutar esta instruccin, en la salida analgica de la tarjeta aparece el valor de tensin contenido en la variable x. El cdigo con que se implement esta funcin se muestra a continuacin. En esta implementacin se especific como canal de salida el canal DA0. /* Data Adquisition Card Driver Modular version Card Writing Module */

6 #include <math.h> #include <conio.h> #include "mex.h" /* Input Arguments */ #define Y_IN prhs[0]

/* Card accessing memory directions */ #define #define #define #define #define #define #define #define #define #define #define #define dummy_code 0x0 ad_ready 0xfe ad_sel 0x2f0 ad_sts 0x2f0 da_sel 0x2f1 ext_event 0x2f1 da_dat_l 0x2f2 ad_dat_l 0x2f2 da_dat_h 0x2f3 ad_dat_h 0x2f3 da_start 0x2f4 ad_start 0x2f4

/* Data writing function */ void escribe(double *y) { double aux; double Out; int aux = 4095*(*y/(double)10); Out = 4095-aux; outp(ad_sel,0x1); outp(da_sel,0x1);

dummy_var;

/* Selection of input and output channels */

outp(da_dat_h,(Out/16)); /* Writing the value in the card output */ outp(da_dat_l,(16*(Out-(double)((Out/16)*16)))); outp(da_sel,0x6); outp(da_start,dummy_code); dummy_var=inp(ad_start); } /* Matlab Gateway function */ void mexFunction( int Matrix int Matrix ) { double unsigned int

nlhs, *plhs[], nrhs, *prhs[]

*y; m,n;

/* Assign pointers to the various parameters */ y = mxGetPr(Y_IN); /* Do the actual computations in a subroutine */ escribe(y); return; }

7 Funcin de lectura de la tarjeta Esta funcin se encuentra implementada por el archivo MEX lee.mex y se utiliza en la ventana de comando de Matlab de la siguiente manera: >> x = lee De esta manera, x pasa a contener el valor de tensin que se encuentra presente en la entrada de la tarjeta. El cdigo con que se implement esta funcin se muestra a continuacin. En esta implementacin se especific como canal de entrada el canal SE3. /* Data Adquisition Card Driver Modular Version Card Reading Module 20/12/96 */

#include <math.h> #include <conio.h> #include "mex.h" #define Y_OUT plhs[0]

/* Card accessing memory directions */ #define #define #define #define #define #define #define #define #define #define #define #define dummy_code 0x0 ad_ready 0xfe ad_sel 0x2f0 ad_sts 0x2f0 da_sel 0x2f1 ext_event 0x2f1 da_dat_l 0x2f2 ad_dat_l 0x2f2 da_dat_h 0x2f3 ad_dat_h 0x2f3 da_start 0x2f4 ad_start 0x2f4

/* Data reading function*/ void lee(double *y) { int dummy_var; int i=750; double aux; outp(ad_sel,11); /* Selection of input and output channels */ outp(da_sel,4); dummy_var=inp(ad_start); while (i>0) /* void loop waiting for A/D conversion */ { i--; } aux= 10*(inp(ad_dat_h)*(double)16 + (inp(ad_dat_l)/(double)16))/(double)4095; *y=aux; } /* Matlab Gateway function */ void mexFunction( int

nlhs,

8 Matrix int Matrix ) { double *y; *plhs[], nrhs, *prhs[]

/* Create a matrix for the return argument */ Y_OUT = mxCreateFull(1, 1, REAL); /* Assign pointers to the various parameters */ y = mxGetPr(Y_OUT); /* Do the actual computations in a subroutine */ lee(y); return; } Conociendo las implementaciones de ambas funciones bsicas, es posible describir las implementaciones finales, tanto para Matlab como para Simulink.

4. 4.1.

FUNCIN CONTROLADORA DE LA TARJETA PARA MATLAB Modo de uso de la funcin

La funcin de Matlab dacc es la funcin que se encarga de escribir la seal de entrada al proceso y leer la seal de entrada a la tarjeta con una tasa de muestreo definida por el usuario. La funcin se llama en la ventana de comando de Matlab de la siguiente manera: >> salida = dacc(tiempo_de_muestreo, entrada) Los parmetros de la funcin son: entrada: vector de largo n x 1 que contiene n muestras de la seal que se quiere entregar a la entrada del proceso. Los valores de las muestras deben encontrarse dentro del rango de salida que ha sido definido por medio de los jumpers de la tarjeta. tiempo_de_muestreo: tasa de muestreo en segundos. Por otra parte, la variable salida es un vector de tamao n x 2 que contiene los valores de las muestras obtenidas en la entrada de la tarjeta en la primera columna, mientras que en la segunda columna aparece la base de tiempo de la funcin, donde cada elemento indica el tiempo en que se ley cada muestra. Junto con lo anterior, la funcin dacc entrega un grfico de la seal de entrada al proceso versus la seal de entrada a la tarjeta, ajustndose la escala de tiempo del grfico a los valores de la base de tiempo entregada en la variable salida. 4.2 Estructura de la funcin dacc

La funcin dacc est programada con los elementos de programacin que proporciona Matlab, el cual interpreta lnea a lnea cada una de las instrucciones contenidas en el cdigo. El cdigo de la funcin dacc se encuentra en el archivo dacc.m, que es el archivo que es interpretado por Matlab al invocar la funcin. Al analizar el cdigo de la funcin, se observa que incorpora cada una de las funcionalidades bsicas que se definieron en el anlisis general del problema: Escritura y lectura en la tarjeta: se encuentran implementadas en las funciones escribe y lee, que ya fueron descrita anteriormente.

9 Funcin de monitoreo de tiempo: esta se encuentra implementada en la funcin timing, la cual recibe como parmetros el tiempo de muestreo y el valor del instante de tiempo en que se efectu la ltima operacin de lectura y escritura de la tarjeta. Mediante un loop dentro de dacc, esta funcin est siendo llamada continuamente para verificar si ha transcurrido el tiempo de muestreo. Si es as, devuelve el valor de este nuevo instante de tiempo en que se muestrea y un flag puesto en 1 que habilita la ejecucin de las rutinas de lectura y escritura en la tarjeta. Si no ha transcurrido el tiempo de muestreo, este flag se mantiene en 0.

El tiempo de ejecucin esta determinado por el largo del vector de entrada a la funcin y el tiempo de muestreo. El loop maestro del programa detiene la ejecucin de la funcin cuando se ha escrito a la tarjeta el ltimo valor de entrada. A continuacin se presenta el cdigo de dacc, contenido en dacc.m: % Data Adquisition Card Driver % Matlab Interpreted Version % 03/01/97 % % Usage: salida=dacc(sample_t,entrada) % % Inputs: sample_t = sampling time in seconds for card reading and writing % Minimun sample time = 0.1 sec % entrada = input vector to the process % Data range is [0,10] Volts % % Outputs: salida = output vector from the process % % Be sure that the files: % dacc.m timing.m escribe.mex lee.mex % are in the same directory. function[salida]=dacc(sample_t,entrada) largo=length(entrada); salida=zeros(largo,2); cuenta=1; switch=zeros(2,6); t_old=clock; start=t_old; % Stops when the last value of entrada appears in the card output while cuenta<=largo, switch=timing(t_old,sample_t); if switch(2) == 1 t_old=switch(1,:); escribe(entrada(cuenta)); salida(cuenta,1)=lee; salida(cuenta,2)=t_old(1,5)*60+t_old(1,6); cuenta=cuenta+1; end end demora=etime(clock,start); salida(:,2)=salida(:,2)-(start(1,5)*60+start(1,6)); escribe(0); plot(salida(:,2),[salida(:,1) entrada]); set(gca,'xlim',[0 demora]);

A continuacin se muestra el el cdigo de la funcin timing, el cual est contenido en el archivo timing.m:

10 function[flag]=timing(t_old,sample_t) t_nuevo=clock; aux=etime(t_nuevo,t_old); if aux>=sample_t flag=[t_nuevo;ones(1,6)]; else flag=[t_old;zeros(1,6)]; end Para garantizar la correcta ejecucin de la funcin dacc, debe verificarse que los archivos dacc.m, timing.m, lee.mex y escribe.mex se encuentren dentro del mismo directorio. 5. 5.1 BLOQUES DE CONTROL DE LA TARJETA PARA SIMULINK Modo de uso de los bloques implementados

Para manejar la tarjeta desde el ambiente de Simulink, existen 4 bloques, dos de los cuales corresponden a los de manipulacin de seales analgicas: uno denominado ADC que lee la seal de entrada a la tarjeta y otro denominado DAC que escribe en la tarjeta la seal de entrada al proceso. Ambos bloques se muestran a continuacin en la figura 2.

Seal DAC DAC ADC Tiempo ADC

Figura 2: Implementacin en bloques de Simulink El bloque DAC tiene como entrada la seal que se quiere escribir en la tarjeta. Al hacer doble-click en el bloque, aparece una ventana de dilogo en la cual se especifica el tiempo de muestreo de la seal para escribir las muestras en la tarjeta. El bloque ADC lee la seal de entrada a la tarjeta y tiene dos salidas. La primera, denominada Seal, entrega los valores de las muestras ledas por la tarjeta, pudiendo conectarse a algn bloque de despliegue grfico para mostrar en tiempo real la forma de la seal recibida o a un bloque To Workspace para poder procesar la seal de entrada en la ventana de comando de Matlab. La otra salida, denominada Tiempo, entrega la base de tiempo asociada a la lectura de la seal de la tarjeta. Esta base de tiempo es inicializada a cero cada vez que se inicia la simulacin. Al hacer doble-click en el bloque, aparece una ventana de dilogo en la cual se especifica el tiempo de muestreo de la seal para leer las muestras de la tarjeta. Cuando se usan ambos bloques a la vez en un mismo modelo debe tenerse en cuenta que si en cada bloque se especifica un tiempo de muestreo distinto, ambos bloques funcionarn a la menor tasa de muestreo de entre las dos. En general, esta situacin no debe ser considerada anmala, debido a que en la mayora de los casos se requiere que los procesos de escritura y lectura en la tarjeta se efecten a la misma tasa de muestreo. Los otros dos bloques corresponden a los de lectura y escritura de datos digitales denominados Lector Digital y Escritor Digital, respectivamente. El bloque Lector Digital, lee los valores binarios 0 (0 volts) o 1 (5 volts) presentes en la puerta digital DI o DII, este valor es traducido a un valor entre 0 y 127 disponible en la salida Seal del bloque. El proceso inverso de escritura tambin es posible gracias al bloque Escritor Digital, el cual escribe el valor binario correspondiente al valor decimal entre 0 y 127 a la entrada del bloque en los 7 bits menos significativos de la puerta DI o DII. En el laboratorio no es necesario utilizar el bloque de lectura digital, pero si el bloque de escritura digital para activar el triac del calefactor. Por ejemplo, si a la entrada del bloque se escribe un 9 se tendr un 000 1001 en la puerta digital. Sera muy perjudicial escribir un 9 en la puerta digital de la tarjeta cuando externamente se est recibiendo un 7, por

11 ejemplo, pues se estara recibiendo un 000 0111, lo cual causara un cortocircuito en los bits 1 y 2 y la destruccin del registro de la puerta digital. 5.2 Estructura de los bloques DAC y ADC

En el caso de los bloques de Simulink, las funciones bsicas de escritura, lectura y monitoreo temporal se implementan de manera radicalmente distinta a la implementacin de la funcin dacc. La estructura de acuerdo a la que son construidos los bloques de Simulink se denomina S-Function, mediante la cual cada bloque es un objeto que responde a un set definido de mensajes para actualizar valores, leer entradas, desplegar salidas, etc. Simulink provee un bloque especial, denominado S-Function, mediante el cual el usuario puede programar el cdigo correspondiente a un bloque de funcionalidades definidas por el mismo usuario y luego incluir este bloque como parte de las libreras estndar de Simulink. El cdigo utilizado en cada bloque S-Function puede ser un archivo .m de Matlab o un archivo MEX compilado de C o Fortran. Utilizando las potencialidades del bloque S-Function se desarrollaron las estructuras internas de DAC y ADC que manejan la escritura y lectura de la tarjeta y el monitoreo temporal. Para obtener una referencia ms completa sobre implementar bloques de Simulink definidos por el usuario utilizando S-Functions, se recomienda consultar el Manual de Usuario de Simulink. Ambos bloques incorporan en su estructura interna un bloque S-Function denominado Real-Time Clock, que se encarga de sincronizar el reloj de simulacin de Simulink al reloj de tiempo real del timer del computador. El tiempo de muestreo que se especifica para los bloques DAC y ADC es en realidad el perodo para el cual el reloj de Simulink se sincroniza con el tiempo real. Al efectuar esta sincronizacin, se ejecutan las rutinas de lectura y escritura de la tarjeta en ambos bloques. Las instrucciones de este bloque se encuentran en el archivo rtclock.mex. El bloque DAC incluye un bloque S-Function denominado escritor, cuya instrucciones de ejecucin se encuentran en el archivo escritor.m, el cual a su vez invoca a la funcin de escritura contenida en escribe.mex para leer la tarjeta. A continuacin s se muestra la estructura interna de DAC:

Real-time Clock 1 in_1 escritor S-Function

A continuacin se muestra el cdigo contenido en el archivo escritor.m: function[sys,x0]=ed(t,x,u,flag) if flag==3 escribe(x); elseif flag==0 sys=[0 1 0 1 0 0]; x0=0; elseif flag==2 sys=u; else sys=[]; end Por su parte, la estructura del bloque ADC es similar, donde un bloque S-Function denominado lector, que a su vez invoca a la funcin de lectura definida en lee.mex, se encarga leer la el valor de la seal de entrada de la tarjeta. Tambin incluye un bloque Clock para proporcionar la base de tiempo.

12 A continuacin se muestra la estructura interna del bloque ADC:

Real-time Clock lector S-Function 1 out_1 2 out_2

Clock

El cdigo contenido dentro del bloque lector es el siguiente: function[sys,x0]=ed(t,x,u,flag) if flag==3 sys=x; elseif flag==0 sys=[0 1 1 0 0 0]; x0=0; elseif flag==2 sys=lee; else sys=[]; end

5.3

Implementacin de los bloques de escritura y lectura digital

Los bloques de lectura y escritura digital tienen una estructura similar a la utilizada en los bloques ADC y DAC. En este caso se utilizan los registros 2f5hex, 2f6hex y 2f7hex; los dos ltimos corresponden al registro de entrada (lectura) y salida (escritura), respectivamente. El registro 2f5hex define el puerto digital DI o DII que se utilizar para la operacin de I/O. 6. ANLISIS COMPARATIVO ENTRE AMBAS IMPLEMENTACIONES EN MATLAB Y SIMULINK

Al analizar comparativamente las potencialidades y desventajas de ambas implementaciones, es posible concluir que la implementacin en bloques de Simulink es mucho ms poderosa y eficiente, debido a una serie de consideraciones que se hacen a continuacin. Uno de los parmetros operativos ms crticos de ambas implementaciones se refiere a que la tasa de muestreo a la que opera el sistema sea la que efectivamente se especifica al hacer andar la implementacin. Sobre este aspecto, la implementacin en Matlab resulta menos eficiente que los bloques de Simulink ya que al verificar la base de tiempo que devuelve la funcin dacc se advierte que el tiempo entre cada muestra siempre presenta un incremento de un 10% respecto al tiempo especificado. Este error aparece para cada muestra, ya que si este error apareciera en forma aislada en algunas muestras se perdera la utilidad de las muestras ledas de la tarjeta. Por otra parte, el menor tiempo de muestreo que se puede entregar a la funcin para que opere satisfactoriamente es 0.1 segundos. Por otra parte, el manejo de tiempo proporcionado por los bloques de Simulink es muy eficiente, ya que la base de tiempo muestra que no se produce ningn error respecto al tiempo de muestreo especificado. Por otra parte, permite tiempos de muestreo menores, verificndose que los bloques se comportaban bien con tiempos de hasta 0.03 segundos. Sin embargo a medida que el sistema aumenta en complejidad, i.e. aumenta el nmero de bloques, el tiempo mnimo posible de muestreo aumenta a 0.15 segundos e incluso a 0.2 cuando se estn escribiendo y leyendo varios canales de la tarjeta a la vez. Por otra parte, las posibilidades de despliegue grfico en el ambiente Matlab son mucho ms limitadas que las de Simulink, pudindose visualizar las seales slo una vez concluida la ejecucin de la funcin. Por su parte, los bloques grficos de Simulink permiten que las seales de entrada y salida puedan monitorearse en tiempo real.

13 ANEXO: RUTINAS DE LECTURA Y ESCRITURA EN TURBO PASCAL PARA LA TARJETA DACC A continuacin se presentan rutinas para accesar a los puertos analgicos o digitales, de lectura (input) y escritura (output) de la tarjeta. Como se muestra a continuacin, para que estas funciones y procedimientos funcionen se debe incluir el header o include file daccdrv.pas (se encuentra listado al final del anexo) al inicio del programa: PROGRAM CONTROL; {Laboratorio de Control Automtico IEE-2682 -----------------------------------------Interface de Control PID. Por: ------------------------------------------} USES CRT,DOS,GRAPH; {$I daccdrv.pas} CONST PI=3.14159265; TYPE ... VAR ... FUNCTION LEEDATODIGIT:real; VAR in_dig:integer; BEGIN in_dig:=Port[dio_in]; LEEDATODIGIT:=in_dig; END; FUNCTION LEEDATO:real; {Funcin que lee el dato a la entrada de la tarjeta conversora DACC. El dato ledo correspondera a la salida del proceso.} VAR in_adc:integer; dummy_var:byte; BEGIN {empezar(x,y) es la llamada a un procedimiento que inicializa la tarjeta DACC fijando los valores del canal de entrada, salida y el tiempo de muestreo: ---empezar(in_canal[0-15],out_canal[0-3],Ciclos de Muestreo);---} empezar(3,4); dummy_var:=Port[ad_start]; {La siguiente lnea debe ser comentada en computadores con procesador 386 o superiores y debe agregarse un delay para espera la conversin A/D} {while Port[ad_sts] and ad_ready=0 do;} delay(1); in_adc:=Port[ad_dat_h]*16+trunc(Port[ad_dat_l]/16); LEEDATO:=in_adc; END; PROCEDURE ESCRIBEDATO(inproc,tierraV:real); {Saca por el puerto de salida de la tarjeta conversora un dato que corresponde a la entrada al proceso, i.e. la salida del PID. tierraV es un voltaje de referencia, normalmente cero. Esta variable no es imprescindible. inproc es el voltaje que se quiere tener en la salida de la tarjeta. } VAR dummy_var:byte; out_dac:integer;

14 BEGIN out_dac:=4095-round(4095*((tierraV+inproc)/10)); empezar(1,1); Port[da_dat_h]:=trunc(out_dac/16); Port[da_dat_l]:=out_dac-trunc(out_dac/16)*16; Port[da_start]:=dummy_code; dummy_var:=Port[ad_start]; END; PROCEDURE ESCRIBEDIGIT(out_dig:byte); {Escribe en el puerto definido por dio_in el valor binario pasado a travs de out_dig.} BEGIN Port[ dio ]:=byte(2); delay(10); Port[dio_in]:=out_dig; END; Archivo DACCDRV.PAS {==============================================================} { Driver para el manejo de la tarjeta DACC } {==============================================================} const dummy_code = $0; ad_ready = $fe; ad_sel = $2f0; {Registro que selecciona la entrada Anlogica 0-7} ad_sts = $2f0; da_sel = $2f1; {Registro que selecciona la salida Aanalgica} ext_event = $2f1; da_dat_l = $2f2; {Registro Inferior del Puerto Anlogo} ad_dat_l = $2f2; da_dat_h = $2f3; {Registro Superior del Puerto Anlogo} ad_dat_h = $2f3; da_start = $2f4; ad_start = $2f4; dio = $2f5; {Seleccin del puerto DI o DII} dio_in = $2f6; {Puerto de Digital de Lectura} dio_out = $2f7; {Puerto de Digital de Escritura} {--------------------------------------------------------------} procedure empezar( in_canal, out_canal : byte); begin Port[ ad_sel ] := byte(in_canal); Port[ da_sel ] := byte(out_canal); end; {--------------------------------------------------------------} procedure terminar; begin end; {Fin Driver} Nota: 1. Para las experiencias en el laboratorio no se requiere de los puertos digitales DI, DII. El uso de las rutinas de escritura y lectura usando el puerto digital debe hacerse con extremo cuidado ya que son bidireccionales. Su uso incorrecto puede daar la tarjeta. 2. El procedimiento terminar debe contener las instrucciones que resetean la tarjeta (e.g. poner en cero las salidas).

15 Visual C++: Para visual C++ hay que hacer unas pequeas correcciones que se incluyen a continuacin. Guardar como tarjeta.h e incluir al path. /* Card accessing memory directions */ #include<conio.h> #define #define #define #define #define #define #define #define #define #define #define #define dummy_code 0x0 ad_ready 0xfe ad_sel 0x2f0 ad_sts 0x2f0 da_sel 0x2f1 ext_event 0x2f1 da_dat_l 0x2f2 ad_dat_l 0x2f2 da_dat_h 0x2f3 ad_dat_h 0x2f3 da_start 0x2f4 ad_start 0x2f4

void lee(double *y) { int dummy_var; int i=5750; double aux; _outp(ad_sel,11); /* Selection of input and output channels */ _outp(da_sel,4); dummy_var=_inp(ad_start); while (i>0) /* void loop waiting for A/D conversion */ { i--; } aux= 10*(_inp(ad_dat_h)*(double)16 + (_inp(ad_dat_l)/(double)16))/(double)4095; *y=aux; } void escribe(double *y) { double aux; double Out; int dummy_var; aux = 4095*(*y/(double)10); Out = 4095-aux; _outp(ad_sel,0x1); /* Selection of input and output channels */ _outp(da_sel,0x1); _outp(da_dat_h,(Out/16)); /* Writing the value in the card output */ _outp(da_dat_l,(16*(Out-(double)((Out/16)*16)))); _outp(da_sel,0x6); _outp(da_start,dummy_code); dummy_var=_inp(ad_start); }

Marzo 2005