5 de junio de 2015

Midiendo los fríos y calores

En esta ocasión presentaremos una manera de medir la temperatura ambiente usando Python, Arduino, y un sensor.


El hardware

Para este proyecto usaremos el sensor TMP36. Esta es la descripción oficial de dicho componente:
El TMP36 es un sensor de precisión y bajo voltaje que permite medir la temperatura en grados centígrados. La salida de voltaje provista es linealmente proporcional a la temperatura en grados Celsius. No requiere ninguna calibración externa para proporcionar una precisión típica de ± 2 °C. Este sensor es muy fácil de usar, basta con conectarlo a tierra y a un voltaje de entre 2.7 y 5.5 voltios y se podrá comenzar a tomar lecturas por el correspondiente pin de salida. El factor de escala de salida es de 10 milivoltios por grado Celsius.
Este sensor es relativamente económico, tiene un costo aproximado de 2.00 USD. Físicamente se ve así:

Sensor de temperatura TMP36.

Tal como se pudo apreciar en la descripción de arriba, el TMP36 tiene tres pines. Viendo el componente de frente a su parte plana:
  • El pin de la izquierda (Vs) se conecta al voltaje.
  • El pin central (Vout) se conecta a un pin de entrada analógica del Arduino.
  • El pin de la derecha (GND) se conecta a tierra.
La siguiente figura muestra el TMP36 con los nombres de sus pines:


El diagrama de abajo elaborado con Fritzing muestra la manera de conectar el sensor con el Arduino:

Vista de protoboard Fritzing para
el sensor de temperatura.

La siguiente foto muestra como se ven físicamente las conexiones de nuestros componentes electrónicos:

Vista física del sensor de temperatura TMP36
conectado al Arduino.

El software

Para escribir el programa que controlará nuestro hardware tenemos primero que seguir las mismas instrucciones presentadas en “Cómo programar a tu Arduino”. Si aún no le hemos hecho, debemos descargar Firmata en el Arduino e instalar la biblioteca pyFirmata en la computadora anfitriona.

NOTA: Todo el código presentado aquí fue probado con Python 3.4.

Las instrucciones para importar el paquete pyfirmata y crear el objeto que representa nuestra placa (board) de Arduino son las usuales:
import pyfirmata

placa = pyfirmata.Arduino('/dev/ttyACM0')
No hay que olvidar ajustar la cadena de caracteres que indica el puerto serie que utiliza nuestra plataforma ('/dev/ttyACM0' en mi caso, ya que estoy usando Linux) para poder conectarse al Arduino.

Dado que vamos a utilizar un pin de entrada es necesario crear un thread iterador, de lo contrario la placa puede seguir enviando datos por la conexión serial hasta producir un desbordamiento. Para crear dicho thread usamos la siguiente instrucción:
pyfirmata.util.Iterator(placa).start()
A continuación asignamos a la variable entrada el objeto asociado al pin 0 analógico (a) de entrada in (i) del Arduino:
entrada = placa.get_pin('a:0:i')
Posteriormente debemos invocar el método enable_reporting() sobre la entrada para poder leer las señales recibidas:
entrada.enable_reporting()
Ahora solo queda leer el estado del sensor usando el método read() sobre el objeto entrada:
v = entrada.read()
El valor devuelto por el método read() depende del voltaje presente en el pin de entrada analógica. Este voltaje va de 0 a 5 voltios, sin embargo el método read() devuelve un valor ajustado entre 0.0 y 1.0. Multiplicaremos v por 5 para tener el valor de lectura en voltios, ya que así lo requiere una fórmula que usaremos más adelante.

Una cosa extraña que sucedió al estar realizando diversas pruebas fue que el método read() devuelve None la primera vez que se invoca dentro de un programa. La documentación no menciona razón alguna por lo que pudiera estar sucediendo esto. Para evitar problemas conviene entonces colocar un instrucción if para manejar este caso.

Según la ficha técnica del TMP36, la fórmula para convertir un voltaje V leído del pin Vout a una temperatura C en grados Celsius es:
C =  100 (V 0.5)
Conociendo el valor de C podemos usar la siguiente fórmula si nos interesa conocer la temperatura en grados Fahrenheit:
F = 1.8 (C) + 32
Para facilitar la legibilidad del programa colocaremos dentro de una función la implementación de cada una de las fórmulas de arriba. El siguiente programa completo realiza la lectura de la temperatura ambiente cada 10 segundos:
#!/usr/bin/env python3
# Archivo: temperatura.py

import pyfirmata
from datetime import datetime

PAUSA = 10 # Número de segundos entre tomas de lectura
           # de temperatura.

placa = pyfirmata.Arduino('/dev/ttyACM0')

pyfirmata.util.Iterator(placa).start()

entrada = placa.get_pin('a:0:i')
entrada.enable_reporting()

def volts_to_celsius(v):
    """Convierte un voltaje v obtenido de un sensor
       TMP36 a grados Celsius.
    """
    return 100 * (v - 0.5)

def celsius_to_fahrenheit(c):
    """Convierte c grados Celsius a grados Ffahrenheit.
    """
    return 1.8 * c + 32

try:
    while True:
        d = datetime.now()
        v = entrada.read()
        if v != None:
            v *= 5 # Convertir el valor devuelto por
                   # read() a voltios.

            c = volts_to_celsius(v)
            f = celsius_to_fahrenheit(c)
            print('{}, {:.3f} V, {:.2f} °C, {:.2f} °F'
                  .format(d, v, c, f))
            placa.pass_time(PAUSA)

except KeyboardInterrupt:
    # Terminar programa cuando se presione Ctrl-C.
    pass

finally:
    placa.exit()
Para correr el programa debemos tener el Arduino conectado por el puerto USB a la computadora anfitriona y ejecutar el siguiente comando desde una terminal en el mismo directorio donde se encuentra el archivo temperatura.py:
python3 temperatura.py
La salida del programa debe ser similar a lo siguiente:
2015-06-05 18:14:41.819863, 0.743 V, 24.30 °C, 75.74 °F
2015-06-05 18:14:51.819918, 0.743 V, 24.30 °C, 75.74 °F
2015-06-05 18:15:01.819973, 0.743 V, 24.30 °C, 75.74 °F
2015-06-05 18:15:11.820032, 0.748 V, 24.80 °C, 76.64 °F
2015-06-05 18:15:21.820090, 0.743 V, 24.30 °C, 75.74 °F
2015-06-05 18:15:31.820148, 0.743 V, 24.30 °C, 75.74 °F
2015-06-05 18:15:41.820206, 0.757 V, 25.75 °C, 78.35 °F
2015-06-05 18:15:51.820263, 0.762 V, 26.25 °C, 79.25 °F
2015-06-05 18:16:01.820322, 0.772 V, 27.20 °C, 80.96 °F
2015-06-05 18:16:11.820378, 0.772 V, 27.20 °C, 80.96 °F
2015-06-05 18:16:21.820432, 0.762 V, 26.25 °C, 79.25 °F
2015-06-05 18:16:31.820502, 0.752 V, 25.25 °C, 77.45 °F
2015-06-05 18:16:41.820568, 0.752 V, 25.25 °C, 77.45 °F
2015-06-05 18:16:51.820625, 0.748 V, 24.80 °C, 76.64 °F
2015-06-05 18:17:01.820692, 0.748 V, 24.80 °C, 76.64 °F
2015-06-05 18:17:11.820746, 0.748 V, 24.80 °C, 76.64 °F
...
Por ahí del séptimo renglón de la salida se nota un incremento importante en la temperatura ambiente. Esto se debe a que coloqué en ese momento mi dedo encima del sensor durante aproximadamente medio minuto. Una vez que retiré mi dedo se puede observar un decremento en la temperatura hasta llegar nuevamente a valores cercanos a los del inicio del programa.

El programa termina al presionar Ctrl-C.

No hay comentarios.:

Publicar un comentario