INSTITUTO POLITÉCNICO NACIONAL CENTRO DE INVESTIGACIÓN Y DESARROLLO DE TECNOLOGÍA DIGITAL “MEDICIÓN DE LAS VARIABLES DEL MOVIMIENTO DE CARRERA LIMITADA” TESINA QUE PARA OBTENER LA ESPECIALIDAD EN SISTEMAS INMERSOS PRESENTA: ING. RENÉ DE JESÚS GÓMEZ LÓPEZ BAJO LA DIRECCIÓN DE: M. en C. JOSÉ MARÍA MONTOYA FLORES DICIEMBRE 2009 TIJUANA, BAJA CALIFORNIA, MÉXICO 2 3 Resumen. Este trabajo es parte integral de un proyecto cuyo objetivo es diseñar un equipo que emule una carga mecánica para estudiar variables de comportamiento de dicha carga. Se presenta la implementación de la adquisición de datos que forma parte del sistema en conjunto con la carga mecánica simulada, el sistema de generación de señales y el driver. La generación de señales lo conforman un conjunto de memorias en donde se almacena valores correspondientes a las diferentes variables a las que se quiere someter el sistema simulado tales como fricción, inercia o alguna otra fuerza particular que se desee emplear en la simulación. Estos valores son el comportamiento deseado que se ha programado previamente. Las salidas de estas señales van conectadas directamente a los actuadores con su respectivo amplificador. La adquisición de datos se realiza empleando el miniModul-515c con el que se implementa un muestreo cada milisegundo de la posición del mecanismo a través de un encoder, así como la conversión a digital de la señal de los sensores de torque. Estas lecturas se almacenan en los 32 kBytes de memoria externa incluida en la tarjeta de desarrollo antes mencionada. Finalmente el microcontrolador envía esta información a través del puerto serie cuando se le solicita mediante una aplicación realizada en Visual Basic .NET 2008 haciendo uso de la biblioteca de clases del puerto serie incluida en la .NET framework que permite implementar un puerto serie virtual a través del puerto USB de la computadora. El driver es el encargado de aportar el voltaje requerido para que el motor funcione de acuerdo a algún algoritmo de control que se implemente, dicho driver y algoritmo de control puede variar, esto es el fin de este trabajo, que cada estudiante pueda llegar con su driver y algoritmo de control y lo pruebe con el sistema integrado. 4 Abstract This work is an integral part of a project whose objective is to design a mechanism and hardware for emulate a mechanical charge. In this paper is explained the implementation of the data acquisition that is part of the system in conjunction with the emulated mechanical load, the system of signal generation and the driver. The generation of signals is made up by a set of memories where is stored the values for different variables kind of friction inertia and any other particular force that would be wanted to be consider in the simulation. These values are the desired behavior of the system that anyone has programmed previously. The outputs of these signals are directly connected to the actuators with their respective power amplifier. The data acquisition is obtained by implementing the miniModul-515c. In this development board is implemented a sampling each millisecond of the position of the mechanism through an encoder, as well as the conversion to digital of the signal from torque sensors. These readouts are stored in the 32 Kbytes of the external memory included on the development board mentioned above. Finally the microcontroller sends this information through the serial port when it was requested by a application made in Visual Basic .NET 2008 making use of the library of classes of serial port included in the .NET framework that allows us to implement a virtual serial port via the USB port of the computer. The driver is responsible for providing the voltage needed for the motor to work in agreement to some control algorithm is implemented, the driver and the control algorithm can be different, that’s the purpose of this work, in which each student can develop its own driver and control algorithm and be able to prove those in the integrated system. 5 Contenido: CAPITULO 1. – INTRODUCCIÓN ......................................................10 1.1 ANTECEDENTE Y ALCANCES. ........................................................10 1.2 PLANTEAMIENTO DEL PROBLEMA .....................................................11 1.3 Objetivo General ......................................................................11 1.4 Objetivos Específicos...............................................................11 CAPITULO 2. – SISTEMA DE EMULACIÓN DE CARGA..................13 2.1 DIAGRAMA GENERAL. .....................................................................13 2.2 PROGRAMACIÓN (TARJETA DE CIRCUITO DE EMULADOR). ..................13 2.3 MEDICIÓN (SISTEMA INMERSO). ......................................................14 2.4 INTERFAZ DE USUARIO (COMPUTADORA PERSONAL)..........................14 2.5 PARTE MECÁNICA (MECÁNICA DE EMULACIÓN Y CAPTURA).................14 2.6 MOTOR Y SU ALIMENTADOR (SISTEMA DE MOVIMIENTO).....................15 CAPITULO 3. – DESARROLLO DEL TRABAJO...............................16 3.1 ESPECIFICACIONES. .......................................................................16 3.2 ELEMENTOS A UTILIZAR. .................................................................17 3.3 PROGRAMA DEL MICROCONTROLADOR.............................................19 3.3.1 Ciclo principal........................................................................19 3.3.2 Envío de lecturas. .................................................................21 3.3.3 Captura inicial. ......................................................................23 3.3.4 Interrupción del Timer 2. .......................................................26 3.3.5 Interrupción del Puerto Serie. ...............................................28 3.4 PROGRAMA DE LA PC ....................................................................28 3.4.1 Interfaz de usuario ................................................................28 CAPITULO 4. – CONCLUSIONES Y TRABAJO FUTURO................39 6 ANEXO 1. PROBLEMA DE SINCRONIA. ..........................................40 ANEXO 2. PLATAFORMA .NET Y CONTROL DEL PUERTO SERIE. .............................................................................................................43 .Net SerialPort Class......................................................................45 ANEXO 3. CÓDIGO DE PROGRAMA DEL MICROCONTROLADOR. .............................................................................................................50 ANEXO 4. CÓDIGO DE APLICACIÓN DE LA PC. ............................54 BIBLIOGRAFÍA...................................................................................60 7 Lista de figuras: FIGURA 1. SISTEMA DE EMULACIÓN DE CARGA. .........................................13 FIGURA 2 PARTE MECÁNICA....................................................................15 FIGURA 3. COMPONENTE A DESARROLLAR ................................................16 FIGURA 4. CONEXIONES DEL MICROCONTROLADOR. ..................................17 FIGURA 5. ORGANIZACIÓN DE MEMORIA EXTERNA......................................18 FIGURA 6 CICLO PRINCIPAL DEL PROGRAMA ..............................................20 FIGURA 7. ENVÍO DE LECTURAS ...............................................................22 FIGURA 8. COMPARACIÓN ENTRE LECTURAS DE 10 Y 8 BITS DEL ADC........23 FIGURA 9. CAPTURA INICIAL. ...................................................................25 FIGURA 10. INTERRUPCIÓN DEL TMR2 ....................................................27 FIGURA 11. FORMULARIO PRINCIPAL. .......................................................29 FIGURA 12. OPCIONES DEL MENÚ. ...........................................................30 FIGURA 13. VENTANA DE GUARDAR POSICIÓN ..........................................30 FIGURA 14. AVISO DE QUE NO ENCONTRÓ PUERTO SERIE...........................31 FIGURA 15. AVISO DE COM ELEGIDO ERRÓNEAMENTE. .............................32 FIGURA 16. AYUDAS PARA EL USUARIO.....................................................33 FIGURA 17. MUESTRA GRAFICA DE LOS PASOS A SEGUIR. ..........................33 FIGURA 18. PASO 2. ...............................................................................34 FIGURA 19. PASO 3. ...............................................................................35 FIGURA 20. PASO 3 EN DECIMAL. ............................................................36 FIGURA 21. PASO 3 EN HEXADECIMAL......................................................36 FIGURA 22. ERROR POR MICRO OCUPADO. ...............................................37 FIGURA 23. ERROR DE CONEXIÓN............................................................38 FIGURA 24. ERROR DE I/O. .....................................................................38 FIGURA 25. DIAGRAMA DE POSICIÓN. .......................................................40 FIGURA 26. TIEMPO DE CONFIGURACIÓN Y DE MANTENIMIENTO. .................40 FIGURA 27. PROBLEMA DE SINCRONISMO. ................................................41 FIGURA 28. SINCRONIZACIÓN CON UN CIRCUITO MONOESTABLE.................42 FIGURA 29. FRAMEWORK .NET. ..............................................................44 8 Lista de Tablas: TABLA 1. CONSTRUCTOR DE LA CLASE SERIALPORT..................................46 TABLA 2. PROPIEDADES ÚTILES DE LA CLASE SERIALPORT.........................47 TABLA 3. MÉTODOS ÚTILES DE LA CLASE SERIALPORT...............................48 TABLA 4. EVENTOS DE LA CLASE SERIALPORT. .........................................49 TABLA 5. DELEGADOS DE LA CLASE SERIALPORT. .....................................49 9 CAPITULO 1. – INTRODUCCIÓN 1.1 Antecedente y alcances. La emulación de una carga mecánica surge de la necesidad existente de validar algoritmos de control, con la que se busca construir un mecanismo, en donde se puedan implementar diferentes algoritmos de control sin tener la necesidad de contar con un sistema real. Con este trabajo se pretende tener una planta que se pueda programar para diferentes escenarios y diferentes comportamientos que puedan emular una carga real. Esta flexibilidad es útil por que el usuario solamente tendría que preocuparse por perfeccionar su algoritmo de control contando con la facilidad de adquirir los datos arrojados por el sistema en cualquier momento. La recuperación de los datos muestreados por el sistema se podrá obtener en un archivo de texto para su posterior procesamiento en cualquier computadora que tenga WINXP, VISTA o WIN7 con el driver del cable USB-SERIE y por supuesto un puerto USB disponible. Para la factibilidad del presente trabajo se cuenta con dos aspectos primordiales a considerar, tal es el caso de la construcción de la carga mecánica y la tarjeta de desarrollo a emplear. Afortunadamente el mecanismo está construido casi en su totalidad y el kit de desarrollo miniModul-515c con el que ya se cuenta, encaja perfectamente para esta aplicación ya que permite implementar una prueba con duración de poco más de 8 segundos con un tiempo de muestreo de 1 milisegundo dada la cantidad de memoria externa con la que se cuenta, situación que es más que suficiente para una prueba de este tipo. Otro aspecto que se considera pertinente aclarar es que los datos arrojados como resultado de una prueba serán presentados sin procesamiento alguno. 10 1.2 Planteamiento del problema El trabajo realizado trata básicamente de la adquisición de datos. Los datos que se requieren son la posición y el torque de la carga, ya que con estas mediciones se pueden obtener otras variables útiles, tales como velocidad, aceleración, fuerza, trabajo etc., por medio de un procesamiento posterior mediante software. La opción más indicada para tomar lecturas de la posición es por medio de un encoder acoplado a la flecha del motor; en lo que respecta al torque podemos optar por la opción de medir la corriente que consume el motor o medir la tensión de la banda que acopla un motor con su carga. Para la primera opción la exactitud es pobre y depende mucho de conocer las características del motor, la segunda es mejor opción. Más adelante se presentará una explicación detallada de ello. Por último se tiene la necesidad de almacenar y comunicar los resultados obtenidos, es decir, las lecturas obtenidas durante la simulación de las variables a observar. 1.3 Objetivo General El desarrollo del presente trabajo tiene como objetivo crear una herramienta que se pueda utilizar para fines didácticos, donde el estudiante pueda probar algoritmos de control de una manera simple conociendo únicamente las entradas que requiere el sistema y las salidas que obtendrá del mismo. 1.4 Objetivos Específicos Para la construcción física de esta herramienta se ha planeado emplear un sistema inmerso para establecer la comunicación requerida entre el usuario y el mecanismo mismo que emulará la carga mecánica. También se busca que el comportamiento de la carga mecánica pueda ser totalmente programable, es decir, contar con la flexibilidad 11 de limitar sus movimientos, que permita establecer si será de carrera limitada o no, si la fricción será constante o variable. El sistema inmerso podrá ser conectado a cualquier computadora con puerto USB, que cuente con la aplicación y driver necesarios para establecer comunicación con la tarjeta del microcontrolador. Y para quien elabora este documento el objetivo primordial es fortalecer, enriquecer y desafiar los conocimientos adquiridos durante el paso por esta institución en la especialidad de sistemas inmersos. 12 CAPITULO 2. – SISTEMA DE EMULACIÓN DE CARGA. 2.1 Diagrama general. Para el desarrollo del presente trabajo se optó por organizar las diferentes etapas como se muestra en el siguiente diagrama a bloques. Figura 1. Sistema de emulación de carga. 2.2 Programación (Tarjeta de circuito de emulador). En esta tarjeta se aloja un conjunto de memorias donde se cargarán los datos (Inercia, fricción, efectos de gravedad y límite de carrera) que permitirán manipular ciertos actuadores con el objetivo de programar un comportamiento deseado en la planta. Las salidas de estas memorias van conectadas a un DAC, un amplificador y posteriormente a un actuador para producir el efecto esperado en el mecanismo, en otras palabras, las memorias contendrán la información referente a lo que se quiere someter al sistema. La localidad de memoria estará conectada al actuador en un tiempo dado, 13 y determinada por un contador, dicho contador recibe pulsos del encoder acoplado al motor, del cual también se medirá su torque. 2.3 Medición (Sistema inmerso). Se toma lectura de las variables esenciales que permitirán caracterizar el comportamiento completo de la parte mecánica del sistema: posición y torque. A partir de estos datos se puede obtener velocidad, aceleración, potencia, etc., es decir se puede caracterizar el comportamiento del sistema como resultado del algoritmo de control utilizado. Una vez teniendo la información de la posición y el torque del mecanismo, podemos inferir todo lo que se requiere para conocer el comportamiento del mecanismo, por lo tanto son las variables que se muestrearán cada milisegundo para ser enviadas a la PC para su posterior análisis. 2.4 Interfaz de usuario (Computadora personal). La interfaz del usuario, como su nombre lo indica, es el medio con el cual el usuario podrá interactuar con los componentes del sistema de emulación. Esta interacción es a través de la PC por medio del puerto serie, La PC se comunica al microcontrolador que a su vez ejecuta las tareas seleccionadas por el usuario y tiene las conexiones de los sensores y bus de control del sistema completo. 2.5 Parte mecánica (Mecánica de emulación y captura). Es la parte física donde se montará el motor, discos de freno, sensores, peso, etc. 14 Figura 2 Parte Mecánica. 2.6 Motor y su alimentador (Sistema de movimiento). Este componente lo integra el usuario del sistema. La persona que desee evaluar un algoritmo de control en particular, debe proporcionar el motor que va utilizar y la tarjeta que albergará el algoritmo a ser sujeto de análisis. La única restricción es emitir un pulso al iniciar, como medio de sincronización. 15 CAPITULO 3. – DESARROLLO DEL TRABAJO. 3.1 Especificaciones. La medición de variables del movimiento de carrera limitada involucra al componente de medición y parte del componente de la interfaz de usuario relacionada con dicha medición, como se menciona en el capítulo 2. Si se visualiza el presente trabajo como una caja negra se puede tener una idea clara de los requerimientos que debe satisfacer este componente para ser compatible con las otras etapas del sistema de emulación. Figura 3. Componente a desarrollar Como se observa en la figura anterior, se debe satisfacer la necesidad de obtener datos muestreados con una base de tiempo a 1ms de dos señales analógicas que provienen de dos sensores de fuerza, cuya frecuencia oscila entre 0 y 200 Hz, y dos señales digitales de 8 bits, con una frecuencia de 0 a 80KHz. Ambas señales se unen para formar una lectura de posición de 16 bits. También se requiere proporcionar una señal de “listo”, para indicar que está listo para tomar lecturas, al igual que debe aceptar una señal de “empieza”, para que en ese momento comience la toma de muestras de las variables de interés. 16 3.2 Elementos a utilizar. Para satisfacer los requerimientos solicitados, se utiliza el miniModul-515C, que es la tarjeta que contiene el microcontrolador que se utiliza para organizar las lecturas; marcar la pauta entre muestreo y muestreo; hacer la conversión analógica digital; y comunicar información solicitada por medio de la PC a través de un adaptador USB a serial (DB9) como se puede observar en la siguiente figura. Figura 4. Conexiones del microcontrolador. La memoria externa, que es parte del miniModul-515C, se utiliza para almacenar las lecturas de las variables de interés, la cual consta de 32K localidades que serán llenadas de la siguiente manera. 17 Figura 5. Organización de memoria externa. De la figura anterior, se puede observar, que primero se realizan dos conversiones analógicas a digital de las señales de fuerza, posteriormente se toman dos lecturas de posición y se almacenan en localidades de memoria de 8 bits, que son direccionadas por el apuntador DPTR de 16 bits. Por lo tanto, son 4 bytes los que se almacenan cada milisegundo, si se saturan los 32kBytes con esas muestras, equivale a almacenar datos por más de 8 segundos, lo que es suficiente para la aplicación deseada para el sistema de emulación. El dato de posición se congela en dos latches de 8 bits, dichos bits son actualizados continuamente. Al momento de ser leídos se impide que sean actualizados por medio de un circuito monoestable, para evitar problemas de sincronismo como se muestra en el anexo 1. El Timer 2 del microcontrolador es el encargado de interrumpir al microcontrolador cada milisegundo para hacer el muestreo una vez que se ha solicitado el arranque de las lecturas. 18 3.3 Programa del microcontrolador. 3.3.1 Ciclo principal. El programa del microcontrolador está organizado por modos de operación, que están relacionados con la opción elegida por el usuario que se envía desde la PC mediante el puerto serie. Inicialmente después de un hardware-RESET el programa inicia con la configuración, tanto del puerto serie como del timer 2, interrupciones, ADC, entre otras salidas de control como se muestra enseguida. 19 Figura 6 Ciclo principal del programa Como se puede observar en la figura anterior el programa del microcontrolador está en un lazo infinito evaluando R0, que es el registro donde se almacena el comando que el usuario envía por medio del puerto serie. Dicho comando se almacena al presentarse la interrupción del puerto serie. Por lo tanto, el programa se encuentra a la espera de instrucciones del usuario que son evaluadas en el lazo anterior para posteriormente ejecutar las instrucciones adecuadas. Existen tres estados que el usuario puede seleccionar y que se ejecutan independientemente uno de los otros, estos son: “r” que es cuando el usuario desea leer la memoria externa del microcontrolador, “c” cuando el usuario desea poner al micro a hacer el muestreo y “p” 20 que es lo que se ejecutará cuando el usuario desee programar las variables de fricción, inercia, etc. Existen otros dos estados secundarios que permiten conocer qué es lo que está haciendo el microcontrolador, cuando el micro tiene el estado “e”, en este proceso el microcontrolador le indica a la PC, en qué estado se encuentra actualmente y cuando el estado es “s”, le indica a la PC el progreso de las muestras enviando un aviso ya que se han capturado 256 datos. 3.3.2 Envío de lecturas. El proceso de envío de las lecturas empieza inicializando los valores de R0 y R1. R0 almacena la opción del usuario y R1 almacena el estado actual del microcontrolador, de tal suerte que una vez dentro del proceso, R0 debe ser desactivada para evitar que se ejecute este proceso repetidamente y R1 toma el valor correspondiente a la captura. Una vez teniendo esto se deshabilitan interrupciones para que el proceso se ejecute de principio a fin, sin interrupciones. Esto es necesario ya que la variable DPTR, que es el apuntador de 16 bits, se utiliza en otros procesos y en cada uno se inicializa desde 0 hasta cubrir los 32KBytes de la memoria externa que se están utilizando. El envío se realiza cargando el acumulador con el valor de la localidad de memoria actual y éste a su vez se carga al registro SBUF, de esta manera se envía byte por byte a la PC. Esto se realiza mientras la parte alta del apuntador DPTR que se almacena en el registro DPH no alcanza el valor 80H, una vez que DPH toma este valor significa que ha llegado al final de las lecturas y es cuando termina el proceso habilitando de nuevo las interrupciones, tal como se muestra en el siguiente diagrama: 21 Figura 7. Envío de Lecturas El código en ensamblador, de esta y las siguientes rutinas, se presentan en el ANEXO 3. 22 3.3.3 Captura inicial. El proceso de captura inicial se ejecuta cuando el registro R0 tiene el valor “c”. En la captura inicial se realiza lo necesario para poner al micro en alerta y listo para iniciar la toma de lecturas, esto es, para que el micro inicie el proceso de captura se necesita cargar previamente al contador externo de 16 bits con su valor de inicio, que es el que permite llevar un seguimiento de la posición, también se inicializa el DPTR y se envía la señal de “listo”. Una vez ahí, se espera la instrucción del alimentador del motor quien será el encargado de indicar el inicio del muestreo. Una vez recibida dicha instrucción, lo primero que hará el microcontrolador es enviar un cero lógico para que los latches que almacenan la posición se congelen en el valor actual mientras se realiza la lectura. En lo que el circuito monoestable realiza su labor se realizan las conversiones de las dos señales analógicas, que se conectan a los canales 0 y 1 del ADC del microcontrolador. Figura 8. Comparación entre lecturas de 10 y 8 bits del ADC. Se sabe que el ADC del micro arroja lecturas de 10 bits, como se muestra en la figura anterior, si se trabaja con localidades de memoria de 8 bits, únicamente sería necesario considerar la parte alta de los 23 registros del ADC para que se almacene la lectura de los sensores de fuerza con una resolución de 8 bits. Una vez que ya se han almacenado los dos valores analógicos se procede a activar la salida del lacth con los bits mas significativos y después se coloca en alta impedancia para que el latch con los bits menos significativos se pueda activar, una vez realizada dichas lecturas se procede a cargar al registro del TMR2 para que el lapso entre la muestra inicial y las siguientes sea de exactamente 1ms, de esta manera si se agregan o quitan instrucciones de este procedimiento se puede hacer una compensación de tiempo agregando o quitando unidades a TH2 y TL2 respectivamente según corresponda. Ya solo resta poner a contar al TMR2 y activar las interrupciones deshabilitadas anteriormente y esperar a que se presente una interrupción del TMR2 y proceder de forma similar a la captura inicial con la diferencia en que ya no se cargará el valor del contador externo de 16 bits; no se inicializará el DPTR; ni se modifican los registros del TMR2. 24 Figura 9. Captura Inicial. 25 3.3.4 Interrupción del Timer 2. A diferencia de la captura inicial, en esta rutina se monitorea el valor del apuntador DPTR, tanto para saber si se ha llenado la memoria como para saber cuántos datos han sido muestreados y así avisar a la PC para que muestre al usuario el progreso de la captura. Por tal motivo se verifica si DPL ha regresado a cero y cada vez que regresa a cero se envía un aviso a la PC para que se incremente el porcentaje de progreso de la captura. Para saber si se llenó la memoria se verifica si DPH es igual a 80 en hexadecimal y es cuando se debe suspender el almacenamiento de los datos. Una vez que se ha llenado la memoria solo resta detener el TMR2 para que ya no cuente; limpiar la bandera de interrupción; y mandar la señal a la PC que ha finalizado la prueba. 26 Figura 10. Interrupción del TMR2 27 3.3.5 Interrupción del Puerto Serie. En la rutina de interrupción del puerto serie se verifica si la interrupción es causada por una recepción. Si es causada por una transmisión es ignorada. En el caso de la recepción, se carga el valor recibido al registro R0 y posteriormente se limpia la bandera de interrupción del puerto serie. 3.4 Programa de la PC Para comunicar los datos obtenidos al usuario se desarrolló una aplicación para la PC, bajo Windows, con el entorno de desarrollo Visual Basic .NET 2008 en su versión express, bajado gratuitamente de la red. Se optó por utilizar el framework de Microsoft .NET ya que al ser proporcionado por el mismo desarrollador del sistema operativo, permite reutilizar las librerías ya cargadas en el sistema operativo sin tener que realizar programación de más bajo nivel. De este modo para poder acceder al puerto serie virtual que se conecta desde un puerto USB no se requiere hacer ninguna programación extra. Más información de esta plataforma y del control del puerto serie se presenta en el ANEXO 2. 3.4.1 Interfaz de usuario La interfaz del usuario representa el medio que permitirá interactuar con el sistema. Esta interfaz tiene el esqueleto completo que utilizará el sistema de emulación, por lo que posteriormente se le agregara al menos otro módulo. Al cargarse la aplicación se presenta el formulario principal que se muestra a continuación y cuyo código, realizado en Visual Basic, se incluye en el ANEXO 4. 28 Figura 11. Formulario principal. Se puede observar que se cuenta con una barra de menú que contiene las siguientes opciones. 29 Figura 12. Opciones del menú. Para guardar, se agregó dos opciones, la primera permite grabar en un archivo de texto las lecturas referentes a la posición y la segunda para el torque. Figura 13. Ventana de Guardar Posición La figura anterior muestra la ventana que se abre al elegir guardar posición. Se puede observar que el directorio por defecto para almacenar el archivo es la carpeta Desktop; la extensión por defecto 30 es .txt; el nombre por defecto es posicion.txt; si se elige Guardar Torque ocurre lo mismo, únicamente cambia el nombre por defecto a torque.txt. Es importante hacer notar que al iniciar la aplicación, inmediatamente intenta abrir el COM4, que es el nombre que tiene asignado el puerto serie virtual por defecto, sin embargo no está atado a utilizar únicamente el COM4, si no lo encuentra avisa al usuario y le presenta una lista de los puertos series disponibles en la PC. Si en ese momento no se ha conectado el cable USB-COM se puede conectar pero será presentado en la lista cuando se vuelva a desplegar dicha ventana, que se muestra enseguida y cuyo código se incluye en el ANEXO 4. Figura 14. Aviso de que no encontró puerto serie. El usuario tiene la opción de elegir un puerto serie de la lista o cerrar la aplicación. Si el usuario no sabe cual es el COM al que conectó el microcontrolador puede ir seleccionando cada COM de la lista. Si el COM elegido es erróneo, se le mostrará un aviso de la siguiente manera. 31 Figura 15. Aviso de COM elegido erróneamente. El código en Visual Basic de esta y los demás mensajes de error se incluyen en el ANEXO 4. Este mensaje también podría ser enviado en caso de que el cable no haya sido conectado bien o el micro está en un estado desconocido. La acción a tomar en ese caso seria darle un reset al micro o desconectar y conectar el USB para que sea dado de alta correctamente y al momento de presionar el OK mostrará la lista de los puertos COM encontrados y podrá seguir probando con otros. Para que la aplicación pueda comunicarse exitosamente el microcontrolador debe estar conectado a su fuente de voltaje, ya que al abrir la aplicación se envía un comando para que el micro le responda, si el micro no responde dentro de 500ms significa que el puerto serie elegido no es donde está conectado el micro. Si se está seguro que el COM elegido es el correcto y el micro no responde es posible que se encuentre trabado, cosa que se va solucionar con un reset. Debajo de la barra de menú de la aplicación se incluyó una etiqueta de ayuda la cual presenta indicaciones para el usuario, como se muestra a continuación 32 Figura 16. Ayudas para el usuario. Los pasos a seguir para obtener los resultados deseados del sistema se muestran en las siguientes etiquetas. Figura 17. Muestra grafica de los pasos a seguir. El paso uno será motivo de estudio de otra tesina. El paso dos corresponde a poner el microcontrolador en su modo de captura y presenta la ventana que se muestra a continuación. 33 Figura 18. Paso 2. El usuario únicamente debe presionar START cuando desee colocar el microcontrolador listo para arrancar el muestreo, inmediatamente se despliega el mensaje de “ESPERANDO” debajo del aviso de STATUS. Lo que ocurre en ese momento es que el microcontrolador espera la señal de la tarjeta que proveerá de corriente al motor. Dicha señal puede ser un pulso, que al ser detectado por el microcontrolador inmediatamente empieza con el muestreo de datos, en ese momento se presenta la hora de inicio y la etiqueta de STATUS se coloca en “CORRIENDO”, mientras se actualiza la barra de progreso cada 256 datos muestreados. Una vez finalizada la etapa de muestreo, la etiqueta de status se actualiza a “FINALIZÓ”, se despliega la hora final y se muestra la cantidad de bytes almacenados en la memoria externa del microcontrolador. Transcurriendo 5 segundos se coloca la etiqueta de status en 34 “INACTIVO”; el siguiente paso es solicitar los bytes almacenados para que se puedan observar en la aplicación. El paso tres del TAB presenta los siguientes campos. Figura 19. Paso 3. En este paso de la aplicación el usuario debe presionar el botón “Leer Datos” y al instante se envía la instrucción al microcontrolador para que envíe las lecturas. El usuario tiene la libertad de seleccionar, lecturas en números decimales o hexadecimales, dando la siguiente salida. 35 Figura 20. Paso 3 en Decimal. Figura 21. Paso 3 en Hexadecimal. 36 La lectura en hexadecimal corresponde al valor binario arrojado por el convertidor analógico-digital y la lectura en decimal muestra su equivalente en voltaje, tomando como referencia un voltaje de 5V. Cuando se presentan los datos en forma hexadecimal, los valores negativos se muestran en complemento a dos; dado que la variable que almacena cada lectura es de 2 Bytes es de esperar que los valores negativos se muestren con 4 letras o números, como se observa en la figura anterior. Algunos de los mensajes de error que presenta la aplicación se describen a continuación: enviar un comando dos veces. Figura 22. Error por micro ocupado. Cuando se desconecta el cable USB 37 Figura 23. Error de conexión. Y por fallas inherentes a la aplicación. Figura 24. Error de I/O. 38 CONCLUSIONES Y TRABAJO FUTURO. El empleo de la plataforma .NET permite aprovechar las ventajas de la programación orientada a objetos con la reutilización de código; en este caso se utilizó la clase SerialPort que, sin duda alguna, aceleró el tiempo de desarrollo de la aplicación. En la que queda pendiente agregar el código para el PASO 1 de la aplicación, dado que será desarrollado como parte de otro trabajo de tesina. El hecho de Interfazar aplicaciones por medio del puerto USB, amplía el panorama y la utilización de equipos actuales ya que por lo regular se utilizan puertos que ya no están disponibles y por ende se tiende a depender de esa tecnología y se desaprovechan las bondades y mejoras de los puertos disponibles en la actualidad. 39 ANEXO 1. PROBLEMA DE SINCRONiA. Para obtener la lectura de la posición se requiere lo siguiente. Figura 25. Diagrama de posición. Se obtiene a partir de la interfaz de un encoder que genera pulsos que son utilizados como señal de reloj de un contador de 16 bits. El valor del contador representa la posición y debe ser capturada por el microcontrolador cada milisegundo. Los 16 bits de la posición se envían en paralelo a la tarjeta de memorias de emulación y por medio de un bus de 8 bits al microcontrolador. Se requiere emplear dos latches triestado para enviar los 16 bits por el bus de 8. Alguna de las especificaciones del latch utilizado son: el tiempo de configuración ( t ) y de mantenimiento ( t ) que se muestra S h en la siguiente gráfica. Figura 26. Tiempo de configuración y de mantenimiento. 40 Esta información representa el tiempo que deben permanecer los datos a almacenar en los latches en los pines de entrada antes y después de que se coloque la terminal latch enable en cero; de lo contrario no se garantiza su confiabilidad. Debido a los requerimientos del latch se presenta un problema de sincronización. Puesto que el contador se incrementa o decrementa en sincronía con los pulsos generados por la interfaz del encoder y el lacth se controla en sincronía con el tiempo de muestreo marcado por el microcontrolador, se corre el riesgo de que tanto el contador y los latches se activen al mismo tiempo y genere una lectura errónea. Dado que no se puede predecir este comportamiento es necesario buscar una manera de evitar que se generen lecturas erróneas. Contador En sincronía con el movimiento del motor Latch En sincronía con tiempo de muestreo Figura 27. Problema de sincronismo. La opción más sencilla y confiable para evitar este problema es utilizando un circuito monoestable. Dicho circuito genera un pulso de salida, cuyo ancho de pulso es controlado por un circuito RC, cada que en la entrada detecta un flanco de bajada. La salida de este circuito se conecta al pin “latch enable” para que al momento en que dicha señal regresa a cero el dato sea almacenado. La señal de 41 entrada para este circuito proviene de una compuerta NAND, la que generará el flanco de bajada, solo cuando el pulso de la interfaz del encoder y la salida del microcontrolador estén en nivel alto; y dado que el circuito es no re-disparable, no importa si una señal llega antes que la otra, ya que una vez que se genera el pulso y se coloca la salida del micro en cero, ya no hay manera que se altere la información almacenada en los latches mientras son leídos, tal como se muestra a continuación. Figura 28. Sincronización con un circuito Monoestable. 42 ANEXO 2. PLATAFORMA .NET Y CONTROL DEL PUERTO SERIE. Microsoft .NET es un conjunto de productos y tecnologías de la empresa Microsoft dentro de los cuales la mayoría dependen del Framework .NET, el cual es un componente del sistema Windows y que se puede considerar como un equivalente a una máquina virtual. El Framework .NET puede ser descargado de la página de Microsoft aunque también viene integrada en varias tecnologías de Microsoft. La versión 3.0 del Framework está integrada al Sistema Operativo Windows Vista y a la mayoría de las versiones del Windows Server 2008. La última versión del Framework es la 3.5. Varios lenguajes de programación se utilizan, como C# (el cual es una mezcla entre C++ y Java), C++, J# (cercano a Java más no compatible con él) y Visual Basic .NET. Además de estos lenguajes, más adelante el lenguaje Python será compatible gracias al proyecto IronPython. PHP ya es compatible gracias al proyecto Phalanger. 43 Figura 29. Framework .NET. El Framework se compone de dos bloques principales: el CLR (Common-Language Runtime) y la biblioteca de clases .NET. El CLR es para .NET lo que la Máquina virtual de Java (JVM) es para Java, esto es, una máquina virtual sin la cual la ejecución de código .NET sería imposible. El Framework .Net nació para permitir la interoperabilidad entre diferentes lenguajes de programación. No importa cual lenguaje de programación se utilice para programar en .NET, pues todo el código se transforma en MSIL (Microsoft Intermediate Language). Este código intermedio no lleva ninguna instrucción relativa al Hardware o al Sistema Operativo. Entonces no se puede ejecutar directamente. A pesar de esto, se puede escribir una aplicación directamente en IL, un lenguaje que se parece a Assembler, sin necesidad de pasar por un lenguaje de última generación como C#. El CLR es necesario para ejecutar el código intermedio. Aporta varias funcionalidades como el Garbage Collector (optimiza la memoria utilizada por una aplicación durante su ejecución), la BCL 44 (Base Class Library) y el sistema de seguridad. Una vez que el código está presente en la CLR, pasa a ser compilado por el JIT Compiler (Just In Time) en lenguaje nativo de la máquina. Accesando al puerto serie Los drivers del sistema operativo son los encargados de manejar ciertos detalles específicos del hardware, tal como el detectar puertos, asignarles nombres y manejar la comunicación entre las aplicaciones. Varios drivers son proporcionados con el sistema operativo, cada uno maneja diferentes aspectos de la comunicación del puerto serie: el driver serial.sys controla la comunicación con los dispositivos seriales, el driver serenum.sys se trata de un filtro de más alto nivel que se encarga de enumerar y de recuperar la información de identificación para los dispositivos seriales con la funcionalidad de Plug-and-Play. Un dispositivo con conexión USB que es accesado mediante un puerto serial requiere de un driver adicional. El usbser.sys es un driver del bus que administra la comunicación entre el driver del puerto serie y el driver USB. Los puertos series virtuales requieren el driver proporcionado por el fabricante en lugar de los proporcionados por Windows. Para identificar los puertos series virtuales, Windows utiliza el driver del USB proporcionado por el fabricante y el proporcionado por el sistema operativo. Los archivos .INF son descriptores que contienen información necesaria para identificar los drivers de un dispositivo en particular. .Net SerialPort Class Los programadores que utilizan el .NET Framework de Microsoft pueden disponer de la clase SerialPort para poder acceder a los dispositivos que contengan puerto serie. Las aplicaciones pueden 45 crear objetos de esta clase y tienen la libertad de manipular sus propiedades, utilizar sus métodos o agregar nuevos al igual que a sus eventos, sin la necesidad de recurrir a programación de bajo nivel o a las Windows API que se utilizaban en Visual Basic 6, que por su vulnerabilidad se dejaron de usar en la plataforma .NET. La clase SerialPort fue añadida en la versión 2.0 de dicha plataforma. Y para utilizar esta clase en nuestra aplicación es necesario incluir el namespace System y el System.IO.Ports. La palabra namespace es equivalente a los paquetes y librerías de java. Tabla 1. Constructor de la clase SerialPort. La clase SerialPort tiene un constructor que se puede utilizar con o sin parámetros, dichos parámetros se emplean para inicializar algunas de las propiedades que se muestran en la siguiente tabla. Estas propiedades se deben personalizar de acuerdo a las características del puerto serie que se requiere utilizar, para el caso particular en el que se desea interfazar la PC con el miniMODUL-515C utiliza un Baud rate de 9600, ya que cualquier computadora con puerto serie soporta esta velocidad de transmisión. La propiedad de paridad no se utiliza para esta aplicación por lo que se le asigna el valor Parity.None. La propiedad DataBits le asignamos el valor de 8 bits ya que el microcontrolador permite utilizar entre 8 y 9 bits, sin embargo con 8 bits que se utilicen son suficientes. Para el caso de la propiedad StopBits que almacena el número de bits de paro se le asignó el valor StopBits.One para utilizar un solo bit y en total estará enviando un bit de inicio, 8 bits de datos y un bit de paro. Además de las propiedades mencionadas en la aplicación se utiliza la propiedad BytesToRead para saber cuántos bytes hay en el buffer disponibles para ser leídos, IsOpen se utiliza al abrir el puerto para evitar una excepción. PortName que es donde se carga el nombre del puerto serie que deseamos utilizar de los disponibles. 46 Tabla 2. Propiedades útiles de la clase SerialPort. ReceivedBytesThreshold almacena el número de bits que se requieren en el buffer para que se pueda generar un evento de dato recibido. ReadTimeout se le asigna un valor en milisegundos que la aplicación debe esperar para recibir un dato, es decir, los métodos de lectura que se verán a continuación en todos con excepción de uno bloquean el proceso donde se ejecuta la lectura hasta que se recibe el 47 dato a leer, por lo tanto, si no inicializamos esta propiedad corremos el riesgo que la aplicación se congele esperando datos. Tabla 3. Métodos útiles de la clase SerialPort. “Close” se denomina el método para liberar el puerto utilizado al cerrar la aplicación (caso en que se haya abierto el puerto); “Open”, método para abrir y reservar el puerto para la actual aplicación en tiempo de ejecución; “GetPortNames” es el método que regresa un arreglo con los puertos COM presentes en la PC. De los métodos de lectura que se muestran en la tabla anterior únicamente ReadExisting es el único que no bloquea al proceso al ser empleado. 48 Tabla 4. Eventos de la clase SerialPort. De los eventos generados por la clase SerialPort solamente se utiliza el evento DataReceived que como su nombre lo indica, se genera un evento al recibir el número de bytes que se determinaron con la propiedad ReceivedBytesThreshold. Ahora bien, cuando se presenta este evento se requiere especificar el componente que será avisado en ese caso, para hacerlo se requiere de declarar un delegado que es un concepto que se maneja en la plataforma .NET Tabla 5. Delegados de la clase SerialPort. El único delegado que se utiliza para esta aplicación es el SerialDataReceivedEventHandler. Un delegado es una estructura de programación que permite invocar a uno o varios métodos a la vez. Estos métodos pueden encontrarse en la misma clase desde la que se invocan o en otras clases asociadas. Hablando "a bajo nivel", un delegado es un puntero fijo a una función (pero sin la complejidad de la administración propia de dicho puntero). El principal uso de los delegados es notificar a uno o varios componentes el acontecimiento de un determinado evento con el fin de que dichos componentes tomen alguna acción al respecto. 49 ANEXO 3. CÓDIGO DE PROGRAMA DEL MICROCONTROLADOR. $NOMOD51 $INCLUDE(REG515c.INC) CSEG AT USING 0 SJMP INICIO 0 ;----------------------------------------------------------------------------RUTINA DE INTERRUPCIÓN DEL PUERTO SERIE ORG 0023H LJMP SERISR ;----------------------------------------------------------------------------RUTINA DE INTERRUPCIÓN DE TIMER 2 ORG 002BH LJMP TIMER2ISR ;----------------------------------------------------------------------------CONFIGURACIÓN INICIO: MOV MOV MOV IEN0,#10110000B PCON,#10000000B SCON,#01010000B MOV ADCON1,#10000000B MOV ADCON0,#10000000B MOV MOV SRELH,#03H SRELL,#0B2H ;SE HABILITAN INTERRUPCIONES DEL TIMER2 PUERTO SERIE ;EL BIT SMOD=1 DEL REGISTRO PCON. ;SE ELIGE MODO 1 DE PUERTO SERIE ;Y SE HABILITA LA RECEPCIÓN DEL PUERTO SERIE ;SE PONE EN ALTO ADCL PARA LOGRAR UNA FRECUENCIA ;DE CONVERSIÓN MENOR A 2MHZ RECOMENDADA POR EL FABRICANTE ;SE PONE A BD, PARA ELEGIR AL BAUD GENERATOR COMO GENERADOR DEL BAUD RATE ;DISPARO PARA CONVERSIÓN INTERNA ;MODO DE CONVERSIÓN EN SINGLE ;SE ELIGE EL CANAL 0 ;PARA 9600 BAUD ;----------------------------------------------------------------------------CONFIGURANDO TIMER 2 PARA INTERRUPCIONES DE MUESTREO MOV CRCH,#0FCH ;VALOR DE RECARGA PARA CONTADOR MOV CRCL,#17H MOV T2CON,#00010000B ;SE CONFIGURA T2 CON RECARGA Y SE DEJA DETENIDO ;----------------------------------------------------------------------------INICIALIZANDO CONTADOR DE 16 BITS SETB P4.6 ;PONE EN ALTA IMPEDANCIA BUFFER LOWER SETB P4.5 ;PONE EN ALTA IMPEDANCIA BUFFER HIGH SETB P4.7 ;EL LATCH ES CONTROLADO POR SEÑAL DE CLOCK MOV R0,#00H ;OPCIÓN DE MENÚ, VALOR INICIAL MOV R1,#00H ;PARA ALMACENAR EL ESTATUS DEL MICRO. 0 EN INACTIVO CLR P4.0 ;PARA HACERLO ENTRADA ;---------------------------------------------------------------------------MAIN PRINCIPAL MAINLOOP: CJNE R0,#'r',OPCAPTURA CALL MEMEXTR OPCAPTURA: CJNE R0,#'c',OPPROG CALL CAPTURAINI OPPROG: CJNE R0,#'p',OPSTAT CALL PROGMEM OPSTAT: CJNE R0,#"s",OPEXTRA CALL STATUS OPEXTRA: CJNE R0,#'e',MAINLOOP CALL OPCIONESTADO JMP MAINLOOP ;----------------------------------------------------------------------------ENVIAR ESTADO DEL MICRO OPCIONESTADO: MOV A,R1 MOV SBUF,A ;ENVÍA EL ÚLTIMO DATO DE ESTADO ENVEDO: JNB TI,ENVEDO CLR TI MOV R0,#00H ;ELIMINA LA OPCIÓN DE MENÚ LEÍDA RET ;---------------------------------------------------------------------------ENVÍA STATUS DE CAPTURA STATUS: MOV A,DPH;#80H 50 MOV SBUF,A ;ENVÍA EL ÚLTIMO DATO DEL STATUS JNB CLR MOV RET TI,ENVSTA TI R0,#00H ;ELIMINA LA OPCIÓN DE MENÚ LEÍDA ENVSTA: ;----------------------------------------------------------------------------ENVÍO DE LECTURAS MEMEXTR: MOV R0,#00H ;ELIMINA LA OPCIÓN DE MENÚ LEÍDA MOV R1,#03H ;SE ENCUENTRA EN ESTADO DE ENVÍO DE LECTURAS MOV IEN0,#10100000B ;SE HABILITA LA INTERRUPCIÓN DEL TMR2 Y DESHABILITA LA DEL PUERTO SERIE MOV DPTR,#0000H MASR0: MOVX MOV A,@DPTR SBUF,A JNB CLR INC MOVX MOV TI,MASR01 TI DPTR A,@DPTR SBUF,A JNB CLR INC TI,MASR11 TI DPTR MOVX MOV A,@DPTR SBUF,A JNB CLR INC TI,MASR21 TI DPTR MOVX MOV A,@DPTR SBUF,A JNB CLR INC MOV CJNE MOV MOV RET TI,MASR31 TI DPTR A,DPH A,#80H,MASR0 IEN0,#10110000B R1,#00H ;ENVÍA LA PRIMERA LECTURA MASR01: ;ENVÍA LA SEGUNDA LECTURA MASR11: ;ENVÍA LA TERCERA LECTURA MASR21: ;ENVÍA LA CUARTA LECTURA MASR31: ;SE HABILITAN LAS INTERRUPCIONES DEL TIMER2 Y PUERTO SERIE ;HA TERMINADO EL ENVÍO Y REGRESA A INACTIVO ;----------------------------------------------------------------------------CAPTURA INICIAL CAPTURAINI: MOV R0,#00H ;ELIMINA LA OPCIÓN DE MENÚ ELEGIDA, ENVIADA POR PUERTO SERIE MOV R1,#02H ;SE ENCUENTRA EN ESTADO DE CAPTURA DE MUESTRAS MOV IEN0,#10100000B ;SE HABILITAN INTERRUPCIONES DEL TMR2 Y SE DESHABILITA LA DEL PUERTO SERIE SETB P4.3 ;PONE EN ALTO LOAD (ESTA EN ALTO POR DEFAULT) ;PARA CARGAR EL CONTADOR DE 16 BITS CON UN VALOR DE INICIO CLR P4.3 ;NECESARIO PARA PRODUCIR UN FLANCO DE SUBIDA MOV DPTR,#0000H ;SE INICIALIZA EL APUNTADOR DE 16BITS SETB P4.3 ;YA ESTÁN LOS VALORES DE INICIO EN EL CONTADOR CLR P4.2 ;ENCIENDE LÁMPARA PARA INDICAR QUE ESTA EN ESPERA PARA INICIAR CAPTURA CAPTWAIT: JNB P4.0,CAPTWAIT ;EN ESPERA QUE SE SOLICITE CAPTURA CLR P4.7 ;ENVIADO AL MONOESTABLE PARA QUE YA NO SE CAPTUREN MAS VALORES EN LATCH MOV MOV ADCON0,#10000000B ADDATL,#0FFH ;LECTURA DEL ADC CANAL 0 ;SE ELIGE CANAL CERO Y SE DEJA IGUAL EL ADCL ;SE REALIZA LA CONVERSIÓN JB MOV MOVX INC BSY,XMASW21 A,ADDATH @DPTR,A DPTR MOV MOV ADCON0,#10000001B ADDATL,#0FFH JB MOV MOVX INC BSY,XMASW31 A,ADDATH @DPTR,A DPTR XMASW21: ;ESPERAR MIENTRAS TERMINA LA CONVERSIÓN ;LECTURA DEL ADC CANAL 1 ;SE ELIGE CANAL UNO Y SE DEJA IGUAL EL ADCL ;SE CORRE LA CONVERSIÓN XMASW31: ;ESPERAR MIENTRAS TERMINA LA CONVERSIÓN 51 CLR MOV MOVX INC SETB P4.5 A,P5 @DPTR,A DPTR P4.5 ;HABILITA SALIDA DE LATCH HIGH CLR MOV MOVX INC SETB P4.6 A,P5 @DPTR,A DPTR P4.6 MOV MOV SETB TH2,#0F8H TL2,#7FH T2I0 ;VALOR INICIAL PARA CONTADOR SETB P4.7 ;SE HABILITA LACTH PARA QUE PUEDAN SER ACTUALIZADOS ;PRIMERA LECTURA DE POSICIÓN ;DESHABILITA SALIDA DE LATCH HIGH ;HABILITA SALIDA LATCH LOW ;SEGUNDA LECTURA DE POSICIÓN ;DESHABILITA SALIDA DE LATCH LOW ;SE PONE A CONTAR AL TMR2 RET ;----------------------------------------------------------------------------TIMER 2 ISR. CAPTURA DE MUESTRAS TIMER2ISR: NOP CLR P4.7 ;LATCH ENABLE ;LECTURA DEL ADC CANAL 0 ;SE ELIGE CANAL CERO Y SE DEJA IGUAL EL ADCL ;SE CORRE LA CONVERSIÓN MOV MOV ADCON0,#10000000B ADDATL,#0FFH JB MOV MOVX INC BSY,MASW21 A,ADDATH @DPTR,A DPTR MOV MOV ADCON0,#10000001B ADDATL,#0FFH JB MOV MOVX INC BSY,MASW31 A,ADDATH @DPTR,A DPTR CLR MOV MOVX INC SETB P4.5 A,P5 @DPTR,A DPTR P4.5 ;HABILITA SALIDA DE HIGH CLR MOV MOVX INC SETB P4.6 A,P5 @DPTR,A DPTR P4.6 ;HABILITA SALIDA LATCH LOW ;DESHABILITA SALIDA DE LATCH LOW SETB P4.7 ;LATCH ENABLE MOV CJNE MOV A,DPL A,#00H,MASW0B R0,#'s' ;INDICA QUE DEBE ENVIAR EL STATUS (S) MOV CJNE A,DPH A,#80H,MASW0 SETB CLR P4.2 T2I0 ;INDICA QUE NO ESTA LISTO SE APAGA LA LÁMPARA ;PARA DE CONTAR EL T2 MOV MOV A,#00H SBUF,A ;ENVÍA EL ÚLTIMO DATO DEL STATUS JNB CLR TI,MASW0C TI MOV MOV MOV R0,#00H R1,#00H IEN0,#10010000B MASW21: ;ESPERA MIENTRAS TERMINA LA CONVERSIÓN ;LECTURA DEL ADC CANAL 1 ;SE ELIGE CANAL UNO Y SE DEJA IGUAL EL ADCL ;SE CORRE LA CONVERSIÓN MASW31: ;ESPERAR MIENTRAS TERMINA LA CONVERSIÓN ;PRIMERA LECTURA DE POSICIÓN ;DESHABILITA SALIDA DE LATCH HIGH ;SEGUNDA LECTURA DE POSICIÓN MASW0B: MASW0C: 52 ;ELIMINA LA OPCIÓN DE MENÚ LEÍDA ;HA TERMINADO EL MUESTREO Y REGRESA A ESTADO INACTIVO ;SE HABILITA INTERRUPCIÓN DEL PUERTO SERIE Y SE DESHABILITA LA DEL TMR2 MASW0: CLR RETI TF2 ;---------------------------------------PROGRAMACIÓN DE MEMORIAS PROGMEM: MOV R0,#00H ;ELIMINA LA OPCIÓN DE MENÚ LEÍDA MOV R1,#01H ;SE ENCUENTRA EN ESTADO DE PROGRAMACIÓN MOV R1,#00H ;HA TERMINADO DE PROGRAMAR Y REGRESA A ESTADO INACTIVO RET ;---------------------------------------SERIAL PORT ISR SERISR: JB TI,TRANSF MOV A,SBUF MOV R0,A MOV P1,A CLR RI RETI TRANSF: RETI END 53 ANEXO 4. CÓDIGO DE APLICACIÓN DE LA PC. Código del formulario principal: Imports Imports Imports Imports Imports Imports Imports Imports System System.IO System.IO.Ports System.Runtime.Remoting.Messaging System.Collections.Generic System.Text System.Windows.Forms System.Drawing Public Class Form1 Friend horaActual As Date Friend estado As Integer = -1 Friend paraEnviar As String Friend myValidarPuerto As New validarPuerto Friend myMicroOcupado As New MicroOcupado Friend myPuertoEquivocado As New puertoEquivocado Friend myPuertoDesconectado As New puertoDesconectado Friend myPuertoNoFunciona As New puertoNoFunciona Public nombrePuerto As String = "COM4" Friend puertoSerieBuffer(32767) As Byte Friend lectorBinario As BinaryReader Friend opcionDecimal As Boolean = True Friend pasoElegido As Integer = 0 Friend contadorStatus As Integer = 0 Friend dato As Byte Public Shared contador As Integer = 0 Friend auxPos As StringBuilder Friend auxTorque As StringBuilder Friend auxTime As StringBuilder Friend resultadoDecimal As StringBuilder Friend resultadoHexadecimal As StringBuilder Friend Delegate Sub SerialDataReceivedEventHandlerDelegate(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Private SerialDataReceivedEventHandler1 As New SerialDataReceivedEventHandler(AddressOf DataReceived) Friend myPuertoSerie As SerialPort Friend MyMainForm As Form1 Private Delegate Sub AccessFormMarshalDelegate() Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click Label8.Text = "Pueder ejecutar los pasos en orden o como mejor te convenga." End Sub Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing If (Not (myPuertoSerie Is Nothing)) Then If myPuertoSerie.IsOpen Then Do While (myPuertoSerie.BytesToRead > 0) myPuertoSerie.ReadExisting() Loop myPuertoSerie.Dispose() End If End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load AddHandler validarPuerto.configuracionPuerto, AddressOf setportparameter Dim namearray() As String Dim index As Integer = -1 Dim good As Boolean = False Do Until (good) index = -1 namearray = SerialPort.GetPortNames Do index += 1 Loop Until ((namearray(index) = nombrePuerto) Or (index = namearray.GetUpperBound(0))) If (namearray(index) = nombrePuerto) Then myPuertoSerie = New SerialPort(nombrePuerto, 9600, Parity.None, 8, StopBits.One) myPuertoSerie.ReadBufferSize = 65536 54 myPuertoSerie.ReadTimeout = 500 myPuertoSerie.ReceivedBytesThreshold = 1 If (Not myPuertoSerie.IsOpen) Then Try myPuertoSerie.Open() Try pasoElegido = 0 paraEnviar = "e" myPuertoSerie.Write(paraEnviar) estado = myPuertoSerie.ReadByte If estado = 0 Then good = True estado = -1 Else myPuertoEquivocado.ShowDialog() myPuertoSerie.ReadExisting() myPuertoSerie.Dispose() If (myValidarPuerto.ShowDialog() = Windows.Forms.DialogResult.Cancel) Then End End If End If Catch ex As TimeoutException myPuertoEquivocado.ShowDialog() myPuertoSerie.ReadExisting() myPuertoSerie.Dispose() If (myValidarPuerto.ShowDialog() = Windows.Forms.DialogResult.Cancel) Then End End If Catch ex As System.IO.IOException myPuertoNoFunciona.ShowDialog() End End Try Catch ex As UnauthorizedAccessException If (myValidarPuerto.ShowDialog() = Windows.Forms.DialogResult.Cancel) Then End End If good = False Catch ex As System.Exception If (myValidarPuerto.ShowDialog() = Windows.Forms.DialogResult.Cancel) Then End End If good = False End Try End If Else If (myValidarPuerto.ShowDialog() = Windows.Forms.DialogResult.Cancel) Then End End If good = False End If Loop Timer1.Stop() AddHandler myPuertoSerie.DataReceived, SerialDataReceivedEventHandler1 End Sub Private Sub setportparameter(ByVal puertoSeleccionado As String) nombrePuerto = puertoSeleccionado End Sub Private Sub AccessFormMarshal() Dim args() As Object = {} Dim AccessFormMarshalDelegate1 As New AccessFormMarshalDelegate(AddressOf AccessForm) MyBase.Invoke(AccessFormMarshalDelegate1, args) End Sub Private Sub AccessForm() Select Case pasoElegido Case 0 Case 1 Case 2 If (Not estado = 0) Then estado = dato Else If contadorStatus = 0 Then horaActual = Now TextBox5.Text = horaActual End If Label7.Text = "CORRIENDO" contadorStatus = contadorStatus + 256 55 ProgressBar1.Value = contadorStatus * (100 / 32768) If ProgressBar1.Value = 100 Then ProgressBar1.Value = 0 Label7.Text = "FINALIZO" estado = -1 Timer1.Start() End If TextBox3.Text = contadorStatus If contadorStatus = 32768 Then horaActual = Now TextBox6.Text = horaActual End If End If Case 3 TextBox2.Text = contador If contador >= 32768 Then estado = -1 Dim fin As Integer = puertoSerieBuffer.Count / 4 - 1 Dim posicion(fin) As Double Dim torque(fin) As Double Dim a As Integer Dim b As Integer Dim i As Integer = 0 auxPos = New StringBuilder auxTorque = New StringBuilder auxTime = New StringBuilder resultadoDecimal = New StringBuilder resultadoHexadecimal = New StringBuilder '***************************datos decimales For index As Integer = 0 To puertoSerieBuffer.Count - 4 Step 4 posicion(i) = puertoSerieBuffer(index + 2) * 256 + puertoSerieBuffer(index + 3) a = puertoSerieBuffer(index) b = puertoSerieBuffer(index + 1) torque(i) = (a - b) * (5 / 255) i += 1 Next For index As Integer = 0 To fin auxTime.AppendLine(index) auxPos.AppendLine(posicion(index)) auxTorque.AppendLine(torque(index)) resultadoDecimal.AppendLine(Chr(9) & index & Chr(9) & Chr(9) & posicion(index) & Chr(9) & Chr(9) & Format(torque(index), "0.000")) Next Dim torqueH(fin) As Short Dim posicionH(fin) As Integer i = 0 For index As Integer = 0 To puertoSerieBuffer.Count - 4 Step 4 posicionH(i) = puertoSerieBuffer(index + 2) * 256 + puertoSerieBuffer(index + 3) a = puertoSerieBuffer(index) b = puertoSerieBuffer(index + 1) torqueH(i) = a - b i += 1 Next '*******************************datos hexadeciamles For index As Integer = 0 To fin auxTime.AppendLine(index) auxPos.AppendLine(Convert.ToString(posicionH(index), 16).PadLeft(2, "0"c)) auxTorque.AppendLine(Convert.ToString(torqueH(index), 16).PadLeft(2, "0"c)) resultadoHexadecimal.AppendLine(Chr(9) & index & Chr(9) & Chr(9) & Convert.ToString(posicionH(index), 16).PadLeft(2, "0"c).ToUpper _ & Chr(9) & Chr(9) & Convert.ToString(torqueH(index), 16).PadLeft(2, "0"c).ToUpper) Next If opcionDecimal Then TextBox1.Text = resultadoDecimal.ToString Else TextBox1.Text = resultadoHexadecimal.ToString End If End If Case Else End Select End Sub Private Sub DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Dim numberOfBytesToRead As Integer 56 Select Case pasoElegido Case 0 Case 1 Case 2 If Not (String.Equals(paraEnviar, "e")) Then dato = myPuertoSerie.ReadByte End If Case 3 numberOfBytesToRead = myPuertoSerie.BytesToRead contador = numberOfBytesToRead If numberOfBytesToRead >= 32768 Then Dim mySerialPortStream As Stream mySerialPortStream = myPuertoSerie.BaseStream lectorBinario = New BinaryReader(mySerialPortStream) lectorBinario.Read(puertoSerieBuffer, 0, 32768) End If Case Else End Select If Not (String.Equals(paraEnviar, "e")) Then Me.AccessFormMarshal() End If End Sub Private Sub btnWriteSingle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnWriteSingle.Click If estado = -1 And myPuertoSerie.IsOpen Then Try pasoElegido = 0 paraEnviar = "e" myPuertoSerie.Write(paraEnviar) estado = myPuertoSerie.ReadByte pasoElegido = 3 TextBox1.Text = "" paraEnviar = "r" myPuertoSerie.Write(paraEnviar) Debug.WriteLine(paraEnviar) Catch ex As TimeoutException Catch ex As System.IO.IOException myPuertoNoFunciona.ShowDialog() End End Try Else If Not myPuertoSerie.IsOpen Then myPuertoDesconectado.ShowDialog() End Else myMicroOcupado.ShowDialog() End If End If End Sub Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick Timer1.Stop() Label7.Text = "INACTIVO" End Sub Private Sub SalirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SalirToolStripMenuItem.Click End End Sub Private Sub GuardarComoToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GuardarComoToolStripMenuItem.Click If SaveFileDialog1.ShowDialog() = DialogResult.OK Then Dim myStreamWriter As New StreamWriter(SaveFileDialog1.FileName) If Not (myStreamWriter Is Nothing) Then myStreamWriter.Write(auxPos.ToString) myStreamWriter.Close() End If End If End Sub Private Sub GuardarTorqueToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GuardarTorqueToolStripMenuItem.Click If SaveFileDialog2.ShowDialog() = DialogResult.OK Then Dim myStreamWriter As New StreamWriter(SaveFileDialog2.FileName) If Not (myStreamWriter Is Nothing) Then myStreamWriter.Write(auxTorque.ToString) myStreamWriter.Close() 57 End If End If End Sub Private Sub RadioButton1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.CheckedChanged opcionDecimal = True If Not TextBox1.Text = "" Then TextBox1.Text = resultadoDecimal.ToString End If End Sub Private Sub RadioButton2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton2.CheckedChanged opcionDecimal = False If Not TextBox1.Text = "" Then TextBox1.Text = resultadoHexadecimal.ToString End If End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If estado = -1 And myPuertoSerie.IsOpen Then contadorStatus = 0 Label7.Text = "ESPERANDO" TextBox3.Text = "" TextBox5.Text = "" TextBox6.Text = "" pasoElegido = 0 Try paraEnviar = "e" myPuertoSerie.Write(paraEnviar) estado = myPuertoSerie.ReadByte pasoElegido = 2 If estado = 0 Then paraEnviar = "c" myPuertoSerie.Write(paraEnviar) Debug.WriteLine(paraEnviar) End If Catch ex As TimeoutException Debug.WriteLine("ocurrio timeout") Catch ex As System.IO.IOException myPuertoNoFunciona.ShowDialog() End End Try Else If Not (myPuertoSerie.IsOpen) Then myPuertoDesconectado.ShowDialog() End Else myMicroOcupado.ShowDialog() End If End If End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click pasoElegido = 1 End Sub Private Sub TabControl1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TabControl1.MouseClick Dim value As TabPage value = TabControl1.SelectedTab If value.Equals(TabPage2) Then Label8.Text = "Presiona START para poner el micro en modo de captura." ElseIf value.Equals(TabPage1) Then Label8.Text = "Se implementara proximamente." Else Label8.Text = "Pueder ejecutar los pasos en orden o como mejor te convenga." End If End Sub End Class Código del formulario del error “microcontrolador ocupado”: Public Class MicroOcupado 58 Private Sub Label1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label1.Click End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.DialogResult = Windows.Forms.DialogResult.OK End Sub Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click End Sub Private Sub Label2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label2.Click End Sub End Class Código del formulario del error “puerto desconectado”: Public Class puertoDesconectado Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.DialogResult = Windows.Forms.DialogResult.OK End Sub End Class Código del formulario del error “puerto equivocado”: Public Class puertoEquivocado Private Sub puertoEquivocado_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.DialogResult = Windows.Forms.DialogResult.OK End Sub End Class Código del formulario del error “puerto no funciona”: Public Class puertoNoFunciona Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.DialogResult = Windows.Forms.DialogResult.OK End Sub End Class Código del formulario del aviso “no encontró puerto serie elegido”: Imports System Imports System.Configuration Imports System.IO Imports System.IO.Ports Public Class validarPuerto Friend Shared Event configuracionPuerto(ByVal puertoSeleccionado As String) Private Sub validarPuerto_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ComboBox1.DataSource = SerialPort.GetPortNames End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click RaiseEvent configuracionPuerto(ComboBox1.SelectedItem.ToString) Me.DialogResult = Windows.Forms.DialogResult.OK End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.DialogResult = Windows.Forms.DialogResult.Cancel End Sub End Class 59 BIBLIOGRAFÍA [1] Jeffrey Richter, "WINDOWS VIA C/C++”, Microsoft Press, 2008. [2] Mark E. Russinovich, “WINDOWS INTERNALS”, Microsoft Press, 2005 [3] Bill Vejen, Billy Hollis, “PROFESSIONAL VISUAL BASIC 2008”, Wiley, 2008 [4] http://www.phytec.com/pdf/manuals/L-230e.pdf [5] http://www.phytec.com/pdf/datasheets/C515C_UM.pdf 60