PRÁCTICA FINAL SDMI Estación meteorológica David Guerra, Roman Valls, Daniel Clemente. SDMI22E. Junio 2005. %! Target: html %! Options: --toc %! Style: basic.css ------------------------- %%toc ------------------------- La práctica consiste en usar el micro 80C196KD con una placa de expansión para implementar una estación meteorológica. Mediante un panel se mostrará: - Temperatura ambiente (de -20 a 50 grados) - Humedad (de 0 a 100 %) - Velocidad del viento (km/h y nombre) - Dirección del viento (ángulo y nombre) Los valores para V (velocidad) y D (dirección) se actualizan cada segundo, pero T (temperatura) y H (humedad) se muestran como la media durante los 10 últimos segundos (o minutos, según se configure). Además está la función de Reloj, que cuenta en formato HH:MM:SS. Para medir la temperatura, humedad y dirección usaremos el conversor AD, ya que las muestras tienen una variabilidad pequeña y por tanto se pueden medir correctamente. En cambio, para la velocidad usamos las HSI's porque queremos tratar valores discretos que nos llegan del generador de funciones. = Diagrama de bloques de la placa = [bloque.png] Las siguientes fotografías muestran el aspecto de la placa de ampliación una vez finalizadas todas las conexiones que hemos comentado: [placaplaca.jpg] = Esquema eléctrico = [electrico.png] = Explicación de la solución hardware propuesta = En el montaje tratamos cinco entradas diferentes, tres de ellas son entradas A/D (temperatura, humedad y dirección del viento), una HSI (velocidad del viento), y por último una interrupción externa (pulsador); como interfaz de salida utilizamos un display LCD. En el puerto P0 se encuentran las entradas analógicas; de las ocho entradas posibles, se han utilizado tres. Éstas han sido configuradas de la siguiente manera: P0.1 (patilla 29 JP2) para tomar muestras de temperatura, P0.2 (patilla 31 JP2) para muestras de humedad y P0.3 (patilla 35 JP2) para la dirección del viento. Cada vez que solicitamos una conversión, se ha de seleccionar, mediante el registro ad_command, la patilla del P0 que tiene la información que nos interesa. Como las entradas en realidad eran simuladas por potenciómetros, la Vcc y Gnd de estos se tomaron de las patillas 2 y 1 de JP2. Para poder hacer el cálculo de la velocidad del viento, se simula mediante un generador de señal una entrada de pulsos (tics). Debido a que esta señal puede producir falsas lecturas, se utiliza también una puerta en histéresis (40106, patilla 3 entrada, patilla 4 salida), de esta forma nos aseguramos de que el ruido de la señal no provocará falsas HSI. La salida de la puerta en histéresis, al estar ya filtrada, se conecta a la entrada HSI.0 (patilla 12 JP2). El montaje del pulsador (interrupción externa) consta de varios elementos: una resistencia y un condensador conectados en serie, un pulsador conectado en paralelo con el condensador y una puerta en histéresis (40106, patilla 1 entrada, patilla 2 salida); en este caso también es necesario filtrar la señal producida por el pulsador, ya que al conmutar, se producen una serie de flancos fantasma que podrían provocar la lectura de falsas pulsaciones. La entrada de la puerta en histéresis se conecta en el punto en el que se unen: pulsador, resistencia y condensador. La salida del trigger, al tener ya filtrada la pulsación, se conecta directamente a P2.2 (patilla 28 JP1); las Vcc y Gnd de la puerta en histéresis y del filtro formado por el condensador y la resistencia , se toman de las patillas 1 y 19 de JP1. Para la salida de información utilizamos un display conectado al P1, cuyas Vcc y Gnd se han tomado de las patillas 2 y 1 de JP2. El display necesita además un potenciómetro para regular el contraste. Las Vcc y Gnd de este potenciómetro también se han tomado de las patillas 2 y 1 de JP2. = Diagrama de flujo del software = [flujo.png] La primera tarea que realiza nuestro programa es la de llamar a las funciones encargadas de inicializar todos los dispositivos involucrados en el sistema (LCD, Timer, AD & HSI). Una vez establecidos los parámetros de cada dispositivo, se entra en el bucle principal del programa. Mediante el botón se selecciona el modo activo (0, 1, 2, 3) en el gráfico. Dependiendo del modo selecionado, se lanzarán conversiones digitales o se guardarán interrupciones en de la hsi (con sus respectivos cambios de escala). El tratamiento de medias se comentará más adelante en detalle, pero la idea básica es recoger valores cada segundo y mostrar el resultado de la media cada 10 segundos. Paralelamente a las anteriores operaciones, se mantiene un contador mediante el timer2 que nos servirá para mostrar la hora. Más adelante también se detalla el cálculo teórico que nos permite decir que 20 overflows equivale a un segundo. = Cálculos Teóricos: = == Número de overflows por segundo: == El reloj del 196KD va 20 Mhz. A razón de 1 state time = 2 ciclos, hay 10M st por segundo. Como hemos configurado el Timer2 en "modo normal", se incrementa una vez cada 8 st, o sea, 10M/8 = 10485760/8 = 1310720 incrementos por segundo. Como el Timer2 es de 16 bits, se desborda cada 2^16 incrementos, por tanto 1310720/(2^16) = 1310720/65536 = exactamente 20 veces por segundo. En total, cada 20 overflows del Timer2 representan un segundo; eso hace fácil contar el tiempo desde la propia RSI (cada 20 ejecuciones de la RSI, incrementar el número de segundos). [20ovfs.png] == Conversiones entre unidades: == Para poder mostrar el valor interno recogido por el conversor AD a un valor representativo, tenemos que usar factores de conversión simples procurando que ningún término de la operación se desborde (valor >65535). Estas operaciones simples se pueden observar en el código. El cálculo más complicado es el de "velocidad de los tics HSI" a km/h al medir la velocidad del viento. Para que no se desborde la variable, se hace el cálculo en milisegundos, y teniendo en cuenta que el Timer puede haberse desbordado varias veces entre un tic y el siguiente. En el código están detalladas las conversiones necesarias. == Cálculo de medias: == La temperatura y la dirección del viento se muestrean cada segundo, pero el valor mostrado sólo se actualiza cada 10 segundos, con una media de los 10 últimos valores instantáneos. Usamos la media aritmética normal: en una variable se van acumulando los 10 valores, y cuando llega el décimo, dividimos entre 10. Con un entero (16 bits) para el sumatorio es suficiente, ya que la temperatura puede ser como mucho 50 grados (50*10=500) y la dirección del viento 360 grados (360*10=3600), por tanto el acumulador siempre valdrá menos de 65535. == Coste de RSIs: == Todas las RSI (botón, HSI, Timer2) inhiben las interrupciones, pero se ejecutan muy rápido. La del botón y la del reloj son triviales (unas pocas operaciones matemáticas), y la de HSI siguen siendo cálculos de tiempo constante, sin ningún bucle. La de los HSI consiste en: 2 sumas/restas, 4 productos/divisiones, y varias asignaciones. Todo esto se tendrá que ejecutar antes de que llegue el siguiente tic por HSI para que los cálculos sean correctos. Si un tic llegase demasiado rápido, se perdería ya que las interrupciones están desactivadas mientras se ejecuta esta RSI. A velocidades razonables para un anemómetro, el código funciona bien. = Ampliaciones: = Aspecto de la placa y funcionamiento: ==Visión general:== [p4120196.jpg] ==Modos:== [modos.jpg] Añadidos visuales: Hemos considerado oportuno añadir barras visuales (bloques negros que se aprecian en las fotos), para indicar el nivel de humedad y temperatura en estos dos modos. = Explicación del código: = ==main.c:== Este fichero contiene el programa principal (main). Lo primero que hace es inicializar los registros de los diferentes componentes de la placa que se usarán (ext_int, timer2, ad y hsi's). Las funciones relativas a cada dispositivo se encuentran en ficheros separados para facilitar su mantenibilidad. Se separan dentro de cada uno de estos ficheros, las inicializaciones y el código específico que deben ejecutar para los propósitos de la práctica (inits_ad y conversio_ad, por ejemplo). Cabe destacar la función del bucle principal que selecciona la acción a hacer de entre los diferentes modos, en función del valor de la variable 'modo' que es actualizada por el botón conectado a ext_int. Además, también actualiza el reloj que se muestra en todos los modos, cada segundo (mediante la espera que realizamos con el while anidado). También se aprovecha para tomar muestras de las magnitudes que necesitan media (velocidad y dirección del viento). ==timer2.c:== Obviando las inicializaciones del timer2 (inits_timer2()), la parte más relevante de este fichero es la RSI. Dicha RSI mantiene la cuenta de los overflows que se producen en el timer2, contando 1 segundo para cada 20 overflows (ver sección de cálculos teóricos para su explicación). ==ad.c:== La temperatura, humedad y dirección usan 3 de los 8 canales del AD para realizar sus conversiones. Posteriormente se realiza un cambio de escala para adaptar el valor interno a la representación que queremos (grados centígrados, porcentaje y grados sexagesimales respectivamente). ==hsi.c:== Para medir la velocidad del viento usamos las HSI's. Como el anemómetro puede girar muy poco a poco, lo que hacemos es contar el tiempo que ha pasado entre un tic HSI y el siguiente, y luego hacer una conversión (explicada en la sección de cálculos teóricos). ==lcd.c:== Contiene las primitivas de control del display LCD, tal como se definieron en prácticas anteriores. Algunas de ellas han sido modificadas para evitar problemas al redibujar caracteres en el display y para hacerlas más genericas (siendo así usables en otras partes del proyecto). ==display.c:== Contiene rutinas de alto nivel para el manejo del display LCD. Usa las funciones primitivas definidas en lcd.c. También están definidas funciones que muestran barras visuales para los modos humedad y temperatura, y los cálculos necesarios para saber qué texto hay que mostrar con los nombres de velocidades y direcciones del viento. =Listado del software= ==main.c== %!include: ''main.c.html'' ------------------------------- ==timer2.c== %!include: ''timer2.c.html'' ------------------------------- ==ad.c== %!include: ''ad.c.html'' ------------------------------- ==hsi.c== %!include: ''hsi.c.html'' ------------------------------- ==lcd.c== %!include: ''Lcd.c.html'' ------------------------------- ==display.c== %!include: ''display.c.html'' ------------------------------- ==interrupts.a96== %!include: ''interrupts.a96.html'' ------------------------------- ==Lcd.c== %!include: ''Lcd.c.html'' ------------------------------- ==lcd.inc== %!include: ''lcd.inc.html'' ------------------------------- =Control de versiones concurrente:= Para coordinar y versionar el código de la práctica hemos usado un repositorio de software llamado SubVersion (http://subversion.tigris.org). Esta herramienta nos ha facilitado mucho el mantenimiento del código entre las tres personas del grupo de trabajo. == Breve introducción a Subversion: == Un sistema de control de versions (Version Control System) és una aplicació que s'utilitza per a mantenir un conjunt d'arxius en un servidor central (anomenat repositori) i permetre l'accés a ells de forma concurrent des de diversos clients. SVN (SubVersioN), com ja us podeu imaginar, és un sistema de control de versions. - És lliure. - És bastant fàcil d'usar. - És més que suficient pel que necessitarem, ja que no farem ús de branques, merges, changesets, etc. Les funcions principals (més usades) d'aquest tipus de programes són: - Facilitat per obtenir sempre els arxius més recents. - Mescla automàtica de canvis, en cas que dos desenvolupadors estiguin modificant el mateix arxiu. - Possibilitat de tornar a versions més antigues de qualsevol arxiu. - Emmagatzenament de tots els canvis amb explicacions de cadascun. En altres paraules, a nosaltres ens pot facilitar la feina perquè no haurem de preocupar-nos de quí te els arxius més recents, de comprovar quins canvis hi ha entre els fitxers de cadascú, etc. És a dir, tots els arxius finals de la pràctica estaran guardats en una única màquina, a la qual podrem accedir des de qualsevol punt per a baixar-nos el nostre codi o per a fer modificacions. =Licencia: = This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.1/es/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. [licencia.PNG]