tesis - Instituto Tecnológico de Morelia

Anuncio
INSTITUTO TECNOLOGICO Y DE ESTUDIOS SUPERIORES
DE MONTERREY
CAMPUS TOLUCA
ESTUDIO SOBRE LOS SISTEMAS DE ADQUISICIÓN DE DATOS PARA
ESTACIONES DE MONITOREO REMOTO
TESIS
QUE PARA OBTENER EL GRADO DE:
MAESTRIA EN CIENCIAS CON ESPECIALIDAD EN INGENIERIA
ELECTRÓNICA (SISTEMAS ELECTRÓNICOS)
PRESENTA:
MIGUELANGEL FRAGA AGUILAR
DIRECTOR DE TESIS:
DR. LUCIANO CHIRINOS GAMBOA
TOLUCA, EDO. DE MEXICO, MAYO DE 2006
ESTUDIO SOBRE LOS SISTEMAS DE ADQUISICIÓN DE DATOS PARA
ESTACIONES DE MONITOREO REMOTO
Examen de Grado Presentado por: Miguelangel Fraga Aguilar
Fecha: 10 de mayo de 2006
_____________________________
Dr. José Armando Herrera Corral
Presidente del Jurado Examinador
____________________________
Dr. Luciano Chirinos Gamboa
Sinodal 1
____________________________
Dr. Cesar A. Zamilpa Quiroz
Sinodal 2
Veredicto: Aprobado por Unanimidad
TOLUCA, EDO. DE MEXICO, MAYO DE 2006
Contenido
Contenido.................................................................................................................................................... i
Abstracto................................................................................................................................................... iii
1- Introducción........................................................................................................................................... 1
1.1- Antecedentes................................................................................................................................... 1
1.2- Planteamiento del problema............................................................................................................2
1.3- Justificación.................................................................................................................................... 3
1.4- Objetivos......................................................................................................................................... 3
1.5 Logros del proyecto......................................................................................................................... 4
2- Marco teórico......................................................................................................................................... 5
2.1 Introducción..................................................................................................................................... 5
2.2- Conversores analógico digital y acondicionamiento de señal........................................................ 5
2.2.1- Acondicionamiento de señal.................................................................................................... 5
2.2.1.1- Escalamiento .................................................................................................................... 5
2.2.1.2- Filtrado.............................................................................................................................. 6
2.2.2- Convertidores Analógico Digital............................................................................................. 7
2.2.2.1- Convertidor tipo aproximaciones sucesivas..................................................................... 7
2.2.2.2- Convertidor tipo Ráfaga y media Ráfaga......................................................................... 7
2.2.2.3- Convertidor por doble integración.................................................................................... 8
2.3 Técnicas para la programación de microcontroladores.................................................................... 9
2.3.1- Técnica del ciclo de por pasos (Paced Loop) ......................................................................... 9
3- Método................................................................................................................................................. 11
3.1- Introducción.................................................................................................................................. 11
3.2- Diseño del sistema........................................................................................................................ 11
3.2.1- Especificaciones de la estación meteorológica...................................................................... 11
3.2.2- Selección de los componentes............................................................................................... 12
3.2.3- Diagrama a bloques............................................................................................................... 13
3.2.4- Diagrama de flujo de la operación del sistema...................................................................... 14
3.3- Descripción del circuito ............................................................................................................... 16
3.3.1- Subsistema de alimentación................................................................................................... 16
3.3.2- Subsistema de acondicionamiento de señal........................................................................... 16
3.3.3- Medición de la temperatura interna....................................................................................... 18
3.3.4- Comunicación RS232............................................................................................................ 19
3.3.5- Conexiones del microcontrolador.......................................................................................... 20
3.4- Descripción del programa del sistema......................................................................................... 21
3.4.1- Programa de prueba............................................................................................................... 21
3.4.1.1- Subrutina principal.......................................................................................................... 21
3.4.2- Programa completo de aplicación ......................................................................................... 24
3.4.2.1- Subrutina principal.......................................................................................................... 24
3.4.2.2- Rutina de ajuste de la frecuencia del DCO..................................................................... 24
3.4.2.3- Rutina de Medición......................................................................................................... 25
3.4.2.4- Rutina de escritura a la memoria FLASH....................................................................... 26
3.4.2.5- Rutinas de la interfaz con el usuario .............................................................................. 27
3.4.2.6- Rutinas de transmisión de datos..................................................................................... 28
3.4.2.7- Rutinas para el manejo del puerto serie.......................................................................... 28
3.4.2.8- Rutinas para escribir en la pantalla LCD........................................................................ 28
3.5- Descripción del programa de recepción de datos......................................................................... 29
i
4- Resultados, conclusiones y trabajo futuro........................................................................................... 32
4.1 Introducción................................................................................................................................... 32
4.2- Resultados del programa de prueba.............................................................................................. 32
4.3- Resultados de la prueba a la intemperie. .............................................................................34
4.4- Conclusiones................................................................................................................................. 48
4.5- Trabajo Futuro.............................................................................................................................. 49
Bibliografía.............................................................................................................................................. 50
Índice de figuras....................................................................................................................................... 52
Índice de tablas......................................................................................................................................... 53
Apéndice A - Diagrama Eléctrico de la estación meteorológica............................................................. 54
Apéndice B – Circuito impreso de la estación meteorológica................................................................. 55
.................................................................................................................................................................. 56
Apéndice C – Listado del programa de la estación meteorológica.......................................................... 57
Modulo principal5.c............................................................................................................................. 57
Modulo interfaz2.c............................................................................................................................... 65
Modulo transmite.c.............................................................................................................................. 74
Modulo lcdadn2.c................................................................................................................................. 77
Modulo serie2.c.................................................................................................................................... 79
Modulo prueba6.c................................................................................................................................ 81
Modulo serie.h..................................................................................................................................... 87
Modulo lcdand.h.................................................................................................................................. 87
Modulo interfaz.h................................................................................................................................. 88
Modulo serialport.form........................................................................................................................ 88
Modulo serialport.class........................................................................................................................ 90
ii
Abstracto
Se presenta el proceso de diseño y desarrollo de una estación meteorológica de bajo costo para uso en
investigación agrícola. La estación es capaz de monitorear cinco variables a diferentes velocidades de
muestreo, almacenarlas y posteriormente transmitirlas por módem a las oficinas de los investigadores
en agricultura. Esta diseñada para reducir el consumo de energía y permitir que sea alimentada a partir
de un banco de baterías recargables y paneles solares. Se incluye un programa para la recepción de los
datos capturados en una computadora personal.
Abstract
The design and development process of a meteorological station for use on agriculture research is
presented. The station is able to log five variables at different sampling rates and to transmit the logged
data to the researcher’s office later. It has been designed to reduce power consumption and allow it to
be powered by rechargeable batteries and a solar panel. A personal computer program to receive the
logged data is also included.
iii
1- Introducción
1.1- Antecedentes
Contar con información completa y confiable es indispensable para poder tomar decisiones o para
realizar una investigación seria. Por esta razón, en las diferentes actividades humanas surge con
frecuencia la necesidad de recopilar grandes cantidades de datos. Cuando dicha recopilación debe
efectuarse en lugares remotos y durante largos periodos de tiempo, este proceso resulta muy costoso y
complicado.
Con el objeto de reducir costos y aumentar la confiabilidad de la recopilación, es frecuente utilizar
sistemas automáticos, los cuales tienen que operar en condiciones muy diferentes los sistemas de
monitoreo convencionales. Por el hecho de operar en lugares apartados, no siempre esta disponible la
infraestructura necesaria para proporcionar un suministro de energía eléctrica constante al sistema.
También, puede resultar difícil que el investigador visite con frecuencia al sistema para recoger los
datos obtenidos. Así, el sistema debe ser capaz de almacenar grandes conjuntos de datos y de ser
posible, comunicarlos a un centro de recopilación.
Dos ejemplos en donde la adquisición de datos remota surge como una necesidad se dan en la
sismología y la climatología. Para poder determinar correctamente las características de sismo o
investigar el riesgo que presenta una falla geológica se deben colocar varios sismógrafos en puntos
muy separados uno del otro. Los mejores lugares están fuera de las zonas urbanas, ya que las
vibraciones producidas por los automóviles y la maquinaria pesada afectan las mediciones de los
sismógrafos más sensibles.
En climatología se requiere colocar estaciones climatológicas en todo tipo de lugares, por ejemplo, en
la cima de las montañas para predecir el riesgo de avalanchas o en las llanuras desérticas para
monitorear la formación de tornados. Los datos obtenidos por estas estaciones son reunidos para formar
un mapa con la distribución de las diversas variables climáticas en el área geográfica de interés, el cual
se utiliza para que los especialistas elaboren sus pronósticos. También en zonas de cultivo con
superficie extensa, él poder conocer el microclima local permite a los agrónomos sugerir el mejor tipo
de cultivo para la región y también indicar cuando es el mejor momento para irrigar o aplicar un
pesticida sin que las lluvias lo dispersen y reduzcan su efectividad.
1
1.2- Planteamiento del problema
México, es un país que se encuentra en el cinturón de fuego, una zona sísmica muy activa. También
cuenta con un amplio territorio y una gran diversidad de climas. Por lo anterior, la investigación en
sismología y meteorología son claves para prevenir desastres y para lograr un desarrollo óptimo de la
agricultura del país. Sin embargo, en México no se fabrican equipos que sean útiles para la
recolección automatizada de datos, tales como sismógrafos y estaciones meteorológicas. Esto limita la
capacidad de los investigadores de obtener información de campo de manera continua y amplia,
también aumenta la dependencia tecnológica. Desarrollar la capacidad de diseñar y construir equipos
para el registro automático de variables ambientales a un bajo costo permitiría que se usaran más
ampliamente y que la información obtenida sirviera para que se tomaran decisiones más informadas y
acertadas.
En particular, la Fundación PRODUCE de Michoacán, una asociación de productores agrícolas del
valle de Apatzingan, se encuentra en el proceso de desarrollar técnicas de cultivo que utilizan
información del microclima local para se apliquen a los cultivos menores cantidades de pesticidas y
fertilizantes, evitando el desperdicio y determinando el momento en que su aplicación va a tener un
mejor efecto. De llegarse a aplicar estas técnicas de forma masiva en todo el valle de Apatzingan, estas
tendrían un gran impacto ecológico, económico y social, al ayudar a los a obtener mejores cosechas con
menos agroquímicos.
Sin embargo, para que estas técnicas puedan aplicarse masivamente en la producción es necesario
contar con estaciones meteorológicas de bajo costo que puedan distribuirse entre los productores y que
les permitan obtener la información del microclima local como para que los expertos en agricultura (o
un sistema experto ejecutándose en la computadora que recopila la información meteorológica y
entrenado para dicho propósito) pueda decirles en que momento es conveniente aplicar los
agroquímicos y en que cantidades.
Por esta razón, la fundación se puso en contacto con el autor de este documento y solicito que
cooperáramos en el desarrollo de una estación meteorológica que fuera apta para este fin. El primer
paso en este proceso es la construcción de un primer prototipo que pueda usado por los investigadores
de la fundación para mejorar y validar las técnicas de cultivo propuestas. Con base en este prototipo se
desarrollara una versión mejorada que se probaría en un programa piloto con un grupo selecto de
productores para comprobar que cumple con sus necesidades y en caso de ser necesario mejorar algún
aspecto del funcionamiento de la estación, considerarlo en el diseño del prototipo final que se pudiera
distribuir entre los productores.
2
1.3- Justificación
El poder diseñar equipo de adquisición de datos en el país, permitirá, entre otras ventajas, ahorrar en
gastos de importación, reducir el precio final al usuario del equipo y ampliar su utilización, así como
contar con equipo adaptado especialmente a las necesidades de los investigadores y productores
nacionales. De llegar a desarrollarse un equipo adecuado para su uso en la producción agrícola, tendría
un gran impacto social y económico al aumentar la productividad de los campesinos.
El amplio desarrollo de la tecnología de microprocesadores y microcontroladores, donde ha habido
grandes avances en capacidad de memoria, integración de periféricos y disminución en el consumo de
energía, permite el diseño de equipos más económicos y con un menor número de partes de lo que era
posible en el pasado.
En el mercado internacional existen varios modelos de estaciones capaces de realizar este trabajo, pero
miden una cantidad de variables mayor a la necesaria para poder aplicar las técnicas que consideran el
microclima local y por lo tanto su costo es más elevado. Ejemplos de estaciones comerciales son la
Lacrosse 2510 y la Davis Vantage Pro2. Ambas miden las variables medidas por la estación presentada
en este trabajo y además incluyen un barómetro, un pluviómetro, y enlace por RF con rango máximo
entre 60 y 120m. La estación Lacrosse 2510 tiene un costo de $699USD y la Davis Vantage Pro2
cuesta $599 USD, pero requiere de accesorios adicionales con un costo total de $176 USD extras para
poder transmitir los datos a una PC. Con esto el precio de ambas estaciones seria muy superior al de las
partes del prototipo descrito en el presente trabajo.
1.4- Objetivos
•
Desarrollar Un sistema electrónico de monitoreo para una estación meteorológica que cumpla
con los requerimientos de investigadores en agricultura del estado de Michoacán.
•
Que la estación desarrollada cuente con la capacidad de almacenar los valores capturados por
un periodo largo de tiempo y de comunicarlos a los investigadores.
•
Que sea de bajo costo para que pueda ser la base para una versión mejorada que pueda
distribuirse entre los productores y que les permita tomar decisiones sobre sus cultivos de forma
más informada y objetiva.
•
Documentar el proceso de diseño de la estación para que pueda servir como un ejemplo y una
guía introductoria de cómo desarrollar equipos de monitoreo remoto similares a esta.
3
1.5 Logros del proyecto
Se culmino el desarrollo de un primer prototipo de la estación meteorológica que pude comenzar a
utilizarse en laboratorios de investigación en agronomía. Se valido el correcto funcionamiento de la
estación tanto en la medición de las variables como en el almacenamiento y transmisión.
El prototipo fue evaluado por los investigadores en agricultura de la fundación PRODUCE de
Michoacán y en su opinión el prototipo puede usarse para la investigación de nuevas técnicas de riego
y fumigado para las cuales es indispensable contar con información muy detallada sobre el microclima
local.
Además este prototipo tiene el potencial de ser la base para el desarrollo de una versión con una
interfaz de usuario simplificada, comunicación vía RF y menor costo que pueda utilizarse para que los
productores apliquen estas técnicas en sus cultivos.
4
2- Marco teórico
2.1 Introducción
En este capitulo se presentan una breve descripción los conocimientos teóricos utilizados para el
desarrollo de la estación meteorológica.
2.2- Conversores analógico digital y acondicionamiento de señal
2.2.1- Acondicionamiento de señal
2.2.1.1- Escalamiento
Una de las tareas más frecuentes en el proceso de acondicionamiento de señal es el escalado de la señal
de un sensor que entrega una salida en voltaje. El escalamiento consiste en llevar la señal del rango de
voltaje entregado por el sensor al rango de voltaje que requiere la entrada del convertidor analógico
digital. Este proceso normalmente se realiza por medio de algún amplificador sumador. La función de
mapeo de un rango de voltaje a otro usualmente es una línea recta, de la forma Vo = m * Vi + b. El
parámetro m correspondería con la ganancia del amplificador y el parámetro b con un voltaje de
desplazamiento o polarización que el amplificador suma al voltaje de entrada.
La configuración del amplificador dependerá de varios factores, principalmente de si el voltaje de
entrada es unipolar o diferencial de si se dispone de fuentes de alimentación simétrica. Cuando la
entrada sea unipolar se usara un simple amplificador sumador no inversor como el mostrado en al
figura 2.1. Si es diferencial deberá usarse un amplificador sumador diferencial como el mostrado en la
figura 2.2
Figura 2.1 Amplificador sumador no inversor
Figura 2.2 Amplificador sumador con entrada diferencial
5
El diseño de cualquiera de estos dos amplificadores puede lograrse de una manera relativamente
simple, logrando cualquier combinación de ganancia y desplazamiento de voltaje. Definamos Ra=R1||
R2, Rb=R3||R4||R5. Entonces las ganancias para las diferentes entradas serán:
K(vin-)=-R2/R1
K(vin+)=(Rb/Ra)(R2/R4)
K(voff)=(Rb/Ra)(R2/R5)
La diferencia principal entre los dos amplificadores seria que el voltaje de entrada Vin- es cero en el
amplificador sumador. Pueden usarse las resistencias R1, R2, R4 y R5 para establecer la ganancia y el
voltaje de desplazamiento. Después puede usarse R3 para hacer que Ra = Rb y que las ganancias
positivas coincidan con las deseadas al ser Ra/Rb=1.
Cuando sea necesario alimentar al amplificador operacional con una sola fuente, como ocurre
normalmente cuando se alimenta con baterías, se debe tener mucho cuidado de que el voltaje de salida
nunca salga del rango que puede entregar el amplificador. Por ejemplo, si se alimenta al amplificador
con una fuente de 5V, Se debe cuidar que el voltaje de salida siempre sea positivo y que no exceda los
5 V. Además se deben usar amplificadores de diseñados para trabajar con este tipo de alimentación,
que entre otras características pueden entregar voltajes de salida muy cercanos al de alimentación y una
razón de rechazo de modo común muy alta. Un ejemplo de este tipo de amplificador es el TLV2474 de
TI.
Al momento de diseñar el amplificador, también debe considerarse la impedancia de salida del sensor,
ya que la impedancia de entrada del amplificador debe ser mayor que la del sensor para evitar que el
efecto de carga degrade la medición. En caso de que se tenga un sensor con muy alta impedancia de
salida, lo mas conveniente es colocar un seguidor de voltaje (o dos si la salida es diferencial) antes del
amplificador sumador.
Si la magnitud del la ganancia que se requiere es mayor que diez, puede ser conveniente incluir un
amplificador de instrumentación como etapa de entrada para proporcionar una buena ganancia a la
señal de entrada antes de sumar el voltaje de desplazamiento que se requiera.
2.2.1.2- Filtrado
El criterio más importante para determinar que tipo de filtrado debe realizarse a una señal es conocer
sus características, en particular el ancho de banda de la señal que desea muestrearse. Por el teorema
del muestreo, sabemos que debemos muestrear una señal a por lo menos una frecuencia del doble del
componente de frecuencia más alta de la señal o se perderá información en la conversión. Esta
frecuencia es conocida como la frecuencia de Nyquist. También es necesario asegurarse de que no
lleguen al convertidor analógico a digital componentes de frecuencia más alta que la máxima deseada y
para esto es común colocar un filtro pasa bajos entre la fuente de señal y el convertidor AD. Este filtro
puede ser desde un simple filtro RC pasivo de primer orden hasta filtros activos de orden superior.
Para frecuencias bajas y ambientes sin mucho ruido un filtro RC es suficiente. Sin embargo, en la
mayoría de los casos la mejor opción es un filtro activo de segundo orden o superior. La configuración
Sallen-Key es particularmente útil. Esta configuración y otras son explicadas detalladamente en
(Mallik1996), (Rashid 2000) y (Wait 1992).
6
Una alternativa a un filtro activo de orden alto, expuesta en (Oppenheim 2000), es muestrear a una
frecuencia más alta que la de Nyquist, aplicar un filtro de orden alto digital y después diezmar las
muestras para reducir la frecuencia de muestreo al valor deseado.
2.2.2- Convertidores Analógico Digital
Los convertidores de analógico a digital (ADC) son dispositivos fundamentales para el funcionamiento
de cualquier sistema de medición, ya que se encargan de convertir la magnitud de una variable
analógica a una representación numérica que puede ser usada por el controlador del sistema de
medición. De su buen funcionamiento depende la exactitud y precisión de la medición.
Los parámetros más importantes a tomar en cuenta al seleccionar un ADC son: el rango a plena escala
(FSR), es el conjunto de valores de la variable de entrada que puede aceptar; la resolución, es decir, la
más pequeña diferencia entre dos valores de entrada que puede distinguir y que normalmente se
relaciona con el número de bits del convertidor (n) por FSR/(2^n-1); el formato de la salida; la
velocidad de conversión y finalmente el precio.
Es muy común que los microcontroladores modernos incluyan un convertidor analógico digital como
parte de sus periféricos internos, que debe ser suficiente para muchas aplicaciones. Sin embargo, estos
convertidores suelen estar limitados particularmente en resolución (8 o 10 bits) y velocidad de
conversión (máximo en aproximadamente 200,000 muestras por segundo) para las aplicaciones más
demandantes, por lo que debe considerarse conectar un convertidor externo de más alto precio y
desempeño al microcontrolador, o buscar otro microcontrolador que tenga un convertidor de mejores
características. Conocer los tipos más comunes de convertidores y que se puede esperar de ellos será de
mucha ayuda al momento de hacer la selección.
2.2.2.1- Convertidor tipo aproximaciones sucesivas
Este tipo de topología es muy usada debido a que presenta varias ventajas: un tiempo de conversión
fijo a un precio razonable. Es el tipo más comúnmente usado para los convertidores internos de los
microcontroladores. El diagrama a bloques de este tipo de convertidores de muestra a continuación.
Figura 2.3 Convertidor AD de aproximaciones sucesivas
El bloque marcado como DAC es un convertidor de digital a analógico que transforma la salida digital
en un valor analógico que se compara con la variable de entrada. La unidad de control y el registro de
aproximaciones sucesivas (SAR) usan el resultado de esta comparación para determinar el valor de un
BIT de la salida por ciclo de reloj.
2.2.2.2- Convertidor tipo Ráfaga y media Ráfaga
7
El objetivo del convertidor tipo ráfaga o flash es obtener el resultado de la conversión lo más
rápidamente posible. Por esta razón, emplea un gran número de comparadores que comparan el voltaje
de entrada con un voltaje de referencia generado por un divisor de tensión. Cada una de estos voltajes
corresponde con el valor de entrada que produciría una salida diferente. La salida de los comparadores
se codifica por medio de un circuito combinacional, por lo que ni siquiera es necesaria una señal de
reloj para la operación de este convertidor. El tiempo de conversión es determinado únicamente por el
tiempo de respuesta de los comparadores y el tiempo de retardo del codificador.
Figura 2.4 Convertidor AD tipo ráfaga o flash de tres bits
El principal problema de este tipo de convertidor es que la cantidad de comparadores que se necesitan
crece exponencialmente con el número de bits del convertidor, lo que hace que el precio se dispare. Por
esta razón su uso se limita a aplicaciones como la digitalización de video e instrumentos de medición
de alta frecuencia donde el costo de estos convertidores se justifica.
2.2.2.3- Convertidor por doble integración
Los convertidores de doble integración son muy económicos debido a que no requieren de más
componentes complicados que un integrador, un comparador y un voltaje de referencia. Es el tipo de
convertidor más comúnmente usado en los multimetros digitales debido a su bajo precio y buena
resolución, precisión y exactitud. En algunos microcontroladores de bajo costo se incluyen la referencia
de voltaje y el comparador para poder crear un convertidor de este tipo usando un integrador externo y
simulando la unidad de control y el contador por software.
8
Figura 2.5 Convertidor AD de doble integración
Al iniciar el proceso de conversión, el contador se pone a cero y se comienza a cargar al condensador
del integrador con el voltaje de entrada, hasta que el contador alcanza su cuenta máxima.
Posteriormente se descarga al condensador aplicando un voltaje de referencia negativo mayor que el
voltaje de entrada. El tiempo que tarde en descargarse será proporcional a la relación entre el voltaje de
entrada y el de referencia, por lo que el valor del contador en el momento determinarse la descarga será
proporcional al voltaje de entrada.
La principal limitante de estos convertidores es que son muy lentos, teniendo tiempos de conversión de
cientos de milisegundos a varios segundos. La ventaja es que es relativamente simple incrementar la
resolución del convertidor aumentando el tamaño del contador, en especial en implementaciones por
software.
2.3 Técnicas para la programación de microcontroladores.
2.3.1- Técnica del ciclo de por pasos (Paced Loop)
En sistemas basados microcontroladores pequeños cuentan con muy pocos recursos para la
implementación de las aplicaciones, sin embargo, la mayoría de las aplicaciones requiere la realización
de múltiples tareas de forma simultánea. Utilizar un sistema operativo multitarea completo es una
opción que no siempre es factible, debido a que el CPU no cuenta con los recursos necesarios para su
ejecución.
La alternativa para aplicaciones simples es utilizar una técnica que permite simular el funcionamiento
de multitareas. Existen varias técnicas para lograr esto, una de las más comúnmente usadas es el ciclo
por pasos. La estructura principal del programa (Figura 2.6) consiste en una etapa de inicialización y un
ciclo principal infinito. El ciclo principal es infinito debido a que el programa de aplicación no puede
terminar por que no existe un sistema operativo que tome el control del procesador, además de que la
naturaleza misma de las aplicaciones requieren que el programa continué ejecutándose mientras el
sistema este energizado.
9
Inicialización
Ciclo Principal
Figura 2.6 Estructura principal del programa
El ciclo principal usualmente comienza esperando a que se presente un evento del temporizador que
asegure que cada pasada por el ciclo se ejecute después de un intervalo de tiempo predefinido. Lo
anterior simplifica la implementación de retardos con solamente contar el número de pasadas por el
ciclo principal. También es común que al terminar una pasada por el ciclo el procesador entre en un
estado de ahorro de energía del que saldrá al presentarse el evento del temporizador. En medio del
ciclo, se llama a una serie de funciones o subrutinas, cada una de las cuales implementa una función
tarea en particular.
Las funciones de tarea deben estar diseñadas para hacer una pequeña parte de la tarea y regresar en una
fracción del intervalo de tiempo entre una pasada y la siguiente. Por esta razón, cada función debe
encargarse de conservar en variables globales o estáticas toda la información relacionada con el estado
de la tarea. Una manera muy conveniente de realizar esto es dividiendo la tarea en varas etapas y
almacenar el número de etapa en una variable. Al entrar en la función se revisa el número de etapa por
medio de una estructura switch-case y se realizan las acciones correspondientes a dicha etapa. Para
pasar a la siguiente etapa y que las acciones correspondientes se ejecuten en la siguiente llamada a la
función de tarea, lo único que debe hacerse es incrementar el contenido de la variable donde se
almacena el número de etapa. En muchos casos se debe esperar a que se cumpla alguna condición o se
espera a que se presente algún evento antes de pasar a la siguiente etapa. En estos casos solo se revisa
la condición y si se cumple se incrementa la variable. De esta manera, el formato general de una
función de tarea queda como se muestra en el siguiente listado:
void tarea(void)
{
Static int etapa=0;
switch etapa
{
case 0: acciones etapa 0;
if (condición etapa 0) etapa++;
...
case N: acciones etapa N;
if (condición etapa 0) etapa=0;
}
}
Esta técnica es utilizada para realizar las tareas de medición, transmisión e interfaz de usuario de forma
simultánea en la estación.
10
3- Método
3.1- Introducción
En esta sección se describe el desarrollo de una estación meteorológica para uso agrícola con el objeto
de que sirva como ejemplo del proceso de diseño de un sistema de adquisición de datos remoto.
3.2- Diseño del sistema.
3.2.1- Especificaciones de la estación meteorológica
El primer paso en el proceso de diseño de cualquier equipo es el establecer un conjunto de
especificaciones que deben cumplirse. Estas deben establecerse con la ayuda de un especialista en el
área en que se va utilizar el instrumento con el fin de asegurarse de que realmente sea útil. En este caso
se consulto al Ing. Francisco Javier Maldonado Arceo de la Fundación Produce de Michoacán. Se
determinó que el conjunto de variables mostrado en la tabla siguiente seria suficiente para la toma de
decisiones en agricultura.
Variable a medir
Frecuencia
Rango
Temperatura interna
Una muestra cada 10 min. o cada hora
-50°C a 100°C
Temperatura externa
Una muestra cada 10 min. o cada hora
-50°C a 100°C
Humedad relativa
Una muestra cada 10 min. o cada hora
0 a 100%
Velocidad del viento
Una muestra cada 10 min. o cada hora
0 a 300 Km/Hr
Dirección del viento
Una muestra cada 10 min. o cada hora
0 a 360°
Tabla 3.1 Variables a medir por la estación meteorológica
La frecuencia de muestreo de una muestra por hora es suficiente en las aplicaciones relacionadas con la
producción, pero en algunas aplicaciones de investigación se requeriría una frecuencia de muestreo más
alta, aunque no de más de una medición cada 10 minutos. La frecuencia de muestreo más baja tiene la
ventaja de que permite que la misma cantidad de memoria almacene los datos correspondientes a un
periodo de tiempo más grande. Se decidió ofrecer al usuario final la opción de escoger entre estas dos
frecuencias de muestreo en un menú de configuración, para hacer a la estación más versátil.
Dado el rango de las variables a medir, se determino que un tamaño de palabra de 16 bits basta para
almacenar una muestra de cada una de las cinco variables, así como la hora en que se tomo
compactada, lo que da un total de 12 bytes por muestra. Se desea que la estación sea capaz de
almacenar los datos capturados durante 30 días. Una vez que se conoce la frecuencia de muestreo, el
tamaño de cada muestra y por cuanto tiempo deben almacenarse, se puede especificar cuanta memoria
será requerida en el sistema.
Memoria requerida = 12 bytes/muestra*6 muestras/hora*24*30Horas=51, 840 Bytes
Esta cantidad de memoria esta disponible internamente en la muchos microcontroladores modernos.
11
Además, como la frecuencia de muestreo es muy baja, el tiempo que toma escribir a la memoria Flash
(que es relativamente lenta comparada con otros tipos de memorias), no representa un problema.
3.2.2- Selección de los componentes
Ya que se tienen las especificaciones básicas que debe cumplir la estación meteorológica, se pueden
escoger los componentes que la conformarán, buscando que tengan un bajo costo y consumo de
energía, integren la mayor cantidad de funciones y que sea posible obtener herramientas de desarrollo
para utilizarlos.
Se utiliza un microcontrolador TI MSP430F149 como pieza central de la estación. La principal razón
para escoger este microcontrolador fue que es el que presenta un menor consumo de energía. El ahorro
de energía permite que dos de los elementos más costosos del sistema, los paneles solares y las baterías
sean más pequeños y menos costosos, teniendo un impacto significativo en la reducción del precio final
del sistema completo.
Otras características del MSP430 que fueron determinantes en su elección son el convertidor analógico
digital que tiene una resolución de 12 bits, superior a la de 10 bits que se encuentra en otros
microcontroladores. Además contiene un sensor de temperatura integrado que permite realizar la
temperatura interna sin añadir un sensor extra. También cuenta con 60K bytes de memoria Flash,
suficientes para almacenar los datos capturados y el código del programa.
Para escoger el microcontrolador se consideraron otras opciones como el 68HS12DP26 de Freescale
(antes Motorola), pero aunque este dispositivo posee más recursos y es más rápido que el MSP430, su
consumo de energía es mucho mayor, por lo que fue descartado.
Los siguientes compones que se seleccionaron fueron los sensores. Para medir la temperatura interna,
se escogió el LM35, por cubrir el rango completo en que se desea medir y estar ampliamente disponible
en el mercado a precio muy accesible. Se consideraron otros sensores como el AD22103, el ADT7816
y el TMP06 , pero, o bien no cubrían el rango deseado completo, requieren voltajes de alimentación
más altos o el encapsulado es de montaje superficial, lo que complica mucho el montaje en el exterior
del gabinete de la estación. La salida de este sensor tuvo que ser acondicionada para que pudiera
conectarse al convertidor analógico a digital del microcontrolador, para lo que se uso un amplificador
operacional TLV2444. Se selecciono este amplificador por que puede funcionar con una sola fuente de
voltaje, tiene cuatro amplificadores operacionales en su interior y un consumo de energía muy bajo, en
el orden de los microamperes.
Para la medición de humedad relativa se utilizo al IH-3610-1 de Honeywell. Este sensor se alimenta
con una sola fuente de 5 V y entrega la salida directamente en voltaje. Otros sensores de humedad
capacitivos requieren ser excitados por un oscilador sinusoidal y formar parte de un circuito tipo
puente, o forma parte de un oscilador RC y que se mida la frecuencia de salida del mismo, lo que
aumenta el número de partes, el costo y la complejidad del el sistema. Además de las ventajas ya
mencionadas, el IH-3610-1 tiene un precio similar a los demás sensores de humedad y puede
conseguirse en el país, por lo que fue la opción natural.
12
3.2.3- Diagrama a bloques
Acondicionador
de señal
ADC1
Veleta
MSP430F149
Baterias
y paneles solares
ADC0
Alimentación
sensores
P4.0
ADC2
Humedad
Alimentación
LCD
P4.0
TMR0
Anemometro
Alimentación
microcontrolador
LCD y teclado
P4,P5 P3.2-5
y P1
Sensor de
Temperatura
LM35
Modem
Figura 3.1 – Diagrama a bloques de la estación meteorológica
La estación meteorológica consta de un microcontrolador, una serie de sensores, una pantalla LCD, un
teclado y un sistema de alimentación. El microcontrolador se encarga de aceptar los comandos del
usuario, llevar la cuenta del tiempo, determinar cuando se debe hacer una medición, activar a los
sensores, realizar la medición, almacenar el resultado y comunicarse con una PC para transmitirle los
datos obtenidos. Cada uno de los sensores se conecta de alguna forma al microcontrolador,
dependiendo del tipo de salida que entregue. La mayoría tiene una salida en voltaje y se conecta a un
canal del convertidor analógico a digital. Solo el anemómetro entrega su salida en forma de una señal
digital que se conecta al temporizador para poder medir su frecuencia.
En el subsistema de alimentación se encuentran tres reguladores de voltaje, dos de ellos cuentan con
una entrada de habilitación que permite que el microcontrolador los active únicamente cuando es
necesario, disminuyendo el consumo de energía. Uno de estos alimenta a la pantalla LCD y la activa
solo cuando se reciben ordenes del usuario y el resto del tiempo le corta la alimentación, disminuyendo
el consumo de corriente en 1.2 mA; el otro alimenta a los sensores y a la etapa de acondicionamiento
de señal. Como la toma de una medición de todas las variables solo requiere de unos 3 segundos como
máximo y debe realizarse a lo mucho cada 10 minutos, el tenerlos desconectados la mayor parte del
tiempo también ahorra energía. El regulador que esta permanentemente activado es el que alimenta al
microcontrolador.
13
3.2.4- Diagrama de flujo de la operación del sistema
Este diagrama de flujo describe a grandes rasgos la operación general del sistema y sirve como base
para posteriormente escribir el software del sistema. En este se describe la actividad principal del
sistema que es la medición y almacenamiento de las variables. Sin embargo, en él se dejan fuera
muchos detalles como el hecho de que el usuario debe ser capaz de acceder a la interfaz de
configuración mientras que se están tomando las mediciones, para realizar consultas o dar la orden de
iniciar la transmisión de los datos ya capturados. Además, la transmisión de las datos capturados debe
hacerse al mismo tiempo que la captura, por lo que debe usarse algún esquema para que se puedan
realizar todas la tareas en forma simultánea, así como varias rutinas de atención de interrupciones para
responder rápidamente a los eventos de hardware que así lo requieren.
14
Configuración de
la fecha, hora y
la velocidad de muestreo
por el usuario
Programar la toma de
la siguiente muestra
¿Ya es hora
de tomar la
siguiente
muestra?
Entrar a modo de
ahorro de energía
Encender la fuente
de los sensores y
dejar que se estabilice
Realizar la medición y
almacenarla en
la memoria Flash
Figura 3.2 Diagrama de flujo del proceso de medición y almacenamiento de la estación
meteorológica.
15
3.3- Descripción del circuito
3.3.1- Subsistema de alimentación
Figura 3.3 - Diagrama eléctrico del subsistema de alimentación.
En la figura se puede observar la conexión de los los tres reguladores de baja caída de voltaje que se
utilizaron en la estación meteorológica. El regulador TPS76933 con salida a 3.3V alimenta
directamente al microcontrolador y se encuentra permanentemente activado. Los TPS76950 con salida
de 5V alimentan a los sensores y a la pantalla LCD, los cuales solo se necesitan durante pequeños
periodos de tiempo y pueden desconectarse el resto del tiempo para disminuir la corriente consumida.
El microcontrolador puede encender los reguladores poniendo el bit cero o uno del puerto cuatro en
alto en el momento en que se requiera.
Este tipo de reguladores de baja caída de voltaje puede mantener el voltaje de salida regulado aunque el
voltaje de entrada, proveniente de las baterías, este solamente unos cuantos milivoltios por encima del
de salida, extendiendo el tiempo por el que se puede operar sin recargar las baterías.
3.3.2- Subsistema de acondicionamiento de señal
En este subsistema se acondicionan las señales para poder aplicarlas al conversor analógico digital. El
primer sensor que requiere acondicionamiento es el sensor de temperatura externa LM35. Este circuito
integrado entrega un voltaje de salida proporcional a la temperatura (10mv/°C) el cual puede ser
positivo o negativo (de -0.5 a 1.0V). Para poderlo alimentar con una sola fuente de alimentación, el
fabricante recomienda conectarlo en serie con dos diodos 1N4148 para que la terminal de referencia
quede a un voltaje intermedio y el voltaje de salida pueda ser negativo con respecto a la referencia,
aunque sea positivo con respecto a tierra.
Este voltaje de salida se aplica a un amplificador diferencial que lo amplifica y le suma un voltaje
constante para que quede en el rango de 0 a 2.5v que requiere el conversor A/D. A continuación se
presenta el diseño del amplificador. La configuración de amplificador que se va utilizar es la siguiente.
16
Figura 3.4 Amplificador diferencial con desplazamiento.
Las ecuaciones que rigen el circuito son:
Vo K Vin Vin
K Vin Vin
K Voff Voff
K Vin
R 2 R1 , K Vin
Rb R a R 2 R4 , K Voff
R a R1 R2 , R a R3 R 4 R 5
Rb R a R2 R5
El sensor entrega a su salida una señal diferencial entre –0.5V y +1.5V, correspondientes al rango de
temperatura de –50°C a 150° C en que trabaja el sensor. Se desea llevar este voltaje de salida al rango
de 0.33V a 2.33V para que la señal correspondiente a cualquier temperatura en el rango del sensor
pueda ser convertida por el ADC del MSP430 usando una referencia interna de 2.5V. La conversión se
puede lograr con un amplificador con una ganancia de uno y un voltaje de desplazamiento de 0.833V.
Se desea generar el voltaje de desplazamiento a partir de la referencia de 2.5V. Para lograr esto, se
debe tener K(vin-)=-1, K(vin+)=1, K(voff)=0.833V/2.5V=1/3.
Se escoge R2=100K para mantener una impedancia alta y un consumo de corriente bajo. Como K(vin-)
=-1, K(vin+)=1, K(voff)=0.4; R1= R2/K(vin-)=100K/1=100K. Se supone que Ra/Rb=1 y entonces
R4=R2/K(vin+)=100K/1=100K, R5=R2/K(Voff)=100K/(1/3)=300K. Escogiendo una combinación de
valores comerciales para R5, se pueden usar dos resistencias de 150K conectadas en serie. Con estos
valores se puede calcular Ra=R1||R2=50K. Así, R3 debe escogerse de forma que Rb=R3||R4||
R5=Ra=50K. Despejando R3=1/(1/Ra-(1/R4+1/R5))=150k, la cual es un valor comercial.
Figura 3.5 Diagrama del circuito de acondicionamiento para el sensor de temperatura
17
Figura 3.6 Diagrama eléctrico de circuito de acondicionamiento del sensor de humedad relativa
Para el sensor de humedad, el acondicionamiento fue más simple, debido al rango de salida del sensor
entre 0.92 y 4.09V, y por el hecho de que el voltaje de salida esta referido a tierra. El circuito consiste
de un amplificador seguidor, que evita que se produzca un efecto de carga significativo en el sensor, y
un divisor de voltaje para llevar el voltaje de salida del sensor a un rango que puede aplicarse al
conversor A/D de microcontrolador. El divisor tiene un efecto de atenuación de 0.65 y rango de voltaje
aplicado al convertidor es de 0.6 a 2.65V. Para realizar la conversión de este voltaje se utiliza el voltaje
de referencia de 3.3V. Los errores debidos a la tolerancia de las resistencias utilizadas se compensan
ajustando los coeficientes de la formula de conversión del resultado de la conversión a porcentaje de
humedad relativa.
Figura 3.7 Diagrama eléctrico de circuito de acondicionamiento del anemómetro y la veleta.
La veleta esta acoplada mecánicamente a un potenciómetro de 22KΩsin tope, de manera que el voltaje
en el cursor del potenciómetro es proporcional al ángulo de giro de la veleta. El potenciómetro esta
conectado a JP3. La resistencia R11, reduce el voltaje rango de salida de 0 a 5V a un rango de 0 a
3.24V que puede aplicarse al ADC directamente.
El eje del anemómetro tiene un imán que hace que se cierre un interruptor de lengüetas magnético
sellado al vacío una vez por revolución. Este interruptor se conecta a JP4. El divisor de voltaje formado
por R7 y R8 hacen que se aplique 3.2V a la entrada de captura del temporizador en lugar de los 5 V de
la fuente, así como limita la corriente que circula por el interruptor cuando este se cierra. Los
condensadores C1 y C2 reducen el ruido inducido en los cables de conexión, que tiene tres metros de
largo.
3.3.3- Medición de la temperatura interna
Para la medición de la temperatura interna, se uso el sensor de temperatura integrado del
microcontrolador. Este sensor forma parte del modulo del convertidor analógico digital. Para utilizar
este sensor solo debe seleccionarse el canal número 10 del convertidor (el cual esta conectado
internamente al sensor) y usar un tiempo de muestreo de 30 microsegundos o más. Esto
automáticamente enciende la referencia interna de 2.5V que alimenta al sensor. La siguiente gráfica
muestra la relación entre la temperatura y voltaje de salida del sensor. Como puede observarse, la
relación es lineal y corresponde a la ecuación Vtemp =0.00355T+0.986, donde Vtemp es el voltaje de
salida en volts y T es la temperatura en grados centígrados.
18
Figura 3.8 Curva Temperatura contra voltaje de salida de sensor interno del MSP430
3.3.4- Comunicación RS232
Figura 3.9 Circuito de conversión de niveles lógicos a RS232
Para que el microcontrolador pueda conectarse con un modem o directamente con una PC los niveles
de salida del puerto serie ( 0 -> 0V, 1 -> 3.3V) del microcontrolador deben convertirse a niveles RS232
(0 -> +12V, 1 -> -12V). El circuito integrado escogido para realizar esta función es el MAX3223E, él
cual tiene la ventaja de que puede ser alimentado con voltajes entre 3.0V 5.5V. A partir de esta única
fuente de alimentación se generan los voltajes positivos y negativos requeridos por el estándar RS232.
Otra ventaja que tiene es que cuenta con un apagado automático del generador de los voltajes RS232 en
cuanto se detecta que la línea RS232 esta desconectada, reduciendo el consumo de energía de
aproximadamente un mili Amper a alrededor de un micro Ampere. El apagado de del convertidor de
niveles también puede hacerse manualmente por medio de la línea FORCEOFF, permitiendo ahorrar
19
energía en periodos de tiempo largos en los que no se va a realizar ninguna comunicación.
3.3.5- Conexiones del microcontrolador
Figura 3.10 Conexiones del microcontrolador
Además de las conexiones con otros subsistemas de la estación meteorológica, el microcontrolador
requiere de algunos elementos auxiliares para funcionar adecuadamente. El voltaje de alimentación del
microcontrolador es la salida del regulador TPS76933 (IC3) comentado en la sección sobre el
subsistema de alimentación. Los condensadores de desacoplo C14 a C17 sirven para eliminar el rizo en
el voltaje de alimentación producido por la conmutación interna del microcontrolador. El cristal Q1
proporciona una referencia de tiempo estable para la operación del microcontrolador. La señal de salida
del oscilador del que forma parte este cristal es usada para llevar un reloj de tiempo real, para medir la
velocidad a la que gira el anemómetro y para controlar la frecuencia del oscilador RC interno de alta
frecuencia que utiliza el CPU y el puerto serie.
20
El conector JP1 sirve para conectar la interfase JTAG utilizada para programar al microcontrolador y
durante la depuración de los programas. La presencia de este conector es muy importante, ya que
permite programar al microcontrolador cuando ya esta conectado en el circuito de aplicación y si es
necesario se puede cambiar el programa sin tener que retirar el microcontrolador de la aplicación.
También posibilita observar el contenido de la memoria y de los registros durante la ejecución normal
del programa, facilitando él encontrar errores en la programación. La resistencia R8 y el condensador
C3 se encargan de reiniciar el microcontrolador al conectarse la alimentación a la estación.
El conector JP6 se permite tener acceso al puerto 1 desde el exterior del modulo principal de la estación
meteorológica. A él se conectan cuatro interruptores tipo push-button con resistencias jalando hacia
arriba, las cuales permiten al usuario manejar a la estación a través del sistema de menús de la interfase
de usuario.
Las entradas analógicas entran al convertidor analógico digital por medio de las terminales P6.0 a P6.2.
El puerto P5 y las líneas P4.5 a P4.7 se conectan a la pantalla LCD. Finalmente las terminales P3.0 a
P3.5 van a la interfase RS232.
3.4- Descripción del programa del sistema.
Como este sistema se basa en un microcontrolador y este realiza muchas de las tareas, la programación
del mismo constituye un gran porcentaje del trabajo de diseño. Durante el desarrollo, en realidad fue
necesario escribir dos programas diferentes. El primero se utilizo para probar el circuito, y lo único que
hacia era tomar las mediciones, mostrarlas en la pantalla LCD y transmitirlas a través del puerto serie
para poder observar los resultados en un programa emulador de terminal. El segundo es la aplicación
completa en si, que incluye una interfaz de usuario y puede tomar las mediciones, comunicar los
resultados y atender al usuario al mismo tiempo. También se escribió un programa para la PC en
lenguaje Basic (Gambas) para recibir los datos transmitidos por la estación a la PC y guardarlos en un
archivo. En los siguientes párrafos se explica el funcionamiento de las partes más importantes de estos
programas.
3.4.1- Programa de prueba
El objetivo de este programa es probar que el circuito funcione correctamente; asegurarse de que el
código que accede a los periféricos del microcontrolador, así como algunas librerías utilitarias,
estuvieran libres de errores; y finalmente, tener un acceso continuo a los resultados de la medición para
poder compararlos con otros instrumentos
Este programa se divide en tres módulos: prueba6.c, lcd2.c y serie2.c. El listado completo de estos
módulos se encuentra en uno de los apéndices. A continuación se describen las rutinas del modulo
prueba6.c. Los otros dos módulos; lcd2.c y serie2.c; también son utilizados por el programa de
aplicación de la estación meteorológica completa y serán descritos en la sección correspondiente a
dicho programa.
3.4.1.1- Subrutina principal
Este programa se basa en la estructura más común para programas para microcontroladores, la cual
consiste en una etapa de inicialización y un ciclo principal. Esta estructura es usada debido a que los
programas para microcontroladores no terminan nunca, debido a que no hay un sistema operativo al
cual represarle el control del CPU cuando el programa termina.
En la etapa de iniciación, se configuran a todas las terminales que no van a ser utilizadas como salidas,
con el objeto de evitar que el ruido externo las haga cambiar de nivel y aumenten el consumo de
21
corriente. En este programa de prueba, se activan permanentemente las fuentes de alimentación de los
sensores y de la pantalla LCD, así como el convertidor de niveles RS232 del puerto serie. Además se
configura el puerto serie, el convertidor analógico a digital, el temporizador, la pantalla LCD y el
temporizador vigía que se utilizará en la implementación del reloj de tiempo real. Antes de entrar al
ciclo principal, se habilita la atención de interrupciones y se ponen a cero las variables del reloj de
tiempo real.
Al inicio del ciclo principal, se pone al microcontrolador en modo de ahorro de energía. Se sale de este
modo cuando el temporizador vigía genera una interrupción, en este caso, cada segundo. Con esto se
asegura que se ejecute el ciclo principal una vez por segundo sin tener ninguna rutina de retardo y con
el menor consumo de corriente por parte del microcontrolador. El resto del código se encarga de tomar
las mediciones, mostrar la hora, la temperatura interna y externa en la pantalla LCD y enviar todos los
resultados al puerto serie. Todo esto se termina de hacer en menos de un segundo y se regresa de nuevo
al modo de ahorro de energía.
La temperatura interna, la temperatura externa, la humedad relativa y la dirección del viento se miden
por medio del convertidor analógico a digital. Para realizar las conversiones, se programan cuatro
conversiones por medio de los registros de control del ADC (ADC12MCTL0 a ADC12MCTL3), donde
se indica el canal en el que se va ha efectuar la conversión y el voltaje de referencia que se va a utilizar.
La temperatura interna se convierte el canal 10 (sensor interno) y la temperatura externa en el canal 0.
Para ambos canales se utiliza la referencia interna de 2.5V. El canal 1 se usa para medir el voltaje en el
potenciómetro de la veleta y el canal 2 para la salida del sensor de humedad relativa. Como el rango en
que varían estos dos voltajes excede los 2.5V de la referencia interna, se usa directamente la
alimentación de 3.3V como referencia para estos canales.
El puerto serie se programa para transmisión y recepción de datos de 8 bits a 2400BPS y usando
interrupciones. El reloj del puerto serie se genera a partir del cristal de 32768Hz con lo que se evita
tener que controlar la frecuencia del reloj RC del CPU.
Una de las partes más importantes de este programa de prueba es la que se encarga de convertir los
datos obtenidos del convertidor analógico a digital y del temporizador a los valores en las unidades
correspondientes a la variable medida. En el programa esta sección se ve como una serie de formulas
de un reglón que no aparentan ser importantes, pero que son criticas para obtener resultados realmente
útiles y la obtención de una formula que funcione correctamente no es obvia.
La formula para la conversión de la temperatura externa se obtiene a partir de las siguientes relaciones
básicas: el voltaje de salida del sensor se relaciona con la temperatura por Vs=0.01Te, donde T es la
temperatura en grados centígrados y Vs el voltaje de salida en volts. La salida del sensor se aplica a un
amplificador de acondicionamiento cuya salida en volts es Vamp=Vs+0.8333. Finalmente, dicho
voltaje se convierte a un numero binario por el convertidor analógico a digital, de manera que
ResulAD=Vamp*4095/2.5. De estas tres ecuaciones se puede despejar la temperatura, obteniendo la
siguiente formula:
Te=(ResADC*2.5/4095-0.8333)/0.01
Esta formula es esencialmente correcta, pero no puede implementarse directamente en el
microcontrolador debido a que este solo cuenta con operaciones enteras y la formula tiene varios
coeficientes fraccionarios que de ser truncados alterarían drásticamente el resultado final. La solución a
este problema consiste en reagrupar los coeficientes, de manera que se obtengan números enteros de
gran magnitud que no se alteren demasiado al ser truncados. Otra modificación que se le hizo a la
formula fue multiplicar a la temperatura por 10 para dejarla en décimas de grado centígrado, que es la
resolución con que quiere mostrarse el resultado. El reagrupamiento usado fue el siguiente:
22
10Te=(ResADC- (0.833*4095/2.5) ) * (10*2.5/0.01) / 4095 = (ResADC-1365)*2500/4095
En la medición de la temperatura interna, el voltaje del sensor de temperatura en volts es
Vtemp=0.00355*Ti+0.986, donde Ti es la temperatura interna en grados centígrados. Este voltaje entra
al convertidor analógico a digital obteniendo ResADC= Vtemp*4095/2.5. Nuevamente se puede
obtener una formula de conversión a partir de estas dos igualdades, pero contendría coeficientes
fraccionarios que no se pueden implementar en el microcontrolador. Así es que se reagrupan los
coeficientes para obtener números enteros y también se multiplica la temperatura por 10 para dejarla en
décimas de grados centígrado, de manera que la formula queda:
10Ti=10*(ResADC*2.5/4095-0.986)/0.00355
10Ti=(ResACD- (0.986*4095/2.5) )* (10*2.5/0.00355) /4095
10Ti=(ResADC-1615)*7042/4095
El sensor de humedad Honeywell modelo IH-3610 se vende junto con información de calibración de
fabrica (Figura ???) que permite obtener el porcentaje de humedad relativa a partir del voltaje de salida
del sensor. La relación que nos interesa es RH=(Vo-0.921)/0.0316. Antes de aplicarse al convertidor, la
salida del sensor pasa por un divisor de voltaje formado por una resistencia de 330K y una de 180K,
que entrega un voltaje Vdiv=Vo*330/(180+330). Como en la conversión de este canal se usa como
referencia el voltaje de alimentación del microcontrolador de 3.3V, la salida del convertidor es
ResADC=Vdiv*3.3/4095. Usando las ecuaciones anteriores, despejando la humedad relativa y
reagrupando, se obtiene:
RH=(ResADC*(3.3/4095)*(330+180)/330-0.921)/0.0316
RH=(ResADC- (0.921*(4095/3.3)*(330/510)) ) * (3.3*(510/330)/0.0316) /4095
RH=(ResADC—739)*161/4095)
Figura 3.11 Información de calibración del sensor de humedad.
La más simple de las formulas de conversión es la de la velocidad del viento. El potenciómetro
acoplado a la veleta entrega 3.3V cuando se encuentra en la posición correspondiente a 360°. Estos
mismos 3.3V se usan como referencia al hacer la conversión de analógico a digital, por lo que a 360°
corresponde el resultado máximo de la conversión de 4095. De esta forma, la formula para calcular la
dirección del viento es una simple regla de tres: DV=ResADC*360/4095.
La única variable que no se mide usando el convertidor analógico a digital es la velocidad del viento,
que se mide usando la función de captura de eventos del temporizador B. Al girar el anemómetro
genera un pulso por cada revolución. Cada vez que el temporizador detecta un flanco de subida
almacena el valor del contador del temporizador, el cual tiene un reloj de 32768Hz. Si se resta el valor
de dos capturas consecutivas, se obtiene el tiempo (periodo en múltiplos de 1/32768 S ) que tardo el
anemómetro en dar una revolución y a partir de él se puede calcular la frecuencia de la señal y la
velocidad del viento. En cada revolución una paleta del anemómetro habrá recorrido una distancia
23
lineal igual a 2πr, donde r es el radio del anemómetro, en este caso 0.05m. La frecuencia de la salida
del anemómetro (f) nos indica el número de veces por segundo que se recorre dicha distancia, por lo
que la relación entre la velocidad del viento y la frecuencia en metros/S es v= 2πrf. Sustituyendo el
radio del anemómetro y cambiando las unidades a Km/Hr, se tiene
vel= 2π*(0.05m)*(1Km/1000m)*(3600S/1Hr)*f=1.1309*f
Dado que el periodo de la señal se mide en múltiplos del periodo del reloj de 32768Hz, la frecuencia
del anemómetro (f en Hz) es f=32768/periodo. Como se desea mostrar la velocidad del viento con un
dígito decimal, se multiplica por diez la velocidad y la formula para convertir el periodo a velocidad del
viento queda
10Vel=10*1.1309*32768/ periodo =3705973/periodo
3.4.2- Programa completo de aplicación
El programa de aplicación consta de los módulos principal5.c, interfaz.c, transmite.c lcdand2.c y
serie2.c. El módulo principal.c contiene la rutina principal del programa, varias de las rutinas de
atención a interrupciones, una rutina para escribir a la memoria FLASH, la rutina que realiza el proceso
de medición, una que controla la frecuencia del reloj RC del CPU y la que lleva el reloj de tiempo real.
El módulo interfaz.c contiene las rutinas que implementan la interfaz con el usuario por medio de la
pantalla LCD y un teclado de cuatro teclas; transmite.c incluye las rutinas necesarias para transmitir los
datos capturados a la PC a través del puerto serie; lcdand2.c contiene rutinas para la escritura de datos y
comandos a la pantalla LCD y finalmente, serie2.c permite leer y escribir al puerto serie por medio de
interrupciones y con una cola circular como buffer.
A continuación se describen las rutinas más importantes o las que tienen un funcionamiento que nos es
totalmente obvio, con el objetivo de ayudar al lector a comprender el código fuente del anexo C
3.4.2.1- Subrutina principal
Al igual que el programa de prueba, este programa se basa en la estructura consistente en una etapa de
inicialización y un ciclo principal infinito. En la etapa de iniciación son pocas las diferencias. Una de
las más notables es que el temporizador vigía esta programado para generar una interrupción cada
doscientos cincuenta milisegundos en lugar de cada segundo, con lo que el tiempo que tarda la
ejecución del ciclo principal se reduce. El puerto serie se programa para trabajar a una frecuencia de
9600 BPS, la que no puede ser obtenida a partir del reloj de baja frecuencia de 32768Hz, así que se
genera a partir del reloj del CPU. Como este oscilador de tipo RC no es ni muy estable ni muy exacto
en su frecuencia, debe ser ajustado cada cierto tiempo para mantener la frecuencia constante y evitar
errores en la comunicación. Este ajuste se realiza llamando a la función Ajusta_DCO().
El ciclo principal en ese programa es más pequeño que en el de prueba, ya que algunas tareas se
trasfirieron a otras rutinas. En el ciclo principal primero se revisa si se ha presionado alguna tecla y de
ser así, se llama la rutina interfaz() para que la procese. Después se llama a la rutina de medición y a la
de transmisión de datos por el puerto serie. Finalmente se pone al microcontrolador en un modo de
ahorro de energía hasta que ocurre la siguiente interrupción del temporizador vigía que lo despierta y
hace que se ejecute una vez más el ciclo principal.
3.4.2.2- Rutina de ajuste de la frecuencia del DCO
El ajuste de la frecuencia del oscilador RC del CPU se realiza comparando la frecuencia del oscilador
con alguna frecuencia estable y conocida, como es el caso de la del oscilador de cristal de baja
24
frecuencia. En otros diseños puede usarse la frecuencia de la corriente alterna de alimentación. Para
realizar esta comparación se utiliza el temporizador A. El reloj de alta frecuencia se usa para excitar al
contador del temporizador y se mide el periodo de la señal de referencia por medio de un canal de
captura. Si el número de ciclos de reloj de alta frecuencia en un periodo de la señal de referencia es
mayor que el deseado, la frecuencia del oscilador es muy alta y debe disminuirse. En caso contrario, la
frecuencia debe aumentarse.
En esta rutina no fue posible utilizar interrupciones para hacer la medición del periodo, ya que en un
periodo de la señal de referencia de 32768Hz solo se tienen 32 ciclos del reloj de 1MHz del CPU, lo
cual no es suficiente para completar la llamada y la ejecución de la rutina de atención de interrupciones.
En su lugar, se usa la técnica de escrutinio (polling) para detectar el momento en que se presenta un
flanco de subida y se realiza la captura. En realidad se cuentan ocho flancos para hacer que el tiempo
con el que se compara la frecuencia del DCO sea mayor y se pueda obtener una mejor resolución en la
medición.
La frecuencia de oscilación del DCO puede controlarse por medio de tres mecanismos diferentes. El
primero es cambiando la resistencia conectada al generador de corriente del DCO, lo que hace que se
seleccione un rango de frecuencias diferente. Esto se logra modificando los bits RSELx del registro
BSCCTL1. Dentro de cada rango se puede escoger una de ocho posibles frecuencias por medio de los
bits DCOx del registro DCOCTL. Además, se pueden lograr 32 frecuencias efectivas intermedias entre
cada una de esta ocho usando la modulación. La modulación consiste en alternar entre una frecuencia y
la inmediata superior cada treinta y dos ciclos de reloj. Los bits MODx del registro DCOCTL indican
cuantos de estos treinta y dos ciclos se tomaran de la frecuencia inmediata superior y el resto se tomara
de la frecuencia seleccionada por los bits DCO. De esta forma se logra una frecuencia efectiva
intermedia y el error en frecuencia se integra a cero cada treinta y dos ciclos de reloj. Los tres
mecanismos son utilizados por la rutina de ajuste de la frecuencia del DCO.
3.4.2.3- Rutina de Medición.
El proceso de medición puede llegar a tomar hasta 3 segundos, lo cual es un tiempo mayor al que toma
realizar una pasada por el ciclo principal del programa. Por esta razón, la rutina de medición se diseño
de manera que en cada ocasión en que es llamada, ejecuta una etapa del proceso de medición y regresa
al programa principal para dar tiempo a que se ejecuten las rutinas de interfaz con el usuario y de
transmisión de datos, de manera que entre la ejecución de una etapa y la siguiente existe por lo menos
un cuarto de segundo. La rutina lleva el control de en que etapa del proceso de medición se encuentra
por medio de la variable etapa_med, de forma que para pasar a otra etapa sólo se debe modificar esta
variable. Por medio de una estructura switch se ejecuta el código correspondiente a cada etapa. Existen
cinco etapas en el proceso de medición, las cuales se describen en la siguiente tabla.
25
Etapa
Descripción
0
Se compara la hora actual con la hora en que se programo la siguiente medición.
Cuando es el momento de hacer la medición, se encienden la fuente de alimentación
de los sensores para dar tiempo a que se estabilice. Finalmente se borran las banderas
para la medición de la velocidad del viento.
1
Se habilitan las interrupciones para la medición de la velocidad del viento. Se
enciende la fuente interna del convertidor analógico a digital y se programa los
canales donde se va a realizar una conversión.
2
Arranca la conversión de analógico a digital y una vez terminada, se aplican las
formulas para obtener los valores de las variables en las unidades correctas. Se apaga
la fuente del convertidor analógico a digital.
3
Se espera la medición de la velocidad del viento.
4
Se escriben los datos medidos en la memoria FLASH y se regresa a la etapa 0
Tabla 3.2 – Etapas del proceso de medición
La medición de la velocidad del viento se hace en conjunto con la rutina de atención de interrupciones
del temporizador B, por lo que es necesario en cada llamada a la rutina de medición revisar si ya se
presentaron los dos flancos necesarios para tener una medición de velocidad completa. El código que
realiza esta función se encuentra después de la estructura switch y es el que permite pasar de la etapa
tres a la cuatro.
3.4.2.4- Rutina de escritura a la memoria FLASH
El propósito de esta rutina es escribir un número de 16 bits en la memoria FLASH. Como los datos
medidos son escritos en la memoria en secuencia, se usa la variable puntero para indicar en que
dirección de memoria se debe almacenar el siguiente dato. El MSP430F149 cuenta con 60K de
memoria FLASH que se localizan en el rango de direcciones que va de 1100h a FFFFh. El rango de
1100h a 11FFh esta ocupado por la llamada memoria de información, la cual se divide en dos bancos
de 128 bytes y esta diseñada para guardar información de calibración. El resto de la memoria esta
dividida en segmentos de 512 bytes, por lo que usar la memoria de información para almacenar datos
complicaría el código de la rutina de escritura a memoria. En esta aplicación se usa el rango de DE00h
a FFFFh para guardar el código del programa, de forma que el rango de direcciones que queda
disponible para almacenar los datos capturados es de 1200h a DDFFh.
La variable puntero recibe un valor inicial de 1200h en el programa principal, y cada vez que se realiza
una escritura es incrementada en dos para que apunte a la siguiente palabra de 16 bits en la memoria.
Antes de hacer cualquier escritura, la rutina revisa si la dirección a la que se va a escribir se sale del
rango permitido y si se encuentra en el inicio de un segmento, en cuyo caso se borra el segmento para
asegurarse de que se va a poder escribir en él sin problemas.
El MSP430 cuenta con un circuito controlador especial para la memoria FLASH, por lo que el proceso
de escritura resulta consiste únicamente en enviar un par de comandos al controlador y después escribir
el dato a la localidad deseada como si se tratara de una localidad de memoria RAM. En ese momento la
ejecución del programa por el CPU se detiene hasta que el controlador termina de realizar la escritura.
26
3.4.2.5- Rutinas de la interfaz con el usuario
Al igual que la rutina de medición, la rutina de interfaz con el usuario esta diseñada para ser llamada,
hacer alguna acción rápidamente y regresar al programa principal para permitir que se ejecuten otras
tareas. La rutina de interfaz recibe del programa principal un parámetro que le indica cual fue la ultima
tecla presionada y con base a este parámetro modifica su estado interno, la pantalla y de ser necesario,
alguna de las variables de configuración que controlan el funcionamiento del resto del sistema.
La interfaz con el usuario se basa en un sistema de menús y submenús a los cuales tiene acceso el
usuario por medio de cuatro teclas: entrar, escape, anterior y siguiente. Al energizarse el sistema la
pantalla LCD esta apagada para ahorrar energía, por lo que el usuario debe encenderla presionado la
tecla entrar. En ese momento aparece un elemento del menú principal en el renglón superior de la
pantalla. Presionado la tecla entrar se puede seleccionar ese elemento del menú principal y escoger
entonces alguno de los submenús que aparecerán en el renglón inferior de la pantalla. La tecla escape
permite salir del submenú actual y regresar al nivel superior. Las teclas siguiente y anterior permiten al
usuario pasar al siguiente menú o submenú. La siguiente tabla lista los menús y submenús de la
aplicación.
Menú
Configurar fecha
Submenús
Día
Mes
Año
Configurar hora
Hora
Minuto
Velocidad de captura
Cada 10 minutos
Cada hora
Mostrar últimos resultados
Temperatura y humedad relativa
Velocidad y dirección del viento.
Transmite datos
A que teléfono
Transmitir ahora
Tipo de MODEM
Capturar datos
Tabla 3.3 - Listado de los menús de la estación meteorológica
La interfaz con el usuario en realidad esta dividida en varias subrutinas: interfaz, realiza el manejo de
los menús y submenús; pintamenus, escribe en la pantalla las leyendas correspondientes a cada menú y
submenú; acción se llama una vez que se ha escogido un submenú y es donde realmente se realiza la
acción correspondiente. Además se utilizan varias rutinas auxiliares para funciones tales como mostrar
el valor de las variables, modificar una variable de configuración entera y modificar el número
27
telefónico a donde se va a trasmitir.
3.4.2.6- Rutinas de transmisión de datos
El diseño de la rutina de transmisión esta pensado de manera que la rutina pueda llamarse desde el ciclo
principal, efectuar una etapa del proceso de transmisión y regresar. Al igual que las rutinas de medición
e interfaz, debe almacenar su estado interno en variables para que en cada llamada sepa que parte del
código debe ejecutarse. La variable etapa_trans indica en que etapa se encuentra el proceso de
transmisión, y para pasar de una etapa a otra, solo hay que modificar su valor. El código
correspondiente a la etapa se selecciona por medio de una estructura switch. Las etapas que forman
parte del proceso de medición se muestran en la siguiente tabla.
Etapa
Descripción
0
Envía un comando para reiniciar al módem
1
Espera la respuesta (“OK”) del módem y envía el comando de marcado
2
Espera que el módem confirme la conexión (CONNECT)
3
Transmite un bloque de máximo 120 palabras y su checksum
4
Espera la confirmación de recepción sin errores por la PC y revisa si hay más
datos por transmitir
5
Indica que hubo un error en la transmisión
6 a 11
Envían la secuencia de escapa y el comando de colgar al módem
Figura 3.4 - Etapas de la rutina de transmisión de datos
3.4.2.7- Rutinas para el manejo del puerto serie
Este grupo de rutinas permite la escritura y lectura de datos del y al puerto serie por medio de
interrupciones y una cola circular que sirve como almacenamiento intermedio. Realizar el acceso al
puerto serie de esta manera tiene la ventaja de que la rutina de transmisión de datos puede escribir (o
leer) los datos que deben transmitirse en la cola circular y regresar al programa principal en un tiempo
menor al que realmente toma hacer la transmisión. Cuando el puerto serie esta listo para recibir un
nuevo dato, genera una interrupción y la rutina de atención toma el dato de la cola circular y lo pasa al
puerto serie.
Las rutinas para el manejo del puerto serie se encuentran en el módulo serie2.c y entre ellas se
encuentran las rutinas de atención a interrupciones de recepción y transmisión, rutinas para meter y
sacar datos de las colas de recepción y transmisión, una rutina para saber si hay datos en el buffer de
recepción, y rutinas para tomar una cadena de caracteres y mandarla al puerto serie.
3.4.2.8- Rutinas para escribir en la pantalla LCD.
Para pode mostrar información al usuario a través de la pantalla LCD, es necesario enviarle algunos
comando y los datos que se desea mostrar. De esto se encargan las rutinas de escritura a la pantalla
LCD. Se cuenta con una rutina de escritura de datos y una de comandos, las cuales solo difieren el
28
valor lógico que ponen en la terminal RS de la pantalla, 0 para un comando y 1 para un dato. El
proceso de escritura en si consiste en poner el dato en las terminales de datos de la pantalla, después
poner la terminal E en uno y la terminal R/W en cero, y finalmente regresar la terminal E a cero para
terminar la escritura.
En esta aplicación no fue posible leer a la pantalla por que esta se alimenta con 5V, mientas que el
microcontrolador se alimenta solo con 3.3V. El voltaje de salida de la pantalla podría dañar al
microcontrolador, mientras que el voltaje de salida en nivel alto del microcontrolador es ligeramente
más alto que el voltaje mínimo que la pantalla interpreta como nivel alto. De esta forma la escritura es
posible, pero la lectura no es segura. Una consecuencia importante de no poder hacer lecturas de la
pantalla es que no puede saberse cuando la pantalla esta lista para recibir un nuevo comando o dato, por
lo cual hay que usar algunos retardos para asegurarse que la pantalla va a tener suficiente tiempo como
para terminar de ejecutar el comando enviado.
Además de las rutinas de escritura lectura de comandos y datos, el módulo lcdand2.c contiene una
rutina para enviar una cadena de caracteres a la pantalla y la definición de constantes simbólicas para
los comandos de la pantalla LCD. Antes de utilizar la rutina de escritura de cadenas, es conveniente
asegurarse de que el cursor se encuentre en la posición deseada enviando el comando
LCD_SET_DD_RAM_ADDRESS más la dirección de la localidad donde debe escribirse la cadena en
la pantalla.
3.5- Descripción del programa de recepción de datos
La funcionalidad de la estación meteorológica automatizada seria muy limitada si no se cuenta con la
herramienta adecuada que permita recibir la información capturada por la estación y hacerla disponible
a los especialistas en meteorología en u formato que facilite su consulta y análisis. Esta herramienta es
en este caso una computadora personal corriendo el programa desarrollado en Gambas para esta
aplicación en particular. Gambas es un intérprete avanzado de Basic, similar a Visual Basic, pero esta
pensado para utilizarse en el sistema operativo GNU/LINUX y es de código fuente abierto. Utiliza los
paradigmas de programación por eventos y orientada a objetos comunes en los lenguajes que permiten
el desarrollo de programas con interfaz de usuario grafica.
Los controles que formaran la interfaz de usuario se dibujan usando la barra de herramientas de
Gambas y los nombres, clase y propiedades de estos se almacenan en un formato textual en un archivo
con extensión .form. El texto de que representa la forma dibujada para esta aplicación se incluye en el
apéndice C.
29
Figura 3.12 – Entorno de desarrollo Gambas
El código en Basic del programa se guarda en un archivo con extensión .class y consiste en una serie de
funciones de respuesta a eventos. La mayoría de los controles y sus respectivas rutinas de eventos
sirven para configurar el proceso de recepción de datos, con opciones como indicar el puerto serie que
se va a utilizar, la velocidad de las comunicaciones, el tipo de intercambio de saludos, si se va a realizar
la comunicación a través de dos módems celulares GSM o si se va a simular el comportamiento de un
módem para poder descargar los datos de la estación a través de una conexión directa por cable.
Form_Open() es llamada cuando se carga la forma y se utiliza para dar un valor inicial a algunas
variables. El proceso de recepción en realidad comienza cuando se presiona el botón que abre el puerto
serial al que esta conectado el módem o la estación meteorológica. Además de abrir el puerto, esta
rutina (Button1_Click()) arranca un temporizador para que después de un par de segundos se ejecute la
rutina del temporizador donde se envían los comandos para preparar al módem para recibir datos. El
temporizador se utiliza en otras ocasiones donde se requiere un retardo, tal como antes y después de
enviar la secuencia de escape para colgar el módem.
La mayor parte del proceso de comunicación se lleva a cabo en la rutina de lectura del puerto serie
SPort_Read(). Esta es la rutina que es llamada cuando se tiene un número suficiente de caracteres
recibidos en el puerto para que estos sean leídos y procesados por el programa de aplicación. El
problema es que el momento en que es llamado puede ser algo aleatorio. La función no es llamada
siempre cuando se tiene una cantidad fija de caracteres, ni tampoco cuando se recibe un carácter de
final de línea, o cuando ha pasado un tiempo determinado. Todo lo anterior hace que la rutina no pueda
estructurarse en una forma simple, sino que tenga que almacenar los caracteres recibidos que no han
sido procesados y el estado del proceso de recepción en variables globales para que no se pierdan entre
una llamada y la siguiente. De hecho, se usa una estructura similar a la usada en las rutinas de
medición, transmisión e interfase de la estación meteorológica. El proceso se divide en una serie de
etapas de las que se ejecuta una parte, una o varias etapas cada vez que la rutina es llamada. Las etapas
30
del proceso de recepción se describen en la tabla 3.5
Etapa
0
1
2
3
4
5
Descripción conexión por módem
Descripción emulando módem
Se espera la respuesta del módem al Se espera el comando inicial enviado por la
comando inicial
estación y se responde emulando al módem
Espera la indicación de marcado por Espera el comando de marcado y responde
parte el módem y responde
indicando una conexión. Pasa a la etapa 3
Espera la indicación de conexión por Se omite
parte del módem
Recibe el tamaño del bloque o el indicador de final de la transmisión, en este caso se
transfieren los datos contenidos en memoria a un archivo
Recibe los datos y calcula la suma de comprobación
Compara la suma de comprobación y envía una indicación de comprobación o de error,
después regresa a la etapa 3
Tabla 3.5 – Etapas del proceso de recepción en la PC
Figura 3.13 – Captura de pantalla del programa de recepción
31
4- Resultados, conclusiones y trabajo futuro
4.1 Introducción
Los resultados obtenidos en el desarrollo del caso practico se pueden dividir en dos partes: la primera
son los obtenidos con el programa de prueba y que se usaron para comparar las mediciones obtenidas
con la estación meteorológica con las de otros instrumentos y la segunda son los obtenidos durante un
periodo de prueba de tres días en los que la estación estuvo expuesta a la intemperie para probar su
funcionamiento en condiciones más cercanas a las reales. Ambos resultados se presentan a
continuación.
4.2- Resultados del programa de prueba
Para verificar el correcto funcionamiento de las mediciones de temperatura interna y externa,
primeramente se intento comparar los resultados obtenidos por la estación con los obtenidos por medio
de un termómetro de mercurio marca Brannam graduado de -20 a 100°C. Este enfoque
desafortunadamente no fue muy práctico. Para hacer las mediciones en ambientes controlados, se
realizaban en el interior de un refrigerador y de un horno resistivo. En el caso del refrigerador era
necesario abrir la puerta para poder ver la lectura del termómetro y aunque en el caso del horno se
contaba con una perforación especial para poner un termómetro, el hecho de que la ubicación de esta
perforación hacia imposible colocar el bulbo del termómetro en la misma posición que el sensor interno
del microcontrolador y de que las paredes metálicas del horno conducían el calor hacia el termómetro
más rápidamente que hacia los sensores de la estación; genero un gradiente de temperatura que hizo
imposible aplicar la misma temperatura al termómetro y a los sensores electrónicos.
Con esta prueba, lo que realmente se deseaba era, por un lado, calibrar al sensor de temperatura interna
que no viene calibrado de fabrica, y por otro, compensar los errores en la función de transferencia del
amplificador debidos a la tolerancia en las resistencias del mismo. Los datos necesarios para esta
compensación se deben obtener al medir la misma temperatura con nuestros instrumentos con un
instrumento de referencia, para lo que originalmente se pensó usar el termómetro. Al no ser practico
usarlo, se cambio la referencia al mismo sensor de temperatura externa (LM35), midiendo su voltaje de
salida directamente con un voltímetro. Como este sensor se encuentra calibrado de fabrica y tiene una
exactitud de +/- 0.5°C y una linealidad de +/-0.25°C, puede usarse como una buena referencia.
Lo primero que se hizo fue corregir los errores en el amplificador del sensor de temperatura interna.
Para esto se midió la salida del sensor con un voltímetro, se convirtió a temperatura y se comparo con
las lecturas obtenidas por la estación a tres temperaturas diferentes. Los resultados obtenidos se
muestran en la siguiente tabla.
Referencia (0.1°C)
Estación (0.1°C)
56
36
200
182
316
300
Tabla 4.1 Resultados de las mediciones para la calibración de la medición interna.
32
Se aplico un análisis de regresión lineal con la medición de la estación como variable independiente y
la referencia como variable dependiente y se obtuvo una pendiente de 0.9849 y una ordenada en el
origen de 20.6. Usando estos datos la formula para convertir el resultado del convertidor analógico a
digital a temperatura se modifica de TI = (ResADC-1365)*2500/4095 a
TE = [ (ResADC-1365)*2500/4095] * 0.9849 +20.6
TE = (ResADC-1365+20.6*4095/(2500*0.9849) )*(2500*0.9849)/4095
TE = (ResADC-1330)*2462/4095
Una vez compensado el error del amplificador se utilizó la lectura del sensor externo como referencia
para calibrar al sensor interno, que no viene calibrado de fábrica. Se colocaron los sensores uno junto al
otro y se clocaron en un refrigerador y en el horno resistivo, leyendo los resultados de la medición de la
estación por medio del puerto serie del microcontrolador, para no abrir la puerta y crear un gradiente de
temperatura que arruinara la medición. Los datos obtenidos en estas pruebas se muestran a
continuación.
Temperatura Externa (0.1°C)
Temperatura Interna (0.1°C)
31
20
194
178
406
397
Tabla 4.2 Resultados de las mediciones para la calibración de la medición interna.
El análisis de regresión lineal da una pendiente de 1.0145 y una ordenada en el origen de 10.37.
Corrigiendo la formula para obtener la temperatura interna a partir del resultado del ADC, se obtiene
TI = [(ResADC-1615)*7042/4095]*1.0145+11
TI = (ResADC-1615+ (11*4095/(7042*1.0145)) ) * (7042*1.0145)/4095
TI = (ResADC-1608)*7144/4095
En cuanto al sensor de humedad, no fue posible conseguir otro instrumento con el cual comparar las
mediciones de la estación. Como el sensor viene calibrado de fábrica, lo que se hizo fue medir el
voltaje de salida del sensor, usar la información de calibración para calcular la humedad relativa y
comprarla con la mostrada en ese momento por la estación. Los únicos errores que encontraron por este
procedimiento son muy pequeños y pueden ser atribuidos al redondeo en el calculo con operaciones
enteras en el microcontrolador.
La medición de la dirección del viento se verifico en el laboratorio comparando la medición del ángulo
de la veleta por medio de un transportador con el resultado entregado por la estación. Las mediciones
se hicieron a ángulos de 0°, 90°, 180° y 270°. El error máximo encontrado fue de 3°, lo que indica un
buen grado de linealidad en el potenciómetro acoplado a la veleta.
El funcionamiento del anemómetro se probó de manera indirecta, aplicando una señal de una
frecuencia conocida a la entrada y aprovechando el hecho de que la velocidad del viento es
proporcional a la frecuencia. Las señales de referencia aplicadas, la velocidad medida y la velocidad
esperada, se muestran en la tabla siguiente.
Frecuencia de la señal de referencia (Hz)
201
101
50
Velocidad medida (Km/Hr)
227.13
114.13
56.5
Valor esperado (Km/Hr)
227.36
113.68
56.84
33
Tabla 4.3 – Mediciones de la calibración de la velocidad del viento
Los errores presentados estuvieron dentro del 1% del valor esperado y pueden atribuirse en parte al
redondeo por operaciones enteras.
4.3- Resultados de la prueba a la intemperie.
La prueba de funcionamiento de la estación a la intemperie se realizó entre los días 4 y 8 de septiembre
de 2004. La estación se coloco en la azotea de un edificio en la zona urbana de Morelia, Michoacán. El
gabinete de la estación se coloco en el interior de una caja plástica para evitar que e mojara, quedando
en el exterior del mismo únicamente el sensor de temperatura externa LM35, la veleta y el
anemómetro. Los resultados de las mediciones de estos cuatro días se muestran a continuación.
Fecha
Hora
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
4/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
19:10:00
19:20:00
19:30:00
19:40:00
19:50:00
20:00:00
20:10:00
20:20:00
20:30:00
20:40:00
20:50:00
21:00:00
21:10:00
21:20:00
21:30:00
21:40:00
21:50:00
22:00:00
22:10:00
22:20:00
22:30:00
22:40:00
22:50:00
23:00:00
23:10:00
23:20:00
23:30:00
23:40:00
23:50:00
00:00:00
00:10:00
00:20:00
00:30:00
00:40:00
00:50:00
TI (°C) TE (°C)
23.2
23.2
22.8
22.3
21.8
21.3
21.1
20.8
20.8
20.8
20.6
20.6
20.2
20.1
20.1
20.1
19.5
19.4
19.2
19
18.5
18.2
18
17.7
17.5
17.7
17.5
17.3
17.5
17.3
17.5
17.3
17.1
17
16.8
22.7
22.2
21.6
21.3
21
20.8
20.8
20.9
20.8
20.6
20.9
20.2
20.5
20.3
20.3
18.9
18.3
18.4
17.9
17.3
17.3
17.2
17
18.3
16.9
17
16.3
17
17
17.4
17.3
16.7
16.6
16.7
16.6
HR
Dir (°)
DIR
Vel. (Km/hr)
56.00%
55.00%
56.00%
58.00%
61.00%
62.00%
66.00%
66.00%
66.00%
67.00%
67.00%
69.00%
70.00%
71.00%
71.00%
74.00%
76.00%
77.00%
79.00%
80.00%
83.00%
84.00%
85.00%
87.00%
88.00%
88.00%
88.00%
89.00%
89.00%
89.00%
90.00%
90.00%
91.00%
91.00%
91.00%
313
340
340
301
296
224
352
352
174
187
187
265
174
174
174
133
176
176
176
234
234
234
234
234
234
234
234
234
234
234
160
147
31
32
109
NO
NNO
NNO
ONO
ONO
SO
N
N
S
S
S
O
S
S
S
SE
S
S
S
SO
SO
SO
SO
SO
SO
SO
SO
SO
SO
SO
SSE
SSE
NNE
NNE
ESE
0
0
0
0.59
0
0
0
1.33
1.18
0.72
0
0
0
1.78
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
34
Fecha
Hora
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
01:00:00
01:10:00
01:20:00
01:30:00
01:40:00
01:50:00
02:00:00
02:10:00
02:20:00
02:30:00
02:40:00
02:50:00
03:00:00
03:10:00
03:20:00
03:30:00
03:40:00
03:50:00
04:00:00
04:10:00
04:20:00
04:30:00
04:40:00
04:50:00
05:00:00
05:10:00
05:20:00
05:30:00
05:40:00
05:50:00
06:00:00
06:10:00
06:20:00
06:30:00
06:40:00
06:50:00
07:00:00
07:10:00
07:20:00
07:30:00
07:40:00
07:50:00
08:00:00
08:10:00
08:20:00
08:30:00
08:40:00
08:50:00
09:00:00
09:10:00
09:20:00
TI (°C) TE (°C)
16.6
16.6
16.5
16.6
16.5
16.5
16.5
16.3
16.1
16.1
16.1
15.8
15.8
15.6
15.6
15.4
15.4
15.6
15.6
15.6
15.4
15.4
15.3
15.3
15.3
15.3
15.3
15.3
15.3
15.3
15.4
15.3
15.4
15.3
15.4
15.3
15.4
15.4
15.3
15.3
15.3
15.4
15.6
15.8
15.9
15.9
16.1
16.5
17
17.3
17.8
16.6
16.9
16.5
16.5
16.8
16.7
16.6
16.4
16.6
16.3
16.4
16
16
16.1
16.3
16.4
16.4
16.6
16.6
15.5
16.4
16.4
17.4
17.3
17.9
18.3
18.4
18.5
19.3
19.4
20
19.7
19.8
20
20.2
21.3
21.4
21.4
21.6
21.6
22
22.6
22.4
22.8
22.7
23.6
24.9
24.4
25.3
25.6
26
HR
Dir (°)
DIR
Vel. (Km/hr)
92.00%
92.00%
93.00%
93.00%
92.00%
93.00%
93.00%
94.00%
93.00%
96.00%
95.00%
95.00%
95.00%
95.00%
96.00%
96.00%
96.00%
96.00%
96.00%
96.00%
97.00%
97.00%
96.00%
96.00%
97.00%
97.00%
96.00%
96.00%
97.00%
97.00%
97.00%
97.00%
97.00%
97.00%
97.00%
98.00%
97.00%
97.00%
97.00%
98.00%
98.00%
98.00%
97.00%
97.00%
97.00%
97.00%
97.00%
96.00%
96.00%
95.00%
94.00%
96
70
70
70
70
63
63
46
40
96
107
108
109
106
115
115
115
115
115
115
115
115
115
115
115
115
115
115
116
116
116
116
116
116
116
114
114
113
127
127
127
127
127
127
127
73
73
73
73
73
73
E
ENE
ENE
ENE
ENE
ENE
ENE
NE
NE
E
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
SE
SE
SE
SE
SE
SE
SE
ENE
ENE
ENE
ENE
ENE
ENE
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
35
Fecha
Hora
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
09:30:00
09:40:00
09:50:00
10:00:00
10:10:00
10:20:00
10:30:00
10:40:00
10:50:00
11:00:00
11:10:00
11:20:00
11:30:00
11:40:00
11:50:00
12:00:00
12:10:00
12:20:00
12:30:00
12:40:00
12:50:00
13:00:00
13:10:00
13:20:00
13:30:00
13:40:00
13:50:00
14:00:00
14:10:00
14:20:00
14:30:00
14:40:00
14:50:00
15:00:00
15:10:00
15:20:00
15:30:00
15:40:00
15:50:00
16:00:00
16:10:00
16:20:00
16:30:00
16:40:00
16:50:00
17:00:00
17:10:00
17:20:00
17:30:00
17:40:00
17:50:00
TI (°C) TE (°C)
18.3
18.5
18.5
18.7
19.4
19.9
20.6
20.8
21.1
21.4
22
22.6
23.7
24.7
25.4
27.6
27.5
28.1
28.5
28.7
29.9
30.9
33.3
34
35.7
36.1
37.3
38.1
39
39.7
40.4
41.4
37.1
35
39.3
42.2
41.4
37.6
34.5
36.4
39.5
39.5
39.8
41.4
37.9
37.4
41
40.5
40
36.9
34.2
25.3
23.5
24.1
24.5
23.1
24.5
24.7
25.3
25.4
25.4
25.7
26.9
28.3
26.4
27
28.5
29
28.3
27
31.1
27.2
33.6
34.3
32.7
34.4
32
34.4
34.8
36
37.3
37.1
35.7
30.7
31
39.2
43.8
33
30.5
35.5
35.3
33.4
41.9
37.1
35.2
34.6
40.5
40.4
43.7
32.8
28.2
26.9
HR
Dir (°)
DIR
Vel. (Km/hr)
92.00%
90.00%
86.00%
84.00%
81.00%
79.00%
77.00%
75.00%
72.00%
70.00%
67.00%
65.00%
60.00%
57.00%
55.00%
50.00%
48.00%
46.00%
45.00%
44.00%
41.00%
40.00%
36.00%
33.00%
30.00%
29.00%
27.00%
26.00%
24.00%
23.00%
22.00%
21.00%
28.00%
31.00%
25.00%
22.00%
21.00%
24.00%
29.00%
27.00%
23.00%
23.00%
22.00%
19.00%
23.00%
24.00%
19.00%
19.00%
21.00%
23.00%
28.00%
73
62
61
45
45
45
45
45
45
45
45
45
45
45
45
98
98
110
97
90
98
98
123
45
45
304
76
136
128
80
146
146
210
87
87
214
192
192
216
220
222
181
174
229
217
231
233
241
234
326
279
ENE
ENE
ENE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
E
E
ESE
E
E
E
E
ESE
NE
NE
NO
ENE
SE
SE
E
SE
SE
SSO
E
E
SO
SSO
SSO
SO
SO
SO
S
S
SO
SO
SO
SO
OSO
SO
NO
O
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0.8
0
0
0
0
0
0
0
0
0
0
0
1.22
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0.74
0
0
0
0
0
1.18
2.2
1.39
36
Fecha
Hora
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
5/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
18:00:00
18:10:00
18:20:00
18:30:00
18:40:00
18:50:00
19:00:00
19:10:00
19:20:00
19:30:00
19:40:00
19:50:00
20:00:00
20:10:00
20:20:00
20:30:00
20:40:00
20:50:00
21:00:00
21:10:00
21:20:00
21:30:00
21:40:00
21:50:00
22:00:00
22:10:00
22:20:00
22:30:00
22:40:00
22:50:00
23:00:00
23:10:00
23:20:00
23:30:00
23:40:00
23:50:00
00:00:00
00:10:00
00:20:00
00:30:00
00:40:00
00:50:00
01:00:00
01:10:00
01:20:00
01:30:00
01:40:00
01:50:00
02:00:00
02:10:00
02:20:00
TI (°C) TE (°C)
33.6
34.8
31.1
28.5
26.6
25
24.7
24.4
23.7
22.8
22.5
22
21.4
20.9
20.2
19.7
19.2
19.2
19.4
19
18.5
18
17.8
18
18.2
18.2
18.2
18
17.8
17.7
17.7
17.5
17.3
17.3
17.1
17.1
17.3
17.5
17.5
17.1
16.8
16.5
16.5
16.5
16.5
16.5
16.3
16.1
15.9
15.9
15.9
33.2
28.8
25
24.6
21.6
23.6
23.1
22.7
22
21.7
22.4
21.1
21.2
20
19.6
19.5
19.5
19.9
19.1
18.8
18.1
18
18.7
19
19
18.7
18.7
18.3
18.1
17.7
17.8
17.7
17.4
17.8
12
18.1
18.4
18.6
17.2
16.4
16.1
16
16.1
16.2
16.5
16.2
16.3
16.2
16.2
16.1
16.1
HR
Dir (°)
DIR
Vel. (Km/hr)
30.00%
26.00%
33.00%
39.00%
49.00%
54.00%
55.00%
57.00%
59.00%
61.00%
77.00%
68.00%
69.00%
72.00%
75.00%
78.00%
79.00%
80.00%
79.00%
73.00%
70.00%
72.00%
74.00%
75.00%
75.00%
78.00%
82.00%
84.00%
86.00%
87.00%
89.00%
86.00%
85.00%
86.00%
86.00%
86.00%
85.00%
84.00%
85.00%
87.00%
88.00%
89.00%
89.00%
90.00%
89.00%
89.00%
90.00%
91.00%
91.00%
92.00%
93.00%
283
276
293
360
263
282
282
282
281
281
281
285
281
305
319
273
348
244
349
315
21
359
359
360
358
57
0
49
32
6
296
254
246
246
239
194
176
182
213
235
246
276
276
277
9
9
51
39
47
47
360
ONO
O
ONO
N
O
ONO
ONO
ONO
O
O
O
ONO
O
NO
NO
O
NNO
OSO
N
NO
NNE
N
N
N
N
ENE
N
NE
NNE
N
ONO
OSO
OSO
OSO
OSO
SSO
S
S
SSO
SO
OSO
O
O
O
N
N
NE
NE
NE
NE
N
1.44
1.98
0.69
1.01
1.65
0
0
0
1.2
0
0
0.72
0
1.19
0
0.69
0
0
0
0
1.2
0
0
0
0
0
0
0.68
0
0
0
0.71
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0.81
0
0.8
0
37
Fecha
Hora
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
02:30:00
02:40:00
02:50:00
03:00:00
03:10:00
03:20:00
03:30:00
03:40:00
03:50:00
04:00:00
04:10:00
04:20:00
04:30:00
04:40:00
04:50:00
05:00:00
05:10:00
05:20:00
05:30:00
05:40:00
05:50:00
06:00:00
06:10:00
06:20:00
06:30:00
06:40:00
06:50:00
07:00:00
07:10:00
07:20:00
07:30:00
07:40:00
07:50:00
08:00:00
08:10:00
08:20:00
08:30:00
08:40:00
08:50:00
09:00:00
09:10:00
09:20:00
09:30:00
09:40:00
09:50:00
10:00:00
10:10:00
10:20:00
10:30:00
10:40:00
10:50:00
TI (°C) TE (°C)
15.8
15.4
15.4
15.3
15.3
15.1
15.1
15.1
14.9
14.9
15.1
15.1
14.9
14.9
14.9
14.6
14.4
14.4
14.4
14.2
14
14
13.9
13.9
13.9
13.9
13.9
13.9
13.7
14.2
14.4
14.2
14.4
14.7
14.7
14.7
14.9
15.1
15.4
15.8
16.5
17.1
17.5
17.7
17.8
18.3
19
19.9
20.6
20.8
21.6
15.7
15.8
15.7
16.3
15.5
15.6
15.6
15.5
15.5
15.9
15.3
15.9
15.5
15.2
15.4
15.2
15
15.7
14.6
14.7
14.7
14.5
15.7
14.9
14.4
15
14.7
14.5
15.8
15.5
16
16.3
16.2
16.3
16.7
16.4
16.4
16.7
17.3
18.2
18.9
18.9
19.4
18.7
19.2
19.7
20.6
21
20.6
21.6
22.6
HR
Dir (°)
DIR
Vel. (Km/hr)
92.00%
92.00%
92.00%
92.00%
92.00%
92.00%
93.00%
93.00%
92.00%
93.00%
92.00%
91.00%
91.00%
91.00%
91.00%
91.00%
92.00%
92.00%
92.00%
92.00%
92.00%
92.00%
92.00%
92.00%
93.00%
92.00%
93.00%
93.00%
94.00%
94.00%
95.00%
96.00%
96.00%
96.00%
96.00%
96.00%
96.00%
96.00%
94.00%
94.00%
92.00%
88.00%
85.00%
82.00%
81.00%
78.00%
76.00%
74.00%
71.00%
69.00%
67.00%
45
339
15
25
10
28
36
35
35
36
35
36
36
35
35
35
36
35
35
35
35
35
35
36
36
35
36
35
35
35
35
36
35
35
35
35
35
35
36
36
36
36
36
36
36
36
36
36
36
36
36
NE
NNO
NNE
NNE
N
NNE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
0
0
0
0
0
0.9
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
38
Fecha
Hora
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
11:00:00
11:10:00
11:20:00
11:30:00
11:40:00
11:50:00
12:00:00
12:10:00
12:20:00
12:30:00
12:40:00
12:50:00
13:00:00
13:10:00
13:20:00
13:30:00
13:40:00
13:50:00
14:00:00
14:10:00
14:20:00
14:30:00
14:40:00
14:50:00
15:00:00
15:10:00
15:20:00
15:30:00
15:40:00
15:50:00
16:00:00
16:10:00
16:20:00
16:30:00
16:40:00
16:50:00
17:00:00
17:10:00
17:20:00
17:30:00
17:40:00
17:50:00
18:00:00
18:10:00
18:20:00
18:30:00
18:40:00
18:50:00
19:00:00
19:10:00
19:20:00
TI (°C) TE (°C)
22.8
23.7
24.2
23.8
25.7
28.1
29.7
30.9
32.1
33
35.4
35
38.6
38.5
39.5
39.7
39.5
39.1
37.9
33.8
33.3
36.9
33.3
30.6
29.3
28.7
28.3
27.1
26.1
25.7
25.6
25.4
23
20.6
19.2
18.7
18.9
19.5
23.7
23.7
22.6
21.4
20.8
20.4
19.9
19.4
19
18.9
18.7
18.5
18.3
24.9
24.6
23.9
24.3
27.9
28.9
27.7
30.7
29.4
35.3
33
36.4
32.9
34.7
38.3
37.3
36.8
36.8
31.6
29.4
31.7
31.6
27.7
27.1
27.5
27.7
26.1
24.9
24.9
25.2
25.3
20.6
17.6
16.6
17
16.4
17
18.3
22.4
18.6
17.9
17.9
18.1
18.3
17.5
18.2
17.8
17.5
17.4
17.4
17
HR
Dir (°)
DIR
Vel. (Km/hr)
65.00%
61.00%
58.00%
59.00%
54.00%
47.00%
42.00%
40.00%
36.00%
35.00%
31.00%
30.00%
25.00%
25.00%
24.00%
24.00%
23.00%
24.00%
24.00%
28.00%
30.00%
25.00%
29.00%
34.00%
37.00%
40.00%
40.00%
43.00%
45.00%
46.00%
47.00%
52.00%
63.00%
69.00%
73.00%
76.00%
77.00%
78.00%
63.00%
57.00%
61.00%
63.00%
67.00%
70.00%
74.00%
77.00%
77.00%
78.00%
80.00%
81.00%
81.00%
36
36
43
53
53
53
53
53
53
53
53
59
59
284
284
212
213
213
197
134
134
147
132
132
132
132
132
132
124
114
114
206
211
130
130
130
130
130
130
121
121
121
121
121
122
122
122
122
163
180
180
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
ENE
ENE
ONO
ONO
SSO
SSO
SSO
SSO
SE
SE
SSE
SE
SE
SE
SE
SE
SE
SE
ESE
ESE
SSO
SSO
SE
SE
SE
SE
SE
SE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
ESE
SSE
S
S
0
0
0
0
0
0
0
0
7.21
0
0
0
0
0
0
0
0
0
5.32
0
0
0
0
0
0
0
0
0
0
1.84
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
39
Fecha
Hora
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
6/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
19:30:00
19:40:00
19:50:00
20:00:00
20:10:00
20:20:00
20:30:00
20:40:00
20:50:00
21:00:00
21:10:00
21:20:00
21:30:00
21:40:00
21:50:00
22:00:00
22:10:00
22:20:00
22:30:00
22:40:00
22:50:00
23:00:00
23:10:00
23:20:00
23:30:00
23:40:00
23:50:00
00:00:00
00:10:00
00:20:00
00:30:00
00:40:00
00:50:00
01:00:00
01:10:00
01:20:00
01:30:00
01:40:00
01:50:00
02:00:00
02:10:00
02:20:00
02:30:00
02:40:00
02:50:00
03:00:00
03:10:00
03:20:00
03:30:00
03:40:00
03:50:00
TI (°C) TE (°C)
18.2
17.8
17.8
17.5
17.5
17.3
17.3
17.1
17.1
17
16.8
16.8
16.6
16.6
16.5
16.5
16.3
16.5
16.5
16.5
16.3
16.5
16.5
16.5
16.5
16.3
16.3
16.5
16.3
16.3
16.1
15.9
16.1
16.1
16.1
16.1
16.1
15.9
16.1
16.3
16.3
16.1
16.1
16.1
15.9
15.9
15.9
15.9
15.9
15.8
15.8
16.8
17
16.9
16.8
16.9
15.9
16.9
17.1
17.2
17.5
17.5
17.2
17.5
17.5
16.9
16.9
17.9
16.9
19.7
16.7
16.5
16.8
17
17.5
16.9
16.9
17.2
17.2
16.9
17
17
16.7
16.9
17.2
17.9
18.8
17.2
17.2
17.4
17.5
17.4
17.3
17.3
17.3
17.4
17.3
17.5
17.6
17.5
17.6
17.5
HR
Dir (°)
DIR
Vel. (Km/hr)
82.00%
82.00%
83.00%
83.00%
84.00%
85.00%
86.00%
85.00%
85.00%
86.00%
88.00%
88.00%
88.00%
87.00%
87.00%
88.00%
87.00%
88.00%
88.00%
88.00%
88.00%
89.00%
89.00%
89.00%
90.00%
90.00%
90.00%
91.00%
91.00%
91.00%
92.00%
92.00%
92.00%
92.00%
92.00%
93.00%
93.00%
93.00%
93.00%
93.00%
94.00%
94.00%
94.00%
94.00%
95.00%
95.00%
94.00%
94.00%
94.00%
94.00%
94.00%
237
237
237
237
236
236
245
0
0
19
55
44
26
1
65
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
OSO
OSO
OSO
OSO
SO
SO
OSO
N
N
NNE
NE
NE
NNE
N
ENE
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
0
0
0
0
0
0
0.8
0
0
1.22
2.77
0
0.58
0.81
0
0.68
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
40
Fecha
Hora
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
04:00:00
04:10:00
04:20:00
04:30:00
04:40:00
04:50:00
05:00:00
05:10:00
05:20:00
05:30:00
05:40:00
05:50:00
06:00:00
06:10:00
06:20:00
06:30:00
06:40:00
06:50:00
07:00:00
07:10:00
07:20:00
07:30:00
07:40:00
07:50:00
08:00:00
08:10:00
08:20:00
08:30:00
08:40:00
08:50:00
09:00:00
09:10:00
09:20:00
09:30:00
09:40:00
09:50:00
10:00:00
10:10:00
10:20:00
10:30:00
10:40:00
10:50:00
11:00:00
11:10:00
11:20:00
11:30:00
11:40:00
11:50:00
12:00:00
12:10:00
12:20:00
TI (°C) TE (°C)
15.8
15.8
15.8
15.8
15.8
15.6
15.8
15.6
15.8
15.8
15.6
15.6
15.8
15.4
15.3
15.4
15.4
15.4
15.3
15.3
15.1
15.1
14.9
14.9
14.9
14.9
15.3
15.4
15.8
16.1
16.6
17.1
17.8
18.2
18
18.5
19.2
20.8
21.8
22.1
22.1
22
23
23.5
24.2
25.4
26.3
27.5
27.5
28.1
28.7
17.4
18
17.8
17.5
17.5
17.8
18.2
18.1
15.9
18.2
16.4
18.1
16.4
17.3
17.9
18
17.5
17.8
17
17.2
17
16.9
16.9
17.1
16.9
17
18.1
18.2
18.4
18.6
19.3
20.4
20.7
20.4
20.1
21.7
22.8
24.2
24.2
23.9
23.5
22.6
25.1
25.6
27
25.7
26.8
28.8
28
28.2
28.9
HR
Dir (°)
DIR
Vel. (Km/hr)
94.00%
94.00%
94.00%
94.00%
94.00%
94.00%
95.00%
94.00%
94.00%
94.00%
94.00%
94.00%
94.00%
94.00%
95.00%
94.00%
94.00%
94.00%
94.00%
95.00%
95.00%
94.00%
95.00%
95.00%
94.00%
93.00%
92.00%
92.00%
91.00%
90.00%
89.00%
88.00%
86.00%
86.00%
86.00%
91.00%
90.00%
88.00%
79.00%
72.00%
67.00%
67.00%
66.00%
60.00%
60.00%
57.00%
53.00%
48.00%
48.00%
45.00%
44.00%
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
2
5
5
5
5
5
5
5
33
10
10
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
NNE
N
N
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
41
Fecha
Hora
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
12:30:00
12:40:00
12:50:00
13:00:00
13:10:00
13:20:00
13:30:00
13:40:00
13:50:00
14:00:00
14:10:00
14:20:00
14:30:00
14:40:00
14:50:00
15:00:00
15:10:00
15:20:00
15:30:00
15:40:00
15:50:00
16:00:00
16:10:00
16:20:00
16:30:00
16:40:00
16:50:00
17:00:00
17:10:00
17:20:00
17:30:00
17:40:00
17:50:00
18:00:00
18:10:00
18:20:00
18:30:00
18:40:00
18:50:00
19:00:00
19:10:00
19:20:00
19:30:00
19:40:00
19:50:00
20:00:00
20:10:00
20:20:00
20:30:00
20:40:00
20:50:00
TI (°C) TE (°C)
30.9
33.8
34.5
35.5
36.2
33.6
31.2
31.1
30.9
32.6
38.8
42.8
38.3
35.9
34.8
33.5
32.1
35.2
37.1
35.5
32.1
29.3
26.9
25.4
25
24.5
24.5
24.7
24.7
24.9
24.5
23.7
22.6
22
21.6
21.3
20.9
20.9
20.8
20.8
20.6
20.2
19.9
19.7
19.4
19.4
19.2
19
18.9
18.9
18.7
32.1
33
33.5
32.7
30.1
28.6
28.9
30.7
27.9
36.8
40.5
40.2
31
30.8
31.1
30.6
32.9
37.1
31.6
28
27.7
25.2
24.3
24.3
23.3
23.4
23.8
23.8
24.3
23.4
23.5
22.7
21.4
21.1
21.1
21
21.3
20.9
21
20.8
21
20.3
20
19.9
19.6
19.8
19.6
19.3
19.2
19.4
19.4
HR
Dir (°)
DIR
Vel. (Km/hr)
40.00%
34.00%
30.00%
28.00%
27.00%
29.00%
34.00%
35.00%
34.00%
33.00%
25.00%
21.00%
23.00%
25.00%
27.00%
29.00%
31.00%
26.00%
23.00%
25.00%
30.00%
35.00%
40.00%
43.00%
45.00%
48.00%
45.00%
45.00%
46.00%
47.00%
49.00%
51.00%
56.00%
58.00%
60.00%
61.00%
62.00%
63.00%
64.00%
65.00%
66.00%
67.00%
68.00%
69.00%
68.00%
69.00%
69.00%
70.00%
71.00%
72.00%
74.00%
12
11
11
11
47
39
40
38
39
49
49
53
102
241
218
218
265
292
104
100
108
120
84
83
182
158
234
230
228
228
226
231
190
158
141
131
132
115
160
154
143
51
85
86
84
112
81
96
80
96
120
NNE
N
N
N
NE
NE
NE
NE
NE
NE
NE
NE
ESE
OSO
SO
SO
O
ONO
ESE
E
ESE
ESE
E
E
S
SSE
SO
SO
SO
SO
SO
SO
S
SSE
SE
SE
SE
ESE
SSE
SSE
SE
NE
E
E
E
ESE
E
E
E
E
ESE
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
5.46
1.03
1.51
0
0.99
0
1.64
1.25
1.65
1.48
1.78
2.05
0
0
2.27
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
42
Fecha
Hora
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
7/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
21:00:00
21:10:00
21:20:00
21:30:00
21:40:00
21:50:00
22:00:00
22:10:00
22:20:00
22:30:00
22:40:00
22:50:00
23:00:00
23:10:00
23:20:00
23:30:00
23:40:00
23:50:00
00:00:00
00:10:00
00:20:00
00:30:00
00:40:00
00:50:00
01:00:00
01:10:00
01:20:00
01:30:00
01:40:00
01:50:00
02:00:00
02:10:00
02:20:00
02:30:00
02:40:00
02:50:00
03:00:00
03:10:00
03:20:00
03:30:00
03:40:00
03:50:00
04:00:00
04:10:00
04:20:00
04:30:00
04:40:00
04:50:00
05:00:00
05:10:00
05:20:00
TI (°C) TE (°C)
18.7
18.7
18.5
18.3
18.5
18.5
18.5
18.5
18.3
18.3
18.3
18.2
17.5
17
16.6
16.5
16.3
16.1
16.3
16.1
15.9
15.9
15.9
15.9
15.8
15.9
16.1
16.3
16.1
16.1
16.1
16.3
16.1
16.1
15.9
16.1
15.9
15.9
15.8
15.8
15.9
15.9
15.8
15.8
15.8
15.9
15.9
15.9
15.9
15.8
15.9
19.2
19.2
19.1
19.2
19.3
19.4
19.4
19.3
19.3
19.5
19.2
17.2
16.2
15.9
16.1
16.5
16.4
16.2
15.8
15.8
15.5
15.6
15.5
15.5
15.7
15.9
15.9
16.4
17.8
16.9
16.5
16.4
16.3
16.2
16.6
16.6
16.3
16.1
16.4
16.5
16.6
16.4
16.4
16.4
16.6
16.5
16.4
16.1
16.5
16.4
16.7
HR
Dir (°)
DIR
Vel. (Km/hr)
74.00%
74.00%
76.00%
77.00%
76.00%
77.00%
77.00%
76.00%
76.00%
76.00%
75.00%
74.00%
77.00%
79.00%
80.00%
81.00%
81.00%
81.00%
82.00%
82.00%
83.00%
83.00%
84.00%
85.00%
85.00%
85.00%
85.00%
86.00%
86.00%
86.00%
87.00%
87.00%
88.00%
88.00%
88.00%
89.00%
89.00%
89.00%
89.00%
89.00%
89.00%
89.00%
90.00%
90.00%
90.00%
91.00%
90.00%
89.00%
89.00%
89.00%
89.00%
21
21
20
32
20
21
24
194
214
176
193
200
190
47
44
80
60
46
61
61
44
56
56
56
60
50
49
53
49
50
49
48
47
52
45
52
55
52
50
44
50
45
44
42
48
46
41
47
51
44
48
NNE
NNE
NNE
NNE
NNE
NNE
NNE
SSO
SO
S
SSO
SSO
S
NE
NE
E
ENE
NE
ENE
ENE
NE
NE
NE
NE
ENE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
0
0
0
0
0
0
0
2.78
0.97
2.52
2.29
2.64
0.89
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
43
Fecha
Hora
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
05:30:00
05:40:00
05:50:00
06:00:00
06:10:00
06:20:00
06:30:00
06:40:00
06:50:00
07:00:00
07:10:00
07:20:00
07:30:00
07:40:00
07:50:00
08:00:00
08:10:00
08:20:00
08:30:00
08:40:00
08:50:00
09:00:00
09:10:00
09:20:00
09:30:00
09:40:00
09:50:00
10:00:00
10:10:00
10:20:00
10:30:00
10:40:00
10:50:00
11:00:00
11:10:00
11:20:00
11:30:00
11:40:00
11:50:00
12:00:00
12:10:00
12:20:00
12:30:00
12:40:00
12:50:00
13:00:00
13:10:00
13:20:00
13:30:00
13:40:00
13:50:00
TI (°C) TE (°C)
15.9
15.9
15.8
15.8
15.6
15.6
15.8
15.6
15.6
15.6
15.4
15.3
15.1
15.1
14.9
14.9
15.1
15.4
15.8
15.9
16.3
16.8
17.1
17.3
17.8
18.7
19.9
20.8
20.9
21.3
21.8
22.3
23.2
23.7
24.9
26.1
26.9
28.3
29.9
30.6
32.1
32.3
33.1
35.7
38.5
37.1
33
36.6
34.8
32.3
33.8
17
17
16.8
16.9
17
16.9
16.9
16.8
17
16.7
16.6
16.6
16.6
16.3
16.4
14.1
16.9
17
17
17.7
17.7
18.3
18.6
18.8
17
21.2
22.1
21.6
21.4
22.1
22.4
23.1
23.5
24.1
26.7
27.9
26.6
29.1
30.2
32
31.3
32
33.7
33.8
36
29.6
30
32.8
30.5
29.3
30
HR
Dir (°)
DIR
Vel. (Km/hr)
88.00%
88.00%
89.00%
89.00%
89.00%
90.00%
91.00%
91.00%
91.00%
90.00%
91.00%
92.00%
90.00%
90.00%
89.00%
89.00%
89.00%
88.00%
87.00%
86.00%
85.00%
84.00%
84.00%
83.00%
87.00%
84.00%
80.00%
74.00%
70.00%
68.00%
66.00%
64.00%
60.00%
57.00%
53.00%
50.00%
47.00%
43.00%
39.00%
37.00%
34.00%
34.00%
31.00%
27.00%
24.00%
23.00%
30.00%
25.00%
26.00%
31.00%
27.00%
47
46
43
42
46
49
47
42
48
48
49
64
43
42
41
41
41
43
44
42
40
45
35
40
146
87
96
117
110
111
93
83
48
61
62
41
40
44
53
51
49
52
65
44
52
67
62
48
50
60
46
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
ENE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
SE
E
E
ESE
ESE
ESE
E
E
NE
ENE
ENE
NE
NE
NE
NE
NE
NE
NE
ENE
NE
NE
ENE
ENE
NE
NE
ENE
NE
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0.93
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
44
Fecha
Hora
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
8/09/04
14:00:00
14:10:00
14:20:00
14:30:00
14:40:00
14:50:00
15:00:00
15:10:00
15:20:00
15:30:00
15:40:00
15:50:00
16:00:00
16:10:00
16:20:00
16:30:00
16:40:00
16:50:00
17:00:00
17:10:00
17:20:00
17:30:00
17:40:00
17:50:00
18:00:00
18:10:00
18:20:00
18:30:00
18:40:00
18:50:00
19:00:00
19:10:00
19:20:00
19:30:00
19:40:00
19:50:00
20:00:00
20:10:00
20:20:00
20:30:00
20:40:00
20:50:00
21:00:00
21:10:00
21:20:00
21:30:00
21:40:00
21:50:00
22:00:00
22:10:00
22:20:00
TI (°C) TE (°C)
33
31.4
29.2
28.1
27.8
28.5
29.2
31.4
30.9
30.4
31.2
34.2
33.5
30
26.8
24.2
22
21.1
20.6
20.9
20.6
20.4
20.2
20.2
20.1
19.7
19.5
19.4
19.4
19.4
19.2
19
18.9
18.5
18.3
18.3
18.2
18
17.8
17.7
17.5
17.5
17.5
17.5
17.5
17.3
17.3
17.1
17.1
17
17
30
28.3
26.1
25.9
27.1
28.2
28.8
31.1
28.5
28.9
34
32.7
27.7
25.6
22.2
19.1
18.1
18.3
17.7
18.8
18
18.9
18.3
18.4
18.4
18.7
18.6
19.6
19.7
19.1
19.5
18.7
18.8
18.9
18.9
19
18.8
18.6
18.3
18
18.2
17.7
18.2
18
18
18
17.1
17.3
17
17
17.4
HR
Dir (°)
DIR
Vel. (Km/hr)
29.00%
31.00%
35.00%
38.00%
40.00%
38.00%
37.00%
32.00%
32.00%
33.00%
32.00%
27.00%
27.00%
31.00%
41.00%
52.00%
62.00%
65.00%
68.00%
67.00%
67.00%
68.00%
67.00%
68.00%
68.00%
70.00%
69.00%
69.00%
70.00%
69.00%
69.00%
70.00%
71.00%
73.00%
74.00%
75.00%
76.00%
76.00%
75.00%
77.00%
76.00%
77.00%
77.00%
77.00%
77.00%
76.00%
75.00%
74.00%
72.00%
70.00%
67.00%
47
59
42
41
41
41
41
41
39
39
41
51
20
5
100
21
97
94
78
76
4
4
5
4
8
96
94
93
93
5
18
17
35
27
15
15
20
14
14
14
13
13
14
14
14
14
14
13
13
13
12
NE
ENE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NE
NNE
N
E
NNE
E
E
ENE
ENE
N
N
N
N
N
E
E
E
E
N
NNE
NNE
NE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
NNE
0
0
0
0
0
0
0
0
0
0
0
0
1.03
0
2.28
1.32
0
1.39
0.79
0
0.73
0
0.67
1.03
0.74
1.07
0
0
0
0
0
0
0.58
0
1.26
89.3
0.82
0
0
0
0
0
0
0
0
0
0
0
0
0
0
45
Tabla 4.4 Resultados de la prueba a la intemperie.
Te m pe ratura m e dida por la e s tación m e te orológica
50
45
40
Temperatura (°C)
35
30
TI (°C)
25
TE (°C)
20
15
10
5
0
04/09/20 05/09/20 05/09/20 06/09/20 06/09/20 07/09/20 07/09/20 08/09/20 08/09/20 09/09/20 09/09/20
04 12:00 04 00:00 04 12:00 04 00:00 04 12:00 04 00:00 04 12:00 04 00:00 04 12:00 04 00:00 04 12:00
Fe cha/Hora
Figura 4.1 Gráfica de la temperatura interna y externa
M e dicione s de la hum e dad re lativa
120.00%
Humedad Relativa (%)
100.00%
80.00%
60.00%
HR
40.00%
20.00%
0.00%
04/09/20 05/09/20 05/09/20 06/09/20 06/09/20 07/09/20 07/09/20 08/09/20 08/09/20 09/09/20 09/09/20
04 12:00 04 00:00 04 12:00 04 00:00 04 12:00 04 00:00 04 12:00 04 00:00 04 12:00 04 00:00 04 12:00
Fe cha / Hora
Figura 4.2 Gráfica de la humedad relativa
46
El hecho de que las mediciones se hayan realizado en medio de una zona urbana y el de que la estación
se colocara al lado de una pared de mampostería en una caja cerrada afectaron las mediciones. Las
temperaturas máximas registradas (43°C) fueron en general más altas que las reportadas por el servicio
meteorológico para la ciudad (min. 15°C, máx. 26°C). Lo anterior fue debido al efecto de invernadero
que se presento en la caja plástica y al calor almacenado en la pared. Se observan descensos
importantes en la temperatura que coinciden con las visitas para comprobar el funcionamiento de la
estación, durante las cuales se abría la caja plástica y se dejaba escapar más rápidamente el aire
caliente. En cuanto a las temperaturas mínimas, no se vieron tan afectadas ya que durante la noche el
calor almacenado se disipaba y a las siete de la mañana (la hora en que se presentaba la temperatura
mínima) ya no tenía ningún efecto en la medición de la temperatura.
En cuanto a la velocidad del viento, todas las lecturas obtenidas fueron de magnitud pequeña, debido a
que las construcciones circundantes al lugar donde se realizo la prueba impiden el paso de vientos
fuertes. La presencia de ráfagas esporádicas de viento hacia que la posición de la veleta se mantuviera
fija por periodos de tiempo considerables. Finalmente la humedad relativa fue muy alta debido a que
durante los días de la prueba llovió por la tarde y noche. La humedad relativa reportada por el servicio
meteorológico fluctuó entre el 50 y el 100%, mientras que la medida por la estación vario entre el 20 y
el 98%. La discrepancia en el valor mínimo se debe a que el sensor de humedad se encuentra en el
interior del gabinete de la estación, donde se presentaron temperaturas superiores a 40°C que
contribuyeron a la reducción de la humedad relativa.
47
4.4- Conclusiones
En el desarrollo del presente trabajo, se diseño y construyó un prototipo de una estación meteorológica
capaz de medir, registrar y comunicar cinco variables diferentes. Este prototipo cumple con los
requisitos planteados en los objetivos del presente trabajo. Puede medir cinco variables atmosféricas y
almacenar los resultados de las mediciones por un periodo de treinta días. También es capaz de
transmitir los datos capturados a una computadora personal a través de un módem analógico o GSM.
Los costos de manufactura de la estación son los suficientemente bajos como para que se pueda
considerar para emplearse en los proyectos de investigación y desarrollo de la fundación PRODUCE de
Michoacán.
El prototipo fue evaluado por los investigadores en agricultura de la fundación Produce de Michoacán
y en su opinión esta en condiciones para ser utilizado en sus programas de investigación.
Aunque este primer prototipo aún no se encuentra listo para una producción comercial, si puede usarse
en programas de investigación en agricultura y en el desarrollo de una versión mejorada que si pueda
fabricarse en masa y distribuirse a los productores agrarios del estado de Michoacán.
En caso de que el prototipo llegue a producirse en masa como parte la puesta en practica de las técnicas
mejoradas de producción que consideran al microclima local, el impacto de la estación en la
productividad de los cultivos seria bastante importante, ya que preemitiría utilizar técnicas de riego,
abono y fumigación que ahorren insumos y sean más eficientes.
El proceso de diseño del equipo se documento de manera que puede servir para que las personas
interesadas en diseñar un equipo similar conozcan los retos a los que pudieran enfrentarse, algunas
posibles soluciones y recomendaciones para la toma de decisiones en el proceso de diseño.
48
4.5- Trabajo Futuro
Al presentar el equipo a los investigadores de la Fundación Produce de Michoacán, estos quedaron
contentos con el funcionamiento de la estación en cuanto a la medición de las variables meteorológicas
y su almacenamiento, pero les pareció que el usar un módem y una línea telefónica, así sea una línea
privada, iba a resultar poco práctico para los productores. La solución que se propone es hacer el enlace
por medio de radiofrecuencia. Este cambio seria conveniente desde el punto de ahorro de engría ya que
permitiría eliminar la interfase RS232 y al comunicarse por medio de un equipo transciver de RF
conectado a una PC, podría eliminarse también la pantalla LCD y el teclado. Estos tres elementos,
junto con el módem externo, son los que consumen la mayor cantidad de energía. Ya que existen
módulos de RF que tienen un consumo de potencia muy bajo, es posible que se logre una unidad con
menor consumo de energía, más compacta y más fácil de instalar.
Como ya no se contara con una pantalla LCD la interfase del usuario se reducirá a un LED que
parpadee al presionar una tecla, indicando que la estación funciona correctamente. El código de la
interfase de usuario seria sustituido por código para responder a los comandos enviados a la estación
por un programa ejecutándose en una PC, vía RF. El equipamiento de los productores con una PC para
fines administrativos es un proyecto que ya se encuentra en marcha por parte de la fundación produce
de Michoacán y esta misma puede ser usada para la recolección de datos de las estaciones
meteorológicas. Él utilizar un entorno gráfico con menús y ventanas para trabajar con la estación
meteorológica debe resultar más familiar y sencillo para los usuarios finales que la interfase LCD.
El otro aspecto que debe mejorarse es el gabinete de la estación, que debe ser apto para proteger a la
estación de la intemperie, pero debe tener una buena ventilación para evitar que el calor se acumule en
su interior y afecte a las mediciones. También debe poder colocarse en lo alto de una torre, cerrarse con
llave y resistir ataque vandálicos menores.
49
Bibliografía
Acosta Jimeno, C. A. y otros. (1998) “Central hospitalaria de monitoreo” Memorias del XX Congreso
internacional académico de ingeniería electrónica, ELECTRO’99. Chihuahua: Instituto Tecnológico de Chihuahua.
Benitez Villalobos, Juan y otros. (1997) “Digitalización de un sistema de adquisición de datos para
aplicaciones agrícolas” Memorias del VII Congreso interuniversitario de computación, eléctrica y
electrónica, CIECE’97. Ensenada: Universidad Autónoma de Baja California.
Bursky, Dave (1999) “Feature-rich flash memories deliver high density”. Electronic Design.; 9 de
agosto de 1999; Vol. 47, No. 16; p. 67. Cleveland: Penton Media.
Carlson Wireless Telephone, Inc. (1999) All Digital Remote Phone Link <http://www.i-wll.com/>
(pagina web) Redway, CA: autor
Carter, Bruce y Brown, Thomas R (2001). Handbook of operational amplifier aplications Dallas:
Texas Instruments Inc. Disponible en < http://www.ti.com/msp430 > (pagina web, Núm. de doc.
SBOA092A)
Gracey, Ken (1999). “Connect a modem to a basic stamp”. EDN. 16 de septiembre 1999; Vol. 44, No.
19; pg. 194. Boston: Cahners Magazine.
Malik, Norbert R. (1996) Circuitos electrónicos , análisis, simulación y diseño. Madrid Prentice Hall.
Manzini, Ron (2001). Single-Supply Op Amp Design Techniques Application report. Dallas: Texas Instruments Inc. Disponible en < http://www.ti.com/msp430 > (pagina web, Núm. de doc. SLOA030A)
Oppenheim, Allan V. et all Tratamiento de señales en tiempo discreto. Madrid Prentice
Pass, David A. y Mamane, Charles. (1999) “Interactive telemetry controls remedial operations at hazardous waste site”. Pollution Engineering.; Abril de1999; Vol. 31, No. 4; p. 42. Newton: Cahners
Magazine
Rashid, Muhammad H. (2000) Circuitos micro electrónicos, análisis y diseño México D.F.: International Thomson Editores
Texas Instruments Inc. (2003) MSP430x1xx Family Users Guide Dallas: Texas Instruments Inc. Disponible en < http://www.ti.com/msp430 > (pagina web, Núm. de doc. SLAU49C)
Texas Instruments Inc. (2000) MSP430x13x, MSP430x14x, MSP430x14x1MIXED SIGNAL MICROCONTROLLER Data sheet Dallas: autor. Disponible en < http://www.ti.com/msp430 > (pagina
web, Núm. de doc. SLAS272E)
Texas Instruments Inc. (2000) MAX3223 Data sheet Dallas: autor. Disponible en < http://www.ti.com/msp430 > (pagina web, Núm. de doc. SLLS409K)
50
Texas Instruments Inc. (1996) TLV2442, TLV2442A, TLV2444, TLV2444A Advanced LinCMOS.
RAIL-TO-RAIL OUTPUT WIDE-INPUT-VOLTAGE OPERATIONAL AMPLIFIERS Data sheet
Dallas : autor. Disponible en < http://www.ti.com/msp430 > (pagina web, Núm. de doc. SLOS169H)
Wait, John V. y otros (1992). Introduction to operational amplifier, theory and applications. New
York (2ª Edición): McGraw Hill International Editions.
51
Índice de figuras
Figura 2.1 Amplificador sumador no inversor...........................................................................................5
Figura 2.2 Amplificador sumador con entrada diferencial........................................................................ 5
Figura 2.3 Convertidor AD de aproximaciones sucesivas......................................................................... 7
Figura 2.4 Convertidor AD tipo ráfaga o flash de tres bits........................................................................8
Figura 2.5 Convertidor AD de doble integración.......................................................................................9
Figura 2.6 Estructura principal del programa.......................................................................................... 10
Figura 3.1 – Diagrama a bloques de la estación meteorológica ..............................................................13
Figura 3.2 Diagrama de flujo del proceso de medición y almacenamiento de la estación meteorológica.
..................................................................................................................................................................15
Figura 3.3 - Diagrama eléctrico del subsistema de alimentación.............................................................16
Figura 3.4 Amplificador diferencial con desplazamiento. ...................................................................... 17
Figura 3.5 Diagrama del circuito de acondicionamiento para el sensor de temperatura........................ 17
Figura 3.6 Diagrama eléctrico de circuito de acondicionamiento del sensor de humedad relativa......... 18
Figura 3.7 Diagrama eléctrico de circuito de acondicionamiento del anemómetro y la veleta............... 18
Figura 3.8 Curva Temperatura contra voltaje de salida de sensor interno del MSP430 .........................19
Figura 3.9 Circuito de conversión de niveles lógicos a RS232................................................................19
Figura 3.10 Conexiones del microcontrolador.........................................................................................20
Figura 3.11 Información de calibración del sensor de humedad............................................................. 23
Figura 3.12 – Entorno de desarrollo Gambas.......................................................................................... 30
Figura 3.13 – Captura de pantalla del programa de recepción.................................................................31
Figura 4.1 Gráfica de la temperatura interna y externa............................................................................46
Figura 4.2 Gráfica de la humedad relativa............................................................................................... 46
52
Índice de tablas
Tabla 3.1 Variables a medir por la estación meteorológica..................................................................... 11
Tabla 3.2 – Etapas del proceso de medición............................................................................................ 26
Tabla 3.3 - Listado de los menús de la estación meteorológica...............................................................27
Figura 3.4 - Etapas de la rutina de transmisión de datos..........................................................................28
Tabla 3.5 – Etapas del proceso de recepción en la PC.............................................................................31
Tabla 4.1 Resultados de las mediciones para la calibración de la medición interna............................... 32
Tabla 4.2 Resultados de las mediciones para la calibración de la medición interna............................... 33
Tabla 4.3 – Mediciones de la calibración de la velocidad del viento...................................................... 34
Tabla 4.4 Resultados de la prueba a la intemperie...................................................................................46
53
Apéndice A - Diagrama Eléctrico de la estación meteorológica
54
Apéndice B – Circuito impreso de la estación meteorológica
Fondo
Frente
55
56
Apéndice C – Listado del programa de la estación meteorológica
Modulo principal5.c
//
******************************************************************************************
// Programa principal de la estacion meteorologica
//
// Hecho por Miguelangel Fraga Aguilar
//
// ********************
// Version 0.1 20/JUL/04
// Proporciona el marco de referencia para el intercambio de tareas cooperativo, el control
// de la frecuencia de reloj Rc (DCO) e implementa un reloj de tiempo real por software
//
// Presupone que ACLK=32,768Hz, MCLK=SMCLK=DCO=1,048,576Hz
//
// En el ciclo principal se ejecuta cada 1000mS y llama a cada una de las tereas en orden y
// al final entra en modo de ahorro de energia.
// El reloj de tiempo real son 3 variables enteras que son actualizadas por la interrupci�
// del temporizador vigia que trabaja como temporizador de intervalo
// Para regular la frecueccia del DCO, esta se mide usando el temporizador A en modo
continuo
// y tomando com referencia la se�l del cristal de 32,768Hz. Si el valor medido es diferente
// de el deseado, entonces se modifica la frecuencia del DCO
//
// ***************************
// Version 0.2 04/agosto/2004
// Se conecta un teclado de cuatro teclas al puerto 1 bits 0 a 3
// Se detecta una pulsacion por medio de la interrupcion del puerto 1, de eliminan
// los rebotes por medio de un retardo usando el timer B.
//
// ***************************
// Version 0.3 10/agosto/04
// Cambia el periodo de la interrupcion de tiempo real de 1S a 250mS
// inclulle una version basica de la interfaz de usuario
//
// ***************************
// Version 0.3 20/agosto/04
// Portado a la version 3.2 del compilador IAR
// Inclulle una version basica de las rutinas de comunicaciones
// El reloj de tiempo real modifica el dia, mes y anio�
//
// ***************************
// Version 0.4 20/septiembre/04
// Modificada para poder compilase con GCC para poder sobrepasar el limite de 4KB de codigo
// del compilador IAR
//
// ***************************
// version 0.5 17/enero/06
// Se incluye la opción de llamar a un telefono celular dados las bajas tarifas en llamadas
de cel a cel
// El cambio principal se da en el archivo interfaz.c
// ****************************
// Version0.5.1 10/04/06
// Se corrigen varios problemas de comunicacion, la transmision se pasa de binaria a
// texto en hexadecimal. Se incluye control de flujo por hardware en la transmisión.
// Los cambios principales se dan en los archivos transmite.c y serie2.c
//******************************************************************************************
*
#ifndef GCC
#include <msp430x14x.h>
#else
57
#include <io.h>
#include <signal.h>
#endif
#include <stdio.h>
#include "lcdand.h"
#include "serie.h"
//Cabeceras de funciones
void Ajusta_DCO (void);
void interfaz(char tecla);
void programa_medicion(void);
void mide(void);
void transmite(void);
// Variables globales
// Reloj de tiempo real
char cuartos=0, segundos=0,minutos=0,horas=0;
char dia=0,mes=0, ano=0;
// Resultados de las ultimas mediociones
int
int
int
int
int
temp_i=0;
temp_e=0;
velocidad=0;
direccion=0;
humedad=0;
//Temperatura Interna C
//Temperatura Externa C
//Velocidad del Viento Km/Hr
//Direccion del viento
//Humedad relativa %
//varibles para el ADC
static unsigned int ADCresult,ADCresult2,ADCresult3,ADCresult4;
// Medicion de la velocidad del viento
unsigned T1,T2;
unsigned periodo;
char contseg;
//contador para saber cuando se excede el periodo maximo.
char banderas; // Varias banderas.
// Bit 0 - Indica que ya se detecto el primer flanco de subida
// Bit 1 - Indica que ya se detecto el segundo flanco de subida
// Banderas de teclado
unsigned char tecla;
//
/* Velocidad de capura
0 - cada 10 minutos
1 - cada hora
*/
char vel_cap=0;
/*badera paraindicar si se esta realizando una medicion*/
char midiendo =0;
/*variables que indican cuando se realizara la siguiente medicion*/
char hora_pro=0, minuto_pro=10;
int *puntero= (int *)0x1200;
//Inicio de la memoria Flash dedicada a almacenar datos
int transmitiendo=0; //indica cuando se esta realizando una transmision
int gsm=0;
//indica si el modem receptor es un modem analogico (0) o un celular GSM
(1)
// Telefono a marcar para transmitir los datos
char tel[17]="
";
//******************************************************************************
58
//Programa principal
int main(void)
{
WDTCTL = WDT_ADLY_250;
// WDT funciona como interval timer con periodo de
250mS
IE1 |= WDTIE;
// Habilita la interupci� del WDT
P1DIR = 0xF0;
// Programa P1.x como salidas
//Excepto los bits 0 a 3 que son las entradas del teclado
P1OUT = 0;
// borra P1.x
P2DIR = 0xFF;
// Programa P2.x como salidas
P2OUT = 0;
// borra P2.x
P3DIR = 0xDA;
// Programa P3.x como salidas
//Exepto los bits 0,2 y 5 que reciben informaci� del puerto serie
P3OUT = BIT3;
// borra P3.x, exepto P3.1
// El bit p3.1 =0 activa al MAX3222E para las comunicaciones serie
P3SEL |= 0x30;
// P3.4,5 = USART0 TXD/RXD
P5DIR = 0xFF;
// Programa P5.x como salidas
P5OUT = 0;
P5SEL=0;
P4DIR = 0xF7;
// Programa P4.x como salidas
//Exepto bit 3
P4OUT = 3;
// borra P4.x
//exepto bits 0 y 1 para mantener apagado la fuentes de 5V
// borra P5.x
P6DIR = 0xF8;
// Programa P6.x como salidas
//Exepto bits 0,1 y 2
P6OUT = 0;
// borra P6.x
//Preparacion del timer B para medir el periodo del anemometro y el retardo del teclado
TBCTL=TBSSEL_1+MC_2; // Selecciona ACLK como reloj, modo continuo
TBCCTL3=CM_1+CAP;//+CCIE; // Habilita captura, Captura en flanco de subida
// y habilita interrupcion de TBCCR3
banderas=0; //Indica que no se ha presentado ningun flanco
contseg=0; //Borra el contador de tiempo maximo
P4SEL=BIT3; //Asigna la terminal P4.3 Anemometro al timer
BCSCTL1=0X5;
DCOCTL=0X20;
Ajusta_DCO();
//inicializa el puerto serie 0. Puede quedar permanentemente activado ya que al pasar a
LPM3 se
//desactiva automaticamente. Solo el MAX3222E debe ser desactivado para ahorrar energia
//P3OUT &= ~ BIT1;
//Activa el MAX3222E
UCTL0 |= CHAR + SWRST;
// caracter de 8-bits , pone SWRST = 1
UTCTL0 |= SSEL1 + SSEL0; // + URXSE;
// UCLK = SMCLK, no activa deteccion de flanco
de inicio
UBR00 = 0x6D;
// 9600 a partir 1Mhz
UBR10 = 0x00;
UMCTL0 = 0x00;
// sin modulacion
ME1 |= UTXE0 + URXE0;
// activa los modulos TXD/RXD del USART0
UCTL0 &= ~SWRST;
// Inicializa el USART
IE1 |= URXIE0;
// habilita la interucion de RX del USART0
// Prepara las interrupciones del puerto 1 para esperar que se presione una tecla
P1IES&=0xF0; // Interrupcion en el flanco de bajada
P1IFG=0;
// Borra las interrupciones pendientes
P1IE|=0x0f;
// habilita interrupcion en los bits bajos de P1
_EINT();
// Enable interrupts
59
/*********************************************************************************
Ciclo Principal
*********************************************************************************/
while(1)
{
/*Si hay una tecla presionada, la envia a la rutina de interface de usuario
para que sea procesada*/
if(tecla!=0){
//putserial(tecla+'0'); //para depuracion
interfaz(tecla);
}
tecla=0;
mide();
transmite();
if((midiendo==0)&&(transmitiendo==0))
{
_BIS_SR(LPM3_bits);
// Entra al modo LPM3
}
else {
_BIS_SR(LPM0_bits);
// o al modo LPM0
}
}
return(0);
}
interrupt (WDT_VECTOR) watchdog_timer(void)
{
cuartos++;
if (cuartos>=4){
cuartos=0;
segundos++;
if(segundos >= 60){
segundos=0;
minutos++;
if(minutos>=60){
minutos=0;
horas++;
if(horas>=24)
horas=0;
dia++;
if ( (mes==1 && dia>31)||
(mes==2 && dia>28 && ano%4!=0)||
(mes==2 && dia>29 && ano%4==0)||
(mes==3 && dia>31)||
(mes==4 && dia>30)||
(mes==5 && dia>31)||
(mes==6 && dia>30)||
(mes==7 && dia>31)||
(mes==8 && dia>31)||
(mes==9 && dia>30)||
(mes==10 && dia>31)||
(mes==11 && dia>30)||
(mes==12 && dia>31) ){
dia=1;
mes++;
if(mes>12){
mes=1;
ano++;
}
}
}
60
}
}
_BIC_SR_IRQ(LPM3_bits);
// Clear LPM3 bits from 0(SR)
}
// Rutina de interrupcion del puerto 1
// Se activa al presionarsee un intrruptor del teclado
interrupt ( PORT1_VECTOR ) port1_ISR( void )
{
P1IFG=0; //Borra la bandera de interrupcion
P1IE=0; //Deshabilita las interrupciones de P1
//Programa una captura en 25mS para eliminar rebotes
TBCCR1=TBR+819; // 819=.025S*32768HZ= pulsos en 25mS
TBCCTL1|= CCIE;
}
//**************************************************************************
// ajusta el DCO a la frecuencia selecionada
// Usa el timer A para medir la frecuencia del DCO
// Trabaja por medio de escrutio y no de interrupciones por que a las frecuencias
// de MCLK y ACLK hacen que en el tiempo de captura sea menor que el de respuesta
// a una interrupcion.
// Por lo anterior esta rutina debe llamarse con las interrupciones desactivadas
void Ajusta_DCO (void)
{
#define DELTA 1024
// Frecuencia deseada en DCO = DELTA*(1024 HZ) = 1048576
//variables usadas para el control de la frecuencia del DCO
unsigned int Captura=0, Captura_Ant;
unsigned int cuenta_cap;
_DINT(); //Deshabilita las interrupciones
//configura el timer A
CCTL2 = CM_1 + CCIS_1 + CAP ;
// Captura en flanco de subida, entrada=ACLK
TACTL = TASSEL_2 + MC_2 + TACLR;
// reloj de TA=SMCLK, modo continuo, borrar TA
while(1){
//Ciclo infinito, se sale de el cuando se alcanza la frecuncia deseada
while (!(CCIFG & CCTL2));
// Espera a que ocurra una captura
CCTL2 &= ~CCIFG;
// ocurrio una captura, borra la bandera
Captura_Ant = CCR2;
// Almacena la captura actual
cuenta_cap = 0;
while (cuenta_cap < 32){ //Espera a que ocurran 32 capturas (32768/32=1024)
while (!(CCIFG & CCTL2));
// Espera a que ocurra una captura
CCTL2 &= ~CCIFG;
// ocurrio una captura, borra la bandera
cuenta_cap++;
}
Captura = CCR2;
// Lee el valor de la captura
Captura = Captura - Captura_Ant;
// Resta la captura anterior
if (( Captura>= DELTA-1) && (Captura<= DELTA+1)) break;
// Si es el valor
deseado, salir del ciclo
else if (DELTA < Captura)
{
DCOCTL--;
if (DCOCTL == 0xFF)
// el DCO esta muy rapido, bajar velocidad
{
if (!(BCSCTL1 == (XT2OFF + DIVA_3)))
BCSCTL1--;
// Se alcanzo la frec. menor?,
}
//
Seleccionar RSEL m� bajo
61
}
else
{
DCOCTL++;
// el DCO esta muy lento, aumentar velocidad
if (DCOCTL == 0x00)
{
if (!(BCSCTL1 == (XT2OFF + DIVA_3 + 0x07)))
BCSCTL1++;
// Se alcanzo la frecuencia mayor?
}
//
Escoger RSEL mas alta
}
} // fin del ciclo infinito
_EINT(); //habilita las interrupciones
CCTL2 = 0;
// detener CCR2
TACTL = 0;
// detner Timer_A
}
//ISR tic1
interrupt ( TIMERB1_VECTOR ) TIMERBISR( void )
{
unsigned char mascara,valor,i;
switch (TBIV)
{
case 2:
//CCR1
TBCCTL1&= ~CCIE; //Deshabilita la interrupci� del timer
mascara=1;
i=4;
valor=0;
if((P1IN&0x0f)==0)
{
// Ninguna tecla esta presionada, volver a esperar que se presione
// Prepara las interrupciones del puerto 1 para esperar que se presione una
tecla
P1IES&=0xF0;
P1IFG=0;
P1IE|=0x0f;
// Interrupcion en el flanco de subida
// Borra las interrupciones pendientes
// habilita interrupcion en los bits bajos de P1
}else
{
if ((P1IES&0x0f)==0){
//Si se comprobo que la tecla fue presionada, revisar de que teclas se trata
do{
valor++;
if( (P1IN & mascara)!=0) break;
i--;
mascara<<=1; //Corre la mascara para probar el siguiente bit
}while(i>0);
tecla=valor;
}
// Espera a que se libere la tecla
// Prepara las interrupciones del puerto 1 para esperar que se presione una
tecla
P1IES|=0x0F;
P1IFG=0;
P1IE|=0x0f;
// Interrupcion en el flanco de bajada
// Borra las interrupciones pendientes
// habilita interrupcion en los bits bajos de P1
}
break;
case 4: break; //CCR2
case 6: T2=TBCCR3;
if ((banderas & BIT0)==0){ //Si es el primer flanco
T1=T2;
banderas |= BIT0; //indica que ya paso el primer flanco
62
case
case
case
case
}
}else{ // Si es el segundo flanco de un periodo
periodo=T2-T1;
T1=T2;
banderas |= BIT1; //indica que ya hay una medici� lista para usarse
contseg=0; //Pone el contador de tiempo m�imo a cero
}
8: break; //CCR4
10: break; //CCR5
12: break; //CCR6
14: break; //TBOV
}
interrupt ( ADC_VECTOR ) ADC12ISR( void )
{
ADCresult = ADC12MEM0;
// Temperatura interna
ADCresult2 = ADC12MEM1;
// Temperatura externa
ADCresult3 = ADC12MEM2;
// Veleta
ADCresult4 = ADC12MEM3;
// Humedad
_BIC_SR_IRQ(LPM3_bits);
// Sale del modo LPM3
}
void programa_medicion(void)
{
if(vel_cap){
if(horas<23)hora_pro=horas+1;
else hora_pro=0;
minuto_pro=minutos;
}else{
minuto_pro=minutos+10;
if (minuto_pro>=60){
minuto_pro-=60;
if(horas<23)hora_pro=horas+1;
else hora_pro=0;
}else hora_pro=horas;
}
}
//******************************************************************************
//Escribe una palabra en la Flash revisando si es una direcci� valida y si es
//necesario borrar el segmento
void flash_write(int dato)
{
if(((unsigned int)puntero)< (0xDE00-1)){
//Si no se ha llegado al final de la memoria
if(((unsigned int)puntero & 0x1FF)==0){ //Si es el inicio de un segmento de 512Bytes
FCTL1 = FWKEY + ERASE;
// Activa el bit de borrado
FCTL3 = FWKEY;
// Borra el bit de bloqueo
*puntero = 0;
// falsa escritura para iniciar el borrado
}
FCTL3 = FWKEY;
// Borra el bit de bloqueo
FCTL1 = FWKEY + WRT;
// Activa el bit de escritura
*puntero++ = dato;
// Escribe el valor a la flash
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;
// Borra el bit de escritura
// Activa el bit de bloqueo de la FLASH
}
}
void mide(void)
{
static int etapa_med=0;
int X;
63
switch(etapa_med){
case 0:
if(hora_pro==horas)
if(minuto_pro==minutos){
P4OUT&=~BIT0; //enciende la fuente de los sensores
etapa_med++;
midiendo=1;
//Prepara la medicion de la vel. del viento,
banderas=0; //Indica que no se ha presentado ningun flanco
contseg=0; //Borra el contador de tiempo maximo
}
break;
case 1:
TBCCTL3|=CCIE; // Habilita la interrupcion por captura, Captura en flanco de subida
// Preparacion del convertidor analogico a digital
ADC12CTL0 = ADC12ON+MSC+REFON+REF2_5V+SHT0_6; // programa ADC12, ref., muestreo,
// Multiples conversiones
ADC12CTL1 = SHP+CONSEQ_1;
// Usa el temporizador de muestreo,
// una secuencia de conversiones
ADC12MCTL0 = INCH_10+SREF_1;
// Selecciona el canal A10, Vref+
ADC12MCTL1 = INCH_0+SREF_1;
// Selecciona el canal A0, Vref+
ADC12MCTL2 = INCH_1;
// Selecciona el canal A1 con AVCC como referencia
ADC12MCTL3 = INCH_2+EOS;
// Selecciona el canal A2, con AVCC
ADC12IE = 0x04;
// habilita las interrupciones con ADC12IFG.0
P6SEL=BIT0+BIT1+BIT2;
etapa_med++; //espera otros 250mS para que se estabilicen las fuentes
break;
case 2:
ADC12CTL0 |= ENC;
// habilita las conversiones conversions
ADC12CTL0 |= ADC12SC;
// inicia la conversion
_BIS_SR(LPM0_bits);
// Enter LPM0
// temp_i = (Vsensor - 986mV)/3.55mV
// Vsensor = (Vref)(ADCresult)/4095)
// temp_i -> ((ADCresult - 1615)*704)/4095
temp_i = ((((long)ADCresult-1608)*7145)/4095);
// temp_e = (Vsensor - 816mV)/10mV
// Vsensor = (2.5)(ADCresult2)/4095)
// temp_e -> ((ADCresult - 1365)*250)/4095
temp_e = ((((long)ADCresult2-1330)*2462)/4095);
// Convierte el voltaje de la veleta a grados.
direccion = ((((long)ADCresult3)*360)/4095);
// Convierte el voltaje del sensor de humedad a porcentaje.
humedad = (((unsigned long)ADCresult4-739)*161/4095);
//apagado del conversor A/D
ADC12CTL0 = 0;
ADC12CTL1 = 0;
ADC12IE = 0x0;
etapa_med++;
break;
case 3:
break; // se espera la medicion de la velocidad del viento
case 4:
// Escritura de los resultados en la Flash
_DINT(); //Deshabilita las interrupciones
64
FCTL2 = FWKEY + FSSEL0 + FN0;
// Escoge MCLK/2 como reloj del controlador de
FLASH
//Compacta la Hora para escribirla
X=horas<<6|minutos;
flash_write(X); //Escribe la hora
flash_write(temp_i); //Escribe la temperatutra interna
flash_write(temp_e); //Escribe la temperatura externa
_EINT(); //habilita las interrupciones
_NOP(); //para procesar las int. pendientes
_DINT(); //Deshabilita las interrupciones
flash_write(humedad); //humedad relativa
flash_write(direccion); //Escribe la direcci� del viento
flash_write(velocidad);//Escribe la velocidad del viento
FCTL2 = FWKEY;
// Escoge ACLK como reloj para ahorrar energia
_EINT(); //habilita las interrupciones
P4OUT|=BIT0;//Apaga los sensores
etapa_med=0;
//Termina la medicion
midiendo=0;
programa_medicion();
default:
break;
}
// Actualiza la velocidad del viento. Detecta cuando han pasado 3 seg.
// sin que se presenten interrupciones por el anemometo, lo que indica
// una velocidad del viento nula
contseg++;
_DINT(); //Deshabilita las interrupciones
if ((banderas & BIT1)!=0){
velocidad=(unsigned long)3705973/periodo;
if(etapa_med==3){ //se obtubo una medicion correcta de la velocidad
TBCCTL3&=~CCIE; // deshabilita la interrupcion� por captura
etapa_med++;
}
}
_EINT(); //habilita las interrupciones
if (midiendo && (contseg >=12)){
velocidad=0;
banderas=0;
if(etapa_med==3){ //se obtubo una medicion correcta de la velocidad
TBCCTL3&=~CCIE; // deshabilita la interrupcion por captura
etapa_med++;
}
}
}
Modulo interfaz2.c
//******************************************************************
// Archivo que contiene la parte de interfaz del usuario de
// la estación meteorologica
//
// **************************
// Version 0.2 17/enero/2006
// Modificado para incluir la opcion de llamar de celular a celular
//
65
#ifndef GCC
#include <msp430x14x.h>
#else
#include <io.h>
#include <signal.h>
#endif
#include <stdio.h>
#include "lcdand.h"
#define
#define
#define
#define
anterior 1
siguiente 2
entrar 3
escape 4
// Reloj de tiempo real
extern char cuartos, segundos,minutos,horas;
extern char dia,mes, ano;
// Resultados de las ultimas mediciones
extern
extern
extern
extern
extern
int
int
int
int
int
temp_i;
temp_e;
velocidad;
direccion;
humedad;
//Temperatura Interna C
//Temperatura Externa C
//Velocidad del Viento Km/Hr
//Direccion del viento
//Humedad relativa %
extern char vel_cap;
extern int transmitiendo; //indica cuando se esta realizando una transmision
extern int gsm; //indica si el modem receptor es analogico o un celular GSM
// Telefono a marcar para transmitir los datos
extern char tel[];
void programa_medicion(void); //del programa principal
void
char
void
char
interfaz(char);
accion(char n1,char n2,char tecla);
pinta_menu(char n1,char n2);
modifica(char *variable,char tecla, char max);
void borraln(void){
wrcad("
}
");
void interfaz(char tecla)
{
static char n1=0,n2=0,activo=0;
/*
n1 indica la seleccion menu principal, n2 es el submenu
0 indica que no hay nada selecionado
*/
const char max_submenu[7]={0,3,2,2,2,3,0};
if(!activo) {
/* Si no esta activo un submenu, entonces
determina la accion correpondiente a la tecla
dentro del sistema de menus*/
switch (tecla){
case anterior:
if(n1!=0){
if(n2==0) {
/*si no hay submenus*/
66
if(n1>1)n1--; /*va al menu anterior*/
else n1=6;
}else
if(n2>1) n2--;
/*va al submenu anterior*/
else n2=max_submenu[n1];
}
break;
case siguiente:
if(n1!=0){
if(n2==0) { /*si no hay submenus*/
if(n1<6)n1++; /*va al menu siguiente*/
else n1=1;
}else
if(n2<max_submenu[n1]) n2++;
/*va al submenu siguente*/
else n2=1;
}
break;
case entrar:
if(n1==0){
P4OUT&= ~BIT1; //enciende la fuente de la pantalla
n1=1;
activo=0;
//_BIS_SR(LPM0_bits);
lcd_init(); /*enciende la pantalla LCD*/
}else
if((n2!=0)||(max_submenu[n1]==0)){
/*si es un submenu valido,
ejecuta la accion correpondiente*/
if(n1!=6){
/*el parametro tecla=0 indica que
se acaba de selecionar el submenu*/
activo=accion(n1,n2,0);
if(activo) return;
}else{
n1=0;
n2=0;
P4OUT |= BIT1;
//programa_medicion();
}
}else n2=1;
break;
case escape:
n2=0;
activo=0;
break;
}
pinta_menu(n1,n2);
}else {
activo=accion(n1,n2,tecla);
if(!activo) pinta_menu(n1,n2);
}
}
void pinta_menu(char n1,char n2)
{
/*muestra los mensajes adecuados para el menu y submenu*/
switch(n1){
case 1:
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta ala primera linea del LCD
wrcad("Configurar fecha");
67
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
switch (n2){
case 0:
borraln();
break;
case 1:
wrcad("dia
");
break;
case 2:
wrcad("mes
");
break;
case 3:
wrcad("a\xeeo
");
break;
}
break;
case 2:
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta ala primera linea del LCD
wrcad("Configurar hora ");
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
switch (n2){
case 0: borraln();
break;
case 1: wrcad("Hora
");
break;
case 2: wrcad("Minutos
");
break;
}
break;
case 3:
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta ala primera linea del LCD
wrcad("Vel. de captura ");
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
switch (n2){
case 0: borraln();
break;
case 1: wrcad("Cada 10 minutos ");
break;
case 2: wrcad("Cada hora
");
break;
}
break;
case 4:
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta ala primera linea del LCD
wrcad("Ultimos result. ");
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
switch (n2){
case 0: borraln();
break;
case 1: wrcad("Temperatura y HR");
break;
case 2: wrcad("Vel. dir. viento");
break;
}
break;
case 5:
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta ala primera linea del LCD
wrcad("Transmite datos ");
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
switch (n2){
case 0: borraln();
break;
68
case 1: wrcad("A que telefono ");
break;
case 2: wrcad("transmitir ahora");
break;
case 3: wrcad("tipo modem
");
break;
}
break;
case 6:
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta ala primera linea del LCD
wrcad("Caputrar dtos
");
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
borraln();
break;
}
}
char cadena[20];
//******************************************************************************
void i2cad6(unsigned int n,char *cad)
{
unsigned int res,coc;
int i;
coc=n;
for(i=5;i>=0;i--){
res=coc%10;
coc=coc/10;
cad[i]=res|'0';
}
cad[6]=0;
}
/* imprime en la pantalla LCD la temperatuta interna, externa
y la humaedad realtiva*/
void wrTemp(void)
{
int X;
wrcom(LCD_SET_DD_RAM_ADDRESS);
if(temp_i>=0) X=temp_i;
else X=-temp_i;
i2cad6(X ,cadena+2);
cadena[0]='T';
cadena[1]='I';
cadena[2]='=';
if(temp_i<0)cadena[3]='-';
cadena[8]=cadena[7];
cadena[7]='.';
cadena[9]=0xdf;
cadena[10]=' ';
cadena[11]='H';
cadena[12]='=';
cadena[13]=humedad/10+'0';
cadena[14]=humedad%10+'0';
cadena[15]='%';
cadena[16]=0;
wrcad(cadena);
//apunta ala primera linea del LCD
69
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40);
if(temp_e>=0) X=temp_e;
else X=-temp_e;
i2cad6(X ,cadena+2);
cadena[0]='T';
cadena[1]='E';
cadena[2]='=';
if(temp_e<0)cadena[3]='-';
cadena[8]=cadena[7];
cadena[7]='.';
cadena[9]=0xdf;
cadena[10]=' ';
cadena[11]=' ';
cadena[12]=' ';
cadena[13]=' ';
cadena[14]=' ';
cadena[15]=' ';
cadena[16]=0;
wrcad(cadena);
//apunta a la segunda linea del LCD
}
/* imprime en la pantalla LCD la velocidad y direccion del viento*/
void wrViento(void)
{
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta ala primera linea del LCD
cadena[0]='D';
cadena[1]='V';
cadena[2]='=';
i2cad6((unsigned int)direccion ,cadena+3);
cadena[9]=0xdf;
cadena[10]=' ';
cadena[11]=' ';
cadena[12]=' ';
cadena[13]=' ';
cadena[14]=' ';
cadena[15]=' ';
cadena[16]=0;
wrcad(cadena);
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
cadena[0]='V';
cadena[1]='=';
i2cad6((unsigned int)velocidad ,cadena+2);
cadena[8]=cadena[7];
cadena[7]=cadena[6];
cadena[6]='.';
cadena[10]='K';
cadena[11]='m';
cadena[12]='/';
cadena[13]='H';
cadena[14]=' ';
cadena[15]=' ';
cadena[16]=0;
wrcad(cadena);
}
/******************************************************************
rutina que permite la modificacion del telefono
*****************************************************************/
int modifica_tel(char tecla)
{
static char pos;
70
switch(tecla){
case 0:
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
wrcad(tel);
pos=0;
return(1);
case anterior:
if(tel[pos]==' ')tel[pos]='0';
else if(tel[pos]<'9') tel[pos]++;
else tel[pos]=' ';
//imprime el telefono
wrcom(LCD_DISPLAY_ON);// hace que la pantalla oculte el cursor
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
wrcad(tel);
return(1);
case siguiente:
if(pos<15)
pos++;
else pos=0;
wrcom(LCD_DISPLAY_ON+2);// hace que la pantalla muestre el cursor
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40+pos); //apunta a la segunda linea del LCD
//columna pos
return(1);
case entrar:
//Tanto entrar com escape hacen que se salga modificando el telefono
case escape:
return(0);
}
return(0);
}
/******************************************************************
rutina que permite la modificacion del tipo de modem que va a
recibir los datos.
*****************************************************************/
int modifica_modem(char tecla)
{
static int valor;
switch(tecla){
case 0:
valor = gsm;
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
if(valor==0) wrcad("Analogico
");
else wrcad("GSM
");
return(1);
case anterior:
case siguiente:
//Tanto anterior como siguiente modifican el tipo de modem
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
if(valor==1){
wrcad("Analogico
");
valor=0;
}else{
wrcad("GSM
");
valor=1;
}
return(1);
case entrar:
gsm=valor;
case escape:
return(0);
}
71
return(0);
}
/******************************************************************
rutina que ejecuta la accion correspondiente a una tecla en un submenu
*/
char accion(char n1,char n2,char tecla)
{
switch(n1){
case 1:
//menu de configuración de fecha
switch(n2){
case 1: /* dia */
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta
wrcad("dia
");
return( modifica(&dia,tecla,31) );
case 2: /* mes */
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta
wrcad("mes
");
return( modifica(&mes,tecla,12) );
case 3: /* a�*/
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta
wrcad("a\xeeo
");
return( modifica(&ano,tecla,99) );
default:
break;
}
break;
case 2: //menu de configurcion de la hora
switch(n2){
case 1: /* hora */
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta
wrcad("hora
");
if(tecla==entrar) programa_medicion();
return( modifica(&horas,tecla,23) );
case 2: /* mes */
wrcom(LCD_SET_DD_RAM_ADDRESS);
//apunta
wrcad("minuto
");
if(tecla==entrar) programa_medicion();
return( modifica(&minutos,tecla,59) );
default:
break;
}
break;
ala primera linea del LCD
ala primera linea del LCD
ala primera linea del LCD
ala primera linea del LCD
ala primera linea del LCD
case 3: //menu de velocidad de captura
if(n2==1){
/*cambiar velocidad de muestreo a cada 10 min*/
vel_cap=0;
}else{
/*cambiar velocidad de muestreo a cada hora*/
vel_cap=1;
}
return (0);
case 4: //menu para mostrar ultimos resultados
if (n2==1){
/* mostrar tempreaturas y humedad rel.*/
wrTemp();
}else{
wrViento();
}
if( (tecla==entrar)||(tecla==escape) ) return (0);
else return(1);
case 5: //menu configuración de comunicacion
72
switch(n2){
case 1: /* hora */
wrcom(LCD_SET_DD_RAM_ADDRESS);
wrcad("telefono
");
return( modifica_tel(tecla) );
case 2: /* mes */
transmitiendo=1;
return (0);
case 3: /* hora */
wrcom(LCD_SET_DD_RAM_ADDRESS);
wrcad("tipo modem
");
return( modifica_modem(tecla) );
//apunta ala primera linea del LCD
//apunta ala primera linea del LCD
default:
break;
}
default: break;
}
return(1);
}
/* *************************************************************
rutina que permite modificar una variable de 2 digitos decimales
*/
char modifica(char *variable,char tecla, char max)
{
static char digitos[17];
static char pos;
int i;
switch(tecla){
case 0:
digitos[0]=(*variable)/10+'0';
digitos[1]=(*variable)%10+'0';
for(i=2;i<16;i++) digitos[i]=' ';
digitos[16]='\0';
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
wrcad(digitos);
pos=0;
return(1);
case anterior:
if(digitos[pos]<'9') digitos[pos]++;
else digitos[pos]='0';
if( ((digitos[0]&0x0F)*10+(digitos[1]&0x0F)) >max)
digitos[pos]='0';
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
wrcad(digitos);
return(1);
case siguiente:
if(pos==0){
pos=1;
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40+1);
//apunta a la segunda linea del LCD
//segunda columna
}else{
pos=0;
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40); //apunta a la segunda linea del LCD
}
return(1);
case entrar:
*variable= ((digitos[0]&0x0F)*10+(digitos[1]&0x0F));
case escape:
return(0);
73
}
return(0);
}
Modulo transmite.c
/*******************************************************************************************
*****
Rutina de transmision de datos para la estacion meteorologica
version 0.02 18/enero/2006
Se añade la opcion de llamadas de telefono GSM a Tel GSM
********************************************************************************************
****/
#ifndef GCC
#include <msp430x14x.h>
#else
#include <io.h>
#include <signal.h>
#endif
#include <string.h>
#include "serie.h"
#define
#define
#define
#define
etapa_tx1 3
etapa_tx2 4
etapa_error 5
etapa_final 6
char hexa[]="0123456789ABCDEF";
void Ajusta_DCO(void);
extern int *puntero; //Inicio de la memoria Flash dedicada a almacenar datos
extern int transmitiendo; //indica cuando se esta realizando una transmision
extern int gsm;
//vatiables para controlar la comunicación
int etapa_trans=0;
char recibido[30];
int indice=0,tiempo=0;
extern char tel[];
int espera_respuesta(void)
{
tiempo ++;
while(!serial_vacio()){
recibido[indice]=getserial();
tiempo=0;
if((recibido[indice]=='\r')||(recibido[indice]=='\n')){
recibido[indice]='\0';
return(0); //ya se tiene una respuesta
}
if( indice<29 ) indice++;
}
if(tiempo>120){ //se excedio el tiempo de espera, error
etapa_trans=etapa_error;
//return(1);
}
return(1); //Todavia se debe esperar una respuesta
}
void transmite(void)
{
74
static int *puntero_tx;
int dato,t;
static int i,suma,tamano;
switch(etapa_trans){
case 0:
//inicia la transmicion� reseteando el modem
if(transmitiendo){
P3OUT&=~BIT3; //Enciende /DTR
Ajusta_DCO(); //ajusta la frecuencia del oscilador
//RC para asegurar la vel. del puerto serie
etapa_trans++;
//limpia el buffer de recepcion
while(!serial_vacio())getserial();
if(gsm==0) wrcadserial("ATZ\r\r\n");
else wrcadserial("AT+CBST=71,0,1\r\r\n");
tiempo=0;
indice=0;
}
break;
case 1: //espera por "OK"
if( espera_respuesta() )return; //termina si se supero
//el tiempo de espera
//revisa que la respuesta se a correcta.
if((indice>=2) && (tiempo==0))
if(strcmp(recibido,"OK")==0){
etapa_trans++;
wrcadserial("ATD");
wrcadserial(tel);
wrcadserial("\r\r\n");
//limpia el buffer de recepcion
while(!serial_vacio()) getserial();
tiempo=0;
}
indice=0;
i=0;
return;
case 2: //espera por "CONNECT"
if( espera_respuesta() )return; //termina si se supero
//el tiempo de espera
//revisa que la respuesta sea la correcta.
i++;
if(i>=3)
i=0;
if((indice>=7) && (tiempo==0))
recibido[7]='\0';
if(strcmp(recibido,"CONNECT")==0){
etapa_trans++;
puntero_tx=(int *)0x1200; //inicia la transmision al comienzo
// de la memoria de datos
//limpia el buffer de recepcion
while(!serial_vacio()) getserial();
tiempo=0;
}
indice=0;
return;
case etapa_tx1://transmite un bloque de maximo 120 palabras
tamano=puntero-puntero_tx;
75
if(tamano>120)tamano=120;
t=tamano&0xf;
putserial(hexa[t]); //Transmite el tamano�del bloque
t=(tamano>>4)&0xf;
putserial(hexa[t]);
t=(tamano>>8)&0xf;
putserial(hexa[t]);
t=(tamano>>12)&0xf;
putserial(hexa[t]);
suma=0;
for(i=0;i<tamano;i++){
//transmite un dato
dato=(*puntero_tx);
t= dato &0xf;
putserial(hexa[t]);
t=(dato>>4)&0xf;
putserial(hexa[t]);
t=(dato>>8)&0xf;
putserial(hexa[t]);
t=(dato>>12)&0xf;
putserial(hexa[t]);
suma+=dato;
puntero_tx++;
}
t=suma&0xf;
putserial(hexa[t]); //Transmite la suma de comprobacion
t=(suma>>4)&0xf;
putserial(hexa[t]);
t=(suma>>8)&0xf;
putserial(hexa[t]);
t=(suma>>12)&0xf;
putserial(hexa[t]);
etapa_trans=etapa_tx2;
tiempo=0;
return;
case etapa_tx2: //espera la confirmación de recepción sin errores por la PC
tiempo ++;
if(!serial_vacio()){
tiempo=0;
if(getserial()=='X'){//hubo un error, retransmitir el bloque
puntero_tx-=tamano;
}
etapa_trans=etapa_tx1;
if(puntero_tx>=puntero){
//si no faltan datos por transmitir
//envia el indicador de terminacion de transmision
//tamano=500
wrcadserial("4F10");
puntero_tx=puntero=(int *)0x1200;
etapa_trans=etapa_final;
}
}
if(tiempo>15){ //se excedio el tiempo de espera, error
etapa_trans=etapa_error;
return;
}
76
//while(!serial_vacio()) getserial();
return;
case etapa_error: //Indica
//putserial('X');
wrcadserial("X\r\n");
//putserial(0X7F);
etapa_trans++;
break;
que ocurrio un error en la transmision
case etapa_final: //La transmision termino
etapa_trans++;
i=0;
//putserial('+');
break;
case (etapa_final+1):
if(i<15)
i++;
else{
etapa_trans++;
i=0;
}
//wrcadserial("+++");
break;
case (etapa_final+2):
etapa_trans++;
//putserial('+');
wrcadserial("+++");
i=0;
break;
case (etapa_final+3): //retardo para que se reconosca la secuencia de escape
if(i<15)
i++;
else{
etapa_trans++;
i=0;
}
break;
case (etapa_final+4): //La transmision termino
etapa_trans++;
wrcadserial("ATH\r\n");
break;
case (etapa_final+5): //La transmision termino
etapa_trans=0;
transmitiendo=0;
P3OUT|=BIT3; //apaga /DTR
break;
}
}
Modulo lcdadn2.c
/***************************************************************
lcdand.c Libreria de funciones para escribir a una pantalla LCD
77
Alfanumerica inteligente (ej. AND491)conectada al puerto P4 y P5
del MSP430 de la siguiente forma:
MPS430
AND491
P5.4
-D4
P5.5
-D5
P5.6
-D6
P5.7
-D7
P4.5
-RS
P4.6
-R/W
P4.7
-E
Esta version solo utiliza cuatro bits de datos
*****************************************************************/
#ifndef GCC
#include <msp430x14x.h>
#else
#include <io.h>
#include <signal.h>
#endif
#include "lcdand.h"
/*Escribe un comando con RS=0*/
void wrcom(unsigned char comando)
{
P4OUT&= ~(BIT5+BIT6+BIT7); //RS=0,R/W=0, E=0
P5OUT=(comando&0xF0)|(P5OUT&0x0F); //Escribe la parte alta
P4OUT|=BIT7; //Da un pulso en alto en E, E=1
P4OUT&= ~BIT7;// E=0
P5OUT=(comando<<4)|(P5OUT&0x0F); //Escribe la parte baja
P4OUT|=BIT7; //Da un pulso en alto en E, E=1
P4OUT&= ~BIT7;// E=0
}
/*Escribe un dato con RS=1*/
void wrdat(unsigned char comando)
{
P4OUT&= ~(BIT6+BIT7); //RS=1,R/W=0, E=0
P4OUT|= BIT5;
P5OUT=(comando&0xF0)|(P5OUT&0x0F); //Escribe la parte alta
P4OUT|=BIT7; //Da un pulso en alto en E, E=1
P4OUT&= ~BIT7;// E=0
P5OUT=(comando<<4)|(P5OUT&0x0F); //Escribe la parte baja
P4OUT|=BIT7; //Da un pulso en alto en E, E=1
P4OUT&= ~BIT7;// E=0
}
void lcd_init(void)
{
volatile int i;
P5OUT=0;
P5DIR=0xFF; //Programa el puerto P5 como salidas
P4OUT&= ~(BIT5+BIT6+BIT7);
P4DIR|=(BIT5+BIT6+BIT7);
//Programa P4.5 a P4.7 como salidas.
for (i = 2000; i>0; i--);
wrcom(LCD_FUNCTION_SET4);
for (i = 2000; i>0; i--);
// retardo
wrcom(LCD_FUNCTION_SET4+8); //Indica el numero de lineas en la pant.
78
for (i = 8000; i>0; i--);
wrcom(LCD_FUNCTION_SET4+8);
for (i = 1000; i>0; i--);
wrcom(LCD_DISPLAY_ON);
wrcom(LCD_DISPLAY_CLEAR);
wrcom(LCD_ENTRY_MODE_SET);
for (i = 1000; i>0; i--);
// retardo
//Indica el numero de lineas en la pant.
// retardo
}
void wrcad(char *p)
{
while(*p){
wrdat(*p);
p++;
}
}
Modulo serie2.c
#ifndef GCC
#include <msp430x14x.h>
#else
#include <io.h>
#include <signal.h>
#endif
#include "serie.h"
/* Buffer de salida -- buffer circular FIFO de 64 bytes
#define BUFSIZE (512)
#define BUFSIZE_RX 128
*/
unsigned char buffer[BUFSIZE];
volatile unsigned char * bufin = buffer;
volatile unsigned char * bufout = buffer;
unsigned inicio,fin;
unsigned char bufferI[BUFSIZE_RX];
int serial_vacio(void)
{
return(inicio==fin);
}
inline void mete(unsigned char c)
{
if (fin >=inicio) {
if (fin<BUFSIZE_RX) {
bufferI[fin]=c;
fin++;
}else
if (inicio>0){
bufferI[fin]=c;
fin=0;
}
} else if ((fin+1)<inicio){
bufferI[fin]=c;
fin++;
}
}
inline unsigned char saca()
{
unsigned char t;
if (inicio==fin)
79
t=0;
else {
t=bufferI[inicio];
if (inicio<BUFSIZE_RX)
inicio++;
else inicio=0;
}
return t;
}
unsigned char getserial(void) {
unsigned char result;
result = saca();
return result;
}
void putserial(unsigned char val) {
int used;
do {
used = bufin - bufout;
if ( used < 0 ) used += BUFSIZE;
if ( used < BUFSIZE-1 ) {
break;
}
_BIS_SR(LPM0_bits);
} while ( 1 ); /* loop until break */
*bufin++ = val;
if ( bufin == buffer+BUFSIZE ) {
bufin = buffer;
}
/* Make sure transmitter interrupt enabled */
IE1 |= UTXIE0;
// Enable USART0 TX interrupt
}
void wrcadserial(char *p)
{
while(*p){
putserial(*p);
p++;
}
}
#ifdef GCC
interrupt ( UART0RX_VECTOR ) usart0_rx( void )
#else
#if __VER__ < 200
interrupt [ UART0RX_VECTOR ] void usart0_rx( void )
#else
#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx( void )
#endif
#endif
{
mete(RXBUF0);
}
#ifdef GCC
interrupt (UART0TX_VECTOR) usart0_tx( void )
#else
#if __VER__ < 200
interrupt [ UART0TX_VECTOR ] void usart0_tx( void )
#else
#pragma vector=UART0TX_VECTOR
__interrupt void usart0_tx( void )
#endif
#endif
80
{
if ( bufin == bufout ) {
/* terminado -- desactiva la interrupcion del transmisor */
IE1 &= ~ UTXIE0;
IFG1 |= UTXIFG0;
} else {
_EINT(); //habilita las interrupciones
while((P3IN&4)!=0); //espera a que CTS=1
_DINT(); //habilita las interrupciones
TXBUF0 = *bufout++;
if ( bufout == buffer+BUFSIZE ) {
bufout = buffer;
}
}
}
Modulo prueba6.c
//******************************************************************************
// Program para llevar un reloj de tiempo real, medir la velocidad y
// dirección del viento, Temperatura interna con el sensor integrado
// y la externa con un sensor LM35.
// Supone que esta conectado en la terminal P4.3(TB3)
// un inerrruptor activado cada vez que un anemometro de 5cm de radio da una
// revolución. En la terminal P6.1 se conecta un potenciometro sin tope
// acoplado a una veleta para indicar la dirección del viento.
// En P6.2 se conecta un sensor de humedad Honeywell IH-3610-1
// Humedad relativa= (Vout-0.921)/0.0316
// Tambien supone un cristal de 32765Hz en las terminales XIN y XOUT.
// Las mediciones se muestran cada segundo y se enciende un led en P1.0
// mientras se estan realizando.
//
//
MSP430F149
//
--------------//
/|\|
XIN|//
| |
| 32kHz
//
--|RST
XOUT|//
|
|
// VELETA-|P6.1
P1.0|-->LED
//
|
P4.3|--< Anemometro
// LM35>--|P6.0
P6.3|--< Humedad
// +833mV |
|
//
//
// La conversión de frecuencia (Hz o Rev/S) a vel (Km/hr) es
// vel = (2*pi*r*f(m/s)*60(s/min)*60(min/hr) /1000(m/Km)
// Para r=.05m
// vel = 1.13097*f
//
// El rango de velocidad deseado es de 1 a 400 Km/Hr, 0.884 a 353Hz
// prueba5.c ya muestra la velocidad del viento, Además almacena los resultados en la Flash
// en el rango de 0x1200 a 0xEFFF (56,832 bytes - 55.5KB, 111 segmentos de 512 bytes)
//******************************************************************************
#include
#include
#include
#include
<msp430x14x.h>
<stdio.h>
<lcdand.h>
<serie.h>
int segundos,minutos,horas;
static unsigned int ADCresult,ADCresult2,ADCresult3,ADCresult4;
static long int grados,DegC, DegC2;
81
unsigned T1,T2;
unsigned periodo;
char contseg;
//contador para saber cuando se excede el periodo maximo.
char banderas; // Varias banderas.
// Bit 0 - Indica que ya se detecto el primer flanco de subida
// Bit 1 - Indica que ya se detecto el segundo flanco de subida
unsigned long velocidad;
unsigned humedad;
static int *puntero;
//******************************************************************************
void imphora(char *cad)
{
int res,coc;
res=horas%10;
coc=horas/10;
cad[0]=coc|'0';
cad[1]=res|'0';
cad[2]=':';
res=minutos%10;
coc=minutos/10;
cad[3]=coc|'0';
cad[4]=res|'0';
cad[5]=':';
res=segundos%10;
coc=segundos/10;
cad[6]=coc|'0';
cad[7]=res|'0';
cad[8]=0;
}
//******************************************************************************
void i2cad6(unsigned int n,char *cad)
{
unsigned int res,coc;
int i;
coc=n;
for(i=5;i>=0;i--){
res=coc%10;
coc=coc/10;
cad[i]=res|'0';
}
cad[6]=0;
}
//******************************************************************************
//Escribe una palabra en la Flash revisando si es una dirección valida y si es
//necesario borrar el segmento
void flash_write(int dato)
{
if(((unsigned int)puntero)< (0xF000-1)){
//Si no se ha llegado al final de la memoria
if(((unsigned int)puntero & 0x1FF)==0){ //Si es el inicio de un segmento de 512Bytes
FCTL1 = FWKEY + ERASE;
// Activa el bit de borrado
FCTL3 = FWKEY;
// Borra el bit de bloqueo
*puntero = 0;
// falsa escritura para iniciar el borrado
}
FCTL3 = FWKEY;
// Borra el bit de bloqueo
82
FCTL1 = FWKEY + WRT;
*puntero++ = dato;
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;
// Activa el bit de escritura
// Escribe el valor a la flash
// Borra el bit de escritura
// Activa el bit de bloqueo de la FLASH
}
}
//******************************************************************************
//Programa principal
void main(void)
{
char cadena[20];
unsigned X,i;
WDTCTL = WDT_ADLY_1000;
// WDT funciona como interval timer con periodo de
1S
IE1 |= WDTIE;
// Habilita la interupción del WDT
P1DIR = 0xFF;
// Programa P1.x como salidas
P1OUT = 0;
// borra P1.x
P2DIR = 0xFF;
// Programa P2.x como salidas
P2OUT = 0;
// borra P2.x
P3DIR = 0xDA;
// Programa P3.x como salidas
//Exepto los bits 0,2 y 5
P3OUT = 2;
// borra P3.x
// El bit p3.1 =0 activa al MAX3222E para las comunicaciones serie
P5DIR = 0xFF;
// Programa P5.x como salidas
P5OUT = 0;
P5SEL=0;
P4DIR = 0xF7;
// Programa P4.x como salidas
//Exepto bit 3
P4OUT = 0;
// borra P4.x
//exepto bits 0 y 1 para mantener apagado la fuentes de 5V
// borra P5.x
P6DIR = 0xF8;
// Programa P6.x como salidas
//Exepto bits 0,1 y 2
P6OUT = 0;
// borra P6.x
puntero=(int *)0x1200;
//
P1SEL |= BIT4;
//Inicio de la memoria Flash dedicada a almacenar datos
//programa la terminal P1.4 para sacar la señal SMCLK
/* Preparación del convertidor analogico a digital */
ADC12CTL0 = ADC12ON+MSC+REFON+REF2_5V+SHT0_6; // programa ADC12, ref., muestreo,
// Multiples conversiones
ADC12CTL1 = SHP+CONSEQ_1;
// Usa el temporizador de muestreo,
// una secuencia de conversiones
ADC12MCTL0 = INCH_10+SREF_1;
// Selecciona el canal A10, Vref+
ADC12MCTL1 = INCH_0+SREF_1;
// Selecciona el canal A0, Vref+
ADC12MCTL2 = INCH_1;
// Selecciona el canal A1 con AVCC como referencia
ADC12MCTL3 = INCH_2+EOS;
// Selecciona el canal A2, con AVCC
// y marca el final de la secuencia.
P6SEL=BIT0+BIT1+BIT2;
/*Preparación del puerto serie 0 como UART*/
UCTL0 = CHAR;
// caracter de 8-bit
UTCTL0 = SSEL0;
// UCLK = ACLK
UBR00 = 0x0D;
// 32k/2400 = 13.65 (Velocidad de TX y RX)
UBR10 = 0x00;
//
UMCTL0 = 0x6B;
// modulacion
ME1 |= UTXE0 + URXE0;
// habilita USART0 TXD/RXD
IE1 |= URXIE0;
// habilita la interrupcion de RX USART0
P3SEL |= 0x30;
// P3.4,5 = USART0 TXD/RXD
83
//Preparación del timer B para medir el periodo del anemometro
TBCTL=TBSSEL_1+MC_2+TBIE; // Selecciona ACLK como reloj, modo continuo
// y habilita interrupciones
TBCCTL3=CM_1+CAP+CCIE; // Habilita captura, Captura en flanco de subida
// y habilita interrupción de TBCCR3
banderas=0; //Indica que no se ha presentado ningun flanco
contseg=0; //Borra el contador de tiempo maximo
P4SEL=BIT3; //Asigna la terminal P4.3 al timer
for(i=25000;i>0;i--);
lcd_init();
_EINT();
// Enable interrupts
ADC12IE = 0x04;
ADC12CTL0 |= ENC;
// Enable ADC12IFG.0
// Enable conversions
segundos=0;
minutos=0;
horas=0;
while(1)
{
_BIS_SR(LPM3_bits);
P1OUT |= 0x01;
imphora(cadena);
wrcom(LCD_SET_DD_RAM_ADDRESS);
// Entra al modo LPM3
// Enciende el LED en P1.0
//apunta ala primera linea del LCD
//wrcad(cadena);
wrcadserial(cadena);
putserial(' ');
//wrdat(' ');
ADC12CTL0 |= ADC12SC;
_BIS_SR(LPM3_bits);
// Start conversion
// Enter LPM3
//
//
//
DegC = (Vsensor - 986mV)/3.55mV
Vsensor = (Vref)(ADCresult)/4095)
DegC -> ((ADCresult - 1615)*704)/4095
DegC = ((((long)ADCresult-1615)*7040)/4095);
//
//
//
DegC = (Vsensor - 816mV)/10mV
Vsensor = (2.5)(ADCresult2)/4095)
DegC -> ((ADCresult - 1337)*250)/4095
DegC2 = ((((long)ADCresult2-1337)*2500)/4095);
//
Convierte el voltaje de la veleta a grados.
grados = ((((long)ADCresult3-0)*360)/4095);
//
Convierte el voltaje del sensor de humedad a porcentaje.
humedad = (((10*(unsigned long)ADCresult4-7392))/253);
if(DegC>=0) X=DegC;
84
else X=-DegC;
i2cad6(X ,cadena+2);
cadena[0]='T';
cadena[1]='I';
cadena[2]='=';
if(DegC<0)cadena[3]='-';
cadena[8]=cadena[7];
cadena[7]='.';
cadena[9]='°';
cadena[10]=' ';
cadena[11]=0;
wrcadserial(cadena);
cadena[9]=0xDF;
wrcad(cadena);
wrcom(LCD_SET_DD_RAM_ADDRESS+0x40);
//apunta a la segunda linea del LCD
cadena[1]='E';
if(DegC2>=0) X=DegC2;
else X=-DegC2;
i2cad6(X ,cadena+2);
cadena[2]='=';
if(DegC2<0)cadena[3]='-';
cadena[8]=cadena[7];
cadena[7]='.';
cadena[9]='°';
cadena[10]=' ';
cadena[11]=0;
wrcadserial(cadena);
cadena[9]=0xDF;
wrcad(cadena);
cadena[0]='D';
cadena[1]='V';
cadena[2]='=';
i2cad6((int)grados ,cadena+3);
cadena[9]='°';
cadena[10]=0;
wrcadserial(cadena);
putserial(' ');
contseg++;
if ((banderas & BIT1)!=0){
velocidad=(unsigned long)3705973/periodo;
}
if (contseg >=3){
velocidad=0;
banderas=0;
}
cadena[0]='V';
cadena[1]='=';
i2cad6((unsigned int)velocidad ,cadena+2);
cadena[8]=cadena[7];
cadena[7]=cadena[6];
cadena[6]='.';
cadena[10]='K';
cadena[11]='m';
cadena[12]='/';
cadena[13]='H';
cadena[14]=0;
wrcadserial(cadena);
putserial(' ');
85
cadena[0]='H';
cadena[1]='R';
cadena[2]='=';
i2cad6((int)humedad ,cadena+3);
cadena[9]='%';
cadena[10]=0;
wrcadserial(cadena);
putserial('\r');
// Escritura de los resultados en la Flash
_DINT(); //Deshabilita las interrupciones
FCTL2 = FWKEY + FSSEL0 + FN0;
// Escoge MCLK/2 como reloj del controlador de FLASH
//Compacta la Hora para escribirla
X=horas<<6+minutos;
flash_write(X); //Escribe la hora
flash_write(DegC); //Escribe la temperatutra interna
flash_write(DegC2); //Escribe la temperatura externa
flash_write(grados); //Escribe la dirección del viento
flash_write(velocidad);//Escribe la velocidad del viento
FCTL2 = FWKEY;
// Escoge ACLK como reloj para ahorrar energia
_EINT(); //habilita las interrupciones
P1OUT &= ~0x01;
// Clear P1.0 LED off
}
}
interrupt[WDT_VECTOR] void watchdog_timer (void)
{
segundos++;
if(segundos >= 60){
segundos=0;
minutos++;
if(minutos>=60){
minutos=0;
horas++;
if(horas>=24)
horas=0;
}
}
_BIC_SR_IRQ(LPM3_bits);
// Clear LPM3 bits from 0(SR)
}
interrupt[ADC_VECTOR] void ADC12ISR (void)
{
ADCresult = ADC12MEM0;
// Temperatura interna
ADCresult2 = ADC12MEM1;
// Temperatura externa
ADCresult3 = ADC12MEM2;
// Veleta
ADCresult4 = ADC12MEM3;
// Humedad
_BIC_SR_IRQ(LPM3_bits);
// Sale del modo LPM3
}
//ISR tic1
interrupt[TIMERB1_VECTOR] void TIMERBISR (void)
{
switch (TBIV)
{
case 2: break; //CCR1
86
case 4: break; //CCR2
case 6: T2=TBCCR3;
if ((banderas & BIT0)==0){ //Si es el primer flanco
T1=T2;
banderas |= BIT0; //indica que ya paso el primer flanco
}else{ // Si es el segundo flanco de un periodo
periodo=T2-T1;
T1=T2;
banderas |= BIT1; //indica que ya hay una medición lista para usarse
contseg=0; //Pone el contador se tiempo máximo a cero
}
case 8: break; //CCR4
case 10: break; //CCR5
case 12: break; //CCR6
case 14: break; //TBOV
}
}
Modulo serie.h
#ifndef _serie_
#define _serie_
int serial_vacio(void);
unsigned char getserial(void);
void putserial(unsigned char val);
void wrcadserial(char *p);
#endif
Modulo lcdand.h
/***************************************************************
lcdand.h Libreria de funciones para escribir a una pantalla LCD
Alfanumerica inteligente (ej. AND491)conectada al puerto P2 y P5
del MSP430 de la siguiente forma:
MPS430
AND491
P5.0
-D0
P5.1
-D1
P5.2
-D2
P5.3
-D3
P5.4
-D4
P5.5
-D5
P5.6
-D6
P5.7
-D7
P2.0
-RS
P2.1
-R/W
P2.2
-E
*****************************************************************/
#ifndef LCDAND
#define LCDAND
//Declaracion de constantes
#define LCD_FUNCTION_SET8 0x30 //Establece la comunicación con 8 bits de datos
#define LCD_FUNCTION_SET4 0x20 //Establece la comunicación con 4 bits de datos
#define LCD_DISPLAY_ON 0x0C // Activa el display
#define LCD_DISPLAY_CLEAR 0x01 // Limpia el display
#define LCD_ENTRY_MODE_SET 0x06 // Establece el modo de entrada de datos
#define LCD_SET_DD_RAM_ADDRESS 0x80 // Estable la direccion donde se escribiran los datos
87
//hay que sumarle la direccion de 7 bits
/*Escribe un comando con RS=0*/
void wrcom(unsigned char comando);
/*Escribe un dato con RS=1*/
void wrdat(unsigned char comando);
void lcd_init(void);
void wrcad(char *p);
#endif
Modulo interfaz.h
void
char
void
char
interfaz(char);
accion(char n1,char n2,char tecla);
pinta_menu(char n1,char n2);
modifica(char *variable,char tecla, char max);
Modulo serialport.form
# Gambas Form File 1.0
{ FSerialPort Form
MoveScaled(39.25,7.125,51.625,73.625)
'Move(314,57,413,589)
Text = ("Serial Port")
{ TextLabel1 TextLabel
MoveScaled(1,2,21,3)
'Move(8,16,168,24)
Text = ("Port Name :")
}
{ TxtPort TextBox
MoveScaled(23,2,15,3)
'Move(184,16,120,24)
Text = ("/dev/ttyS0")
}
{ TextLabel2 TextLabel
MoveScaled(1,6,21,3)
'Move(8,48,168,24)
Text = ("Speed :")
}
{ CmbSpeed ComboBox
MoveScaled(23,6,15,1)
'Move(184,48,120,8)
Text = ("")
ReadOnly = True
List = ("1200\n2400\n9600\n19200\n38400")
}
{ TextLabel3 TextLabel
MoveScaled(1,10,21,3)
'Move(8,80,168,24)
Text = ("Parity :")
}
{ TextLabel4 TextLabel
MoveScaled(1,14,21,3)
'Move(8,112,168,24)
88
Text = ("Data Bits :")
}
{ TextLabel5 TextLabel
MoveScaled(1,18,21,3)
'Move(8,144,168,24)
Text = ("Stop Bits :")
}
{ CmbParity ComboBox
MoveScaled(23,10,15,1)
'Move(184,80,120,8)
Text = ("")
ReadOnly = True
List = ("None\nEven\nOdd")
}
{ CmbData ComboBox
MoveScaled(23,14,15,1)
'Move(184,112,120,8)
Text = ("")
ReadOnly = True
List = ("8\n7\n6\n5")
}
{ CmbStop ComboBox
MoveScaled(23,18,15,1)
'Move(184,144,120,8)
Text = ("")
ReadOnly = True
List = ("1\n2")
}
{ Button1 Button
MoveScaled(22,22,16,3)
'Move(176,176,128,24)
Text = ("Open")
}
{ TxtSend TextBox
MoveScaled(1,38,43,3)
'Move(8,304,344,24)
Text = ("")
}
{ Button2 Button
MoveScaled(45,38,6,3)
'Move(360,304,48,24)
Text = ("CR")
}
{ TextArea1 TextArea
MoveScaled(1,42,50,8)
'Move(8,336,400,64)
Text = ("")
Wrap = True
}
{ ChkDSR CheckBox
MoveScaled(39,14,11,3)
'Move(312,112,88,24)
Text = ("DSR")
}
{ ChkDTR CheckBox
MoveScaled(39,2,11,3)
'Move(312,16,88,24)
Text = ("DTR")
}
{ ChkRTS CheckBox
MoveScaled(39,5,11,3)
'Move(312,40,88,24)
Text = ("RTS")
}
{ ChkCTS CheckBox
MoveScaled(39,8,11,3)
89
'Move(312,64,88,24)
Text = ("CTS")
}
{ ChkDCD CheckBox
MoveScaled(39,11,11,3)
'Move(312,88,88,24)
Text = ("DCD")
}
{ ChkRNG CheckBox
MoveScaled(39,17,11,3)
'Move(312,136,88,24)
Text = ("RNG")
}
{ Label1 Label
MoveScaled(1,27,15,3)
'Move(8,216,120,24)
Text = ("Flow control :")
}
{ ComboBox1 ComboBox
MoveScaled(18,27,20,2)
'Move(144,216,160,16)
Text = (" ")
ReadOnly = True
List = ("NONE\nCRTSCTS\nXON/XOFF\nCRTSCTS + XON/XOFF")
}
{ SPort #SerialPort
#X = 320
#Y = 176
}
{ CheckBox1 CheckBox
MoveScaled(29,32,19,2)
'Move(232,256,152,16)
Text = ("conexión via celular")
Value = True
}
{ CheckBox2 CheckBox
MoveScaled(4,32,22,3)
'Move(32,256,176,24)
Text = ("Emular modem")
}
{ Timer1 #Timer
#X = 128
#Y = 536
Delay = 2500
}
{ TextEtapa TextBox
MoveScaled(37,67,9,3)
'Move(296,536,72,24)
Text = ("0")
}
{ TextLabel6 TextLabel
MoveScaled(28,67,9,3)
'Move(224,536,72,24)
Text = ("etapa")
}
{ TextRecibe TextArea
MoveScaled(1,52,50,14)
'Move(8,416,400,112)
Text = ("")
}
}
Modulo serialport.class
90
' Gambas class file
'PRIVATE Sport AS SerialPort
'PUBLIC SUB Form_Open()
' Sport=NEW SerialPort AS "Sport"
'END
PRIVATE
PRIVATE
PRIVATE
PRIVATE
PRIVATE
PRIVATE
PRIVATE
PRIVATE
PRIVATE
etapa AS Integer
dato AS Integer
buffer[27000] AS Integer
indice AS Integer
tam AS Integer
i AS Integer
suma AS Long
cadena AS String
escape AS Boolean
PUBLIC SUB Form_Close()
IF Sport.Status = Net.Active THEN CLOSE Sport
END
PUBLIC SUB Check_Status()
ChkDSR.Value
ChkDTR.Value
ChkCTS.Value
ChkRTS.Value
ChkDCD.Value
ChkRNG.Value
=
=
=
=
=
=
Sport.DSR
Sport.DTR
Sport.CTS
Sport.RTS
Sport.DCD
Sport.RNG
END
PUBLIC SUB Button1_Click()
DIM j AS Integer
IF Sport.Status = Net.Active THEN
CLOSE Sport
Button1.Text = "Open"
ELSE
' Line parameters
Sport.PortName = TxtPort.Text
Sport.Speed = CmbSpeed.Text
Sport.Parity = CmbParity.Index
Sport.DataBits = CmbData.Text
Sport.StopBits = CmbStop.Text
' keep DTR on
Sport.FlowControl = ComboBox1.Index
Sport.Open()
Check_Status()
TextArea1.Text = "Port Opened : " & Sport.PortName & " Settings : " &
Sport.Speed & "," & Sport.Parity & "," & Sport.DataBits & "," &
Sport.StopBits & Chr(13) & Chr(10)
Button1.Text = "Close"
etapa = 0
TextEtapa.Text = Str(etapa)
'retardo
Timer1.Delay = 2500
Timer1.Enabled = TRUE
TextRecibe.Text = ""
ENDIF
END
91
PUBLIC SUB SPort_Read()
DIM s AS String
DIM cade2 AS String
DIM n AS Long
DIM chksum AS Integer
DIM linea AS String
DIM hfile AS File
DIM j AS Integer
DIM k AS Integer
DIM salir AS Boolean
cade2 = ""
READ #Sport, s, Lof(Sport)
cadena = cadena & s
TextRecibe.Text = TextRecibe.Text & s
IF checkbox2.Value AND (etapa < 3) THEN
'si se esta emulando un modem, hacer eco de los caracteres recibidos
PRINT #Sport, s;
END IF
salir = FALSE
IF Left(S, 1) = "X" THEN
TextArea1.Text = "Error de en la recepcion"
etapa = 0
TextEtapa.Text = Str(etapa)
cadena = ""
ENDIF
WHILE ((Len(cadena) > 0) AND ( NOT salir))
WHILE (Asc(cadena, 1) = 13) OR (Asc(cadena, 1) = 10)
cadena = Right(cadena, -1)
WEND
SELECT etapa
CASE 0
salir = TRUE
FOR k = 1 TO Len(cadena)
IF (Asc(cadena, k) = 13) OR (Asc(cadena, k) = 10) THEN
cade2 = Left(cadena, k - 1)
cadena = Right(cadena, - k)
salir = FALSE
BREAK
END IF
NEXT
IF checkbox2.Value THEN
'espera el comando de atencion y responde simulando un modem
IF Upper$(Left$(cade2, 3)) = "ATZ" THEN
PRINT #Sport, "OK"; Chr(13); Chr$(13); Chr$(10);
etapa = 1
TextEtapa.Text = Str(etapa)
borra_buffer()
ENDIF
ELSE
'espera OK del modem
IF Upper$(Left$(cade2, 2)) = "OK" THEN
etapa = 1
TextEtapa.Text = Str(etapa)
ELSE
IF cade2 <> "" THEN
salir = FALSE 'revisa si hay mas caracteres leidos
ENDIF
92
ENDIF
ENDIF
TextArea1.Text = cade2
CASE 1
cade2 = ""
salir = TRUE
FOR k = 1 TO Len(cadena)
IF (Asc(cadena, k) = 13) OR (Asc(cadena, k) = 10) THEN
cade2 = Left(cadena, k - 1)
cadena = Right(cadena, - k)
salir = FALSE
BREAK
END IF
NEXT
IF checkbox2.Value THEN
'espera el comando de atencion y responde simulando un modem
IF Upper$(Left$(cade2, 3)) = "ATD" THEN
PRINT #Sport, "CONNECT 19400"; Chr(13); Chr$(13); Chr$(10);
etapa = 3
TextEtapa.Text = Str(etapa)
cadena = ""
TextArea1.Text = cade2
ELSE
IF cade2 <> "" THEN
salir = FALSE 'revisa si hay mas caracteres leidos
ENDIF
ENDIF
ELSE
'espera el indicador de llamada del modem y ordena contestar
IF Upper$(Left$(cade2, 4)) = "RING" THEN
cadena = ""
TextArea1.Text = cade2
'PRINT #Sport, "A";
Timer1.Delay = 500
Timer1.Enabled = TRUE
ELSE
IF cade2 <> "" THEN
salir = FALSE 'revisa si hay mas caracteres leidos
ENDIF
ENDIF
ENDIF
CASE 2
salir = TRUE
FOR k = 1 TO Len(cadena)
IF (Asc(cadena, k) = 13) OR (Asc(cadena, k) = 10) THEN
cade2 = Left(cadena, k - 1)
cadena = Right(cadena, - k)
salir = FALSE
BREAK
END IF
NEXT
'espera "CONNECT" del Modem
IF Upper$(Left$(cade2, 7)) = "CONNECT" THEN
etapa = 3
TextEtapa.Text = Str(etapa)
TextArea1.Text = TextArea1.Text & cade2
borra_buffer()
93
ELSE
'IF (Upper$(Left$(cade2, 10)) = "NO CARRIER") OR (Upper$(Left$(cade2, 2)) = "OK")
THEN
IF (Upper$(Left$(cade2, 10)) = "NO CARRIER") THEN
'fallo la coneccion reiniciar el proceso
etapa = 0
TextEtapa.Text = Str(etapa)
TextArea1.Text = TextArea1.Text & cade2
Timer1_Timer()
ELSE
IF cade2 <> "" THEN
salir = FALSE 'revisa si hay mas caracteres leidos
ENDIF
END IF
ENDIF
'TextArea1.Text = TextArea1.Text & cade2
CASE 3
'En esta etapa se recibe el tamaño del bloque o el indicador de fin de transmision
IF Len(cadena) >= 4 THEN
n = ascii2hex(Asc(cadena, 1)) + ascii2hex(Asc(cadena, 2)) * 16
n = n + ascii2hex(Asc(cadena, 3)) * 256 + ascii2hex(Asc(cadena, 4)) * 4096
etapa = 4
TextEtapa.Text = Str(etapa)
tam = n AND 65535
suma = 0
i = 0
'TextArea1.Text = TextArea1.Text & "recibiendo " & Str$(n) & " datos" & Chr(10) &
Chr(13)
cadena = Right$(cadena, -4)
IF tam = 500 THEN 'se termino la recepcion
'Envia el comado de colgar despues de un retardo
Timer1.Delay = 2000
Timer1.Enabled = TRUE
etapa = 10
TextEtapa.Text = Str(etapa)
'Guarda los datos recibidos en un archivo csv para poderlos pasar a excel
OPEN "/home/mfraga/datos.csv" FOR WRITE CREATE AS #hfile
FOR j = 0 TO indice - 1
SELECT (j + 1) MOD 6
CASE 1
linea = Str(Int(buffer[j] / 64)) & ":" & Str(buffer[j] AND 63) & ","
CASE 2
linea = linea & Str(buffer[j] / 10.0) & ","
CASE 3
linea = linea & Str(buffer[j] / 10.0) & ","
CASE 4
linea = linea & Str(buffer[j] / 100.0) & ","
CASE 5
linea = linea & Str(buffer[j]) & ","
CASE 0
linea = linea & Str(buffer[j] / 100.0)
PRINT #hfile, linea
END SELECT
NEXT
CLOSE #hfile
94
borra_buffer()
cadena = ""
s = ""
TextArea1.Text = TextArea1.Text & Chr(13) & Chr(10)
TextArea1.Text = TextArea1.Text & "Se termino la recepcion"
ELSE
TextArea1.Text = "recibiendo " & Str$(n) & " datos"
TextArea1.Text = TextArea1.Text & Chr(13) & Chr(10)
IF tam = 0 THEN
etapa = 5
TextEtapa.Text = Str(etapa)
ENDIF
ENDIF
ELSE
salir = TRUE
ENDIF
CASE 4
'se reciben los datos del bloque
WHILE (Len(cadena) >= 4)
IF i < tam THEN
n = ascii2hex(Asc(cadena, 1)) + ascii2hex(Asc(cadena, 2)) * 16
n = n + ascii2hex(Asc(cadena, 3)) * 256 + ascii2hex(Asc(cadena, 4)) * 4096
buffer[indice] = n 'almacena el valor aceptado
indice = indice + 1
suma = suma + n
TextArea1.Text = TextArea1.Text & Str$(n) & " "
cadena = Right$(cadena, -4)
i = i + 1
ELSE
etapa = 5
TextEtapa.Text = Str(etapa)
BREAK
ENDIF
WEND
IF etapa = 4 THEN
salir = TRUE
END IF
CASE 5
'Recibe el CheckSum y lo verifica, confirma la recepcion de los datos
IF Len(cadena) >= 4 THEN
n = ascii2hex(Asc(cadena, 1)) + ascii2hex(Asc(cadena, 2)) * 16
n = n + ascii2hex(Asc(cadena, 3)) * 256 + ascii2hex(Asc(cadena, 4)) * 4096
chksum = n AND 65535
TextArea1.Text = TextArea1.Text & Chr(13) & Chr(10)
TextArea1.Text = TextArea1.Text & "checsum= " & Str$(n)
cadena = Right$(cadena, -4)
IF (suma AND 65535) = chksum THEN
PRINT #Sport, "U";
etapa = 3
TextEtapa.Text = Str(etapa)
ELSE
PRINT #Sport, "X";
etapa = 3
TextEtapa.Text = Str(etapa)
cadena = ""
indice = indice - tam
ENDIF
ELSE
salir = TRUE
ENDIF
95
CASE 10, 11, 12 'etapa de colgado
cadena = ""
cade2 = ""
END SELECT
WEND
END
PUBLIC SUB SPort_RNGChange(iVal AS Boolean)
ChkRng.Value = iVal
END
PUBLIC SUB SPort_DTRChange(iVal AS Boolean)
ChkDTR.Value = iVal
END
PUBLIC SUB SPort_DSRChange(iVal AS Boolean)
ChkDSR.Value = iVal
END
PUBLIC SUB SPort_CTSChange(iVal AS Boolean)
ChkCTS.Value = iVal
END
PUBLIC SUB SPort_DCDChange(iVal AS Boolean)
ChkDCD.Value = iVal
END
PUBLIC SUB SPort_RTSChange(iVal AS Boolean)
ChkRTS.Value = iVal
END
PUBLIC SUB Button2_Click()
IF Sport.Status = Net.Inactive THEN
Message("Open port first!")
ELSE
'WRITE #Sport,TxtSend.Text & Chr(13) & Chr(10), txtSend.Length + 2
PRINT #Sport, txtSend.Text; Chr$(13); Chr$(10);
END IF
END
PUBLIC SUB ChkDTR_Click()
Sport.DTR = ChkDTR.Value
Check_Status
END
PUBLIC SUB ChkRTS_Click()
Sport.RTS = ChkRTS.Value
Check_Status
END
PUBLIC SUB ComboBox1_Click()
IF Sport.Status = Net.Inactive THEN
Sport.FlowControl = ComboBox1.Index
END IF
END
96
PUBLIC SUB Form_Open()
cmbSpeed.Index = cmbSpeed.Find("9600")
ComboBox1.Index = ComboBox1.Find("CRTSCTS")
etapa = 0
END
PUBLIC SUB borra_buffer()
DIM j AS Integer
FOR j = 0 TO 26999
buffer[j] = 0
NEXT
indice = 0
END
PUBLIC FUNCTION ascii2hex(t AS Integer) AS Integer
IF (t >= Asc("0")) AND (t <= Asc("9")) THEN
RETURN t AND 15
ELSE
IF (t >= Asc("A")) AND (t <= Asc("F")) THEN
RETURN t - Asc("A") + 10
ELSE
IF (t >= Asc("a")) AND (t <= Asc("f")) THEN
RETURN t - Asc("a") + 10
ELSE
RETURN 0
END IF
END IF
END IF
END
PUBLIC SUB Timer1_Timer()
SELECT etapa
CASE 0, 2
Timer1.Enabled = FALSE
IF checkbox2.Value = FALSE THEN
'si no se esta emulando un modem
IF checkbox1.Value THEN
'Inicializa el modem celular
PRINT #Sport, "AT+CBST=71,0,1"; Chr$(13); Chr$(10);
ELSE
'Inicializa el modem analogico
PRINT #Sport, "ATZ"; Chr$(13); Chr$(10);
ENDIF
ENDIF
CASE 1
PRINT #Sport, "ATA"; Chr$(13); Chr$(10);
etapa = 2
TextEtapa.Text = Str(etapa)
Timer1.Enabled = FALSE
CASE 10
'Envia la secuencia de escape para colgar
PRINT #Sport, "+++";
etapa = 11
97
TextEtapa.Text = Str(etapa)
CASE 11
PRINT #Sport, "ATH"; Chr$(13); Chr$(10);
etapa = 12 'descarta la respuesta del modem
TextEtapa.Text = Str(etapa)
CASE 12
'PRINT #Sport, "ATH"; Chr$(13); Chr$(10);
etapa = 0 'regresa a reinicializar el modem
TextEtapa.Text = Str(etapa)
END SELECT
END
98
Descargar