Ir al contenido principal

Proyecto IoT: Sensor de temperatura wifi con Wifly y DHT11

Hace tiempo que tengo un sensor de temperatura y humedad DTH11 dando vueltas por los cajones, así que ha llegado el momento de probarlo. Junto con un Arduino y un módulo Wifly, voy a mostraros un sensor de temperatura y humedad que envíe datos periódicamente por WiFi a un servidor. Es la base de cualquier proyecto enmarcado en el Internet de las cosas (IoT).

Wifly y DHT11

El sensor DHT11

Este sensor es muy barato y fácil de usar, así que es perfecto para un pequeño proyecto como éste. El siguiente esquema sacado del datasheet del fabricante muestra cómo ha de conectarse el sensor.

Conexión DHT11

Se puede encontrar en versión de tres y cuatro patillas. En la versión de cuatro, una simplemente está desconectada y no se utiliza. Además de los dos pines de alimentación (a 5V), la información se transmite por un único pin conectado al microcontrolador a través de una resistencia pull-up de 5K. En mi diseño he añadido un condensador entre VCC y GND para filtrar la entrada de alimentación. En la fotografía de la cabecera se ve el montaje completo en la protoboard.

Módulo Wifly

Para enviar los datos al servidor tenemos varias opciones como Bluetooth o GSM. Pero como tenía un módulo Wifly a mano, lo haremos por WiFi. Esta basado en el chip RN-171, que está muy probado y es bastante robusto. Además de tener una gran cantidad de funcionalidades. En este proyecto sólo vamos a mostrar su uso más básico, para el cuál sólo necesitamos cuatro conexiones, dos para la alimentación (a 3.3V) y otras dos para al comunicación serie (TX y RX). Si ya has trabajado con un módulo XBee, Wifly es totalmente compatible a nivel de conexiones, por lo que podrías sustituir uno por otro sin tener que modificar el resto del circuito.

Wifly

Montaje con Arduino

El montaje del sensor DHT11 y Wifly con Arduino se muestra en el siguiente esquema. Como ves no hay nada fuera de lo común, lo único más delicado es la conexión del módulo Wifly, cuyas patillas son más pequeñas y están más juntas de lo habitual, lo que es un poco problemático para conectarlo con cables dupont, pero forzando un poquito no hay mayor problema.

Esquema

El sensor se alimenta de la salida de 5V del Arduino, cuya patilla central por donde van los datos de temperatura he conectado al pin 7 del Arduino. El módulo Wifly lo he conectado al pin de 3.3V del Arduino (cuidado con no conectarlo al de 5V si no queréis freír el módulo Wifly). Los pines RX y TX del Wifly se pueden conectar directamente a los pines RX y TX de Arduino (pines 0 y 1), pero yo he preferido usar un puerto serie por software (pines 2 y 3) y dejar libre el puerto serie nativo para depurar la comunicación con el Wifly. El montaje completo queda así.

Montaje

Funcionamiento

El código encargado de de leer el sensor y enviar los datos por el puerto serie al Wifly es el siguiente.

#include "DHT.h"
#define DHTPIN 7 // Pin
// Tipo de sensor
#define DHTTYPE DHT11   // DHT 11 
// Inicializar sensor
DHT dht(DHTPIN, DHTTYPE);
  SoftwareSerial wifly(2, 3); // RX, TX
  void setup() {
  	Serial.begin(9600); // usamos serial normal para debug
   	wifly.begin(9600);
  	dht.begin();
  	// Preparar Wifly
  	delay(5000); // esperamos a que wifly esté listo
  	wifly.print("$$");  // entrar en modo comando
  	delay(1000);
  	wifly.println("join myssid");  // nos asociamos al ssid
  	delay(2000);
  	wifly.println("set com remote 0");  // evitar que se envíe la cadena HELLO al servidor
  	delay(1000);
  }

void loop() { float h = dht.readHumidity(); float t = dht.readTemperature(); // por defecto en Celsius // Comprobar si hay error if (isnan(h) || isnan(t) ) { Serial.println("Error de lectura en el sensor"); return; } // Calculo de la sensación térmica // float hic = dht.computeHeatIndex(t, h, false); wifly.println("open 172.26.0.9 8080"); // abrimos conexión al servidor web delay(1000); wifly.println("GET /readsensor?t="+String(t,2)+"&h="+String(h,2)+" HTTP/1.1"); wifly.println();

delay(60000); // leer cada minuto wifly.print("$$"); }

En la función setup() se inicializa el sensor DHT11 y se realiza la conexión del módulo Wifly a la red WiFi. En este caso es una red WiFi abierta y sin protección, por lo que no es necesario establecer la clave de cifrado. Para conectar a una red WiFi cifrada habrá que realizar algún paso más que puede consultarse en el manual de WiFly.

Una vez en marcha, la función loop() lee cada minuto el valor de temperatura y humedad del sensor y se envía al servidor como una petición GET mediante HTTP. El servidor, como veremos enseguida, registra cada petición y almacena los datos. Quiero hacer notar que este código es ilustrativo y que no es válido para un sistema en producción ya que, además de no ser muy óptimo (entre otras cosas por ese delay de un minuto), tampoco se comprueban errores de comunicación o se chequea el estado del módulo Wifly.

Como servidor web se podría haber usado Apache con PHP, Tomcat con Java o cualquier otra alternativa. Para simplificar he usado el pequeño servidor web que trae Python (para un sistema en producción habría que usar algo más serio). El código es el siguiente:

#!/usr/bin/python
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import urlparse
import datetime

	PORT_NUMBER = 8080
    datos=[]
    
    class myHandler(BaseHTTPRequestHandler):
	
  	# Manejador para peticiones GET
    def do_GET(self):
      if "readsensor" in self.path:
        o = urlparse.urlparse(self.path)
	params = urlparse.parse_qs(o.query)
	t = params["t"][0]
	h = params["h"][0]
	now = datetime.datetime.now()
	datos.append([str(now.hour)+":"+str(now.minute), t, h]);
		
	self.send_response(200)
	self.send_header('Content-type','text/html')
	self.end_headers()
	self.wfile.write('Temperatura: '+t)
	self.wfile.write('<BR>Humedad: '+h)
	self.wfile.write("<BR>OK!")
	return
      else:
	# gerenar datos
	muestra = "['Hora', 'Temperatura', 'Humedad'],"
	for d in datos:
	  muestra=muestra + "['"+d[0]+"',"+d[1]+","+d[2]+"],"
      self.send_response(200)
	self.send_header('Content-type','text/html')
	self.end_headers()
	self.wfile.write("""
	  <html>
	  <head>
	    <a href="https://www.gstatic.com/charts/loader.js">https://www.gstatic.com/charts/loader.js"></a>
	    <script type='text/javascript'>
		google.charts.load('current', {'packages':['corechart']});
		google.charts.setOnLoadCallback(drawChart);
        function drawChart() {
		  var data = google.visualization.arrayToDataTable([""" + muestra +"""]);
          var options = {
		    title: 'Registro humedad/temperatura',
		    curveType: 'function',
		    legend: { position: 'bottom' }
		  };
          var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
		  chart.draw(data, options);
		 }
		</script>
	  </head>
	  <body>
		<div id='curve_chart' style='width: 900px; height: 500px'></div>
	  </body>
	</html>
	""");
try:
  server = HTTPServer(('', PORT_NUMBER), myHandler)
  print 'Iniciando servidor HTTP en puerto ' , PORT_NUMBER
  server.serve_forever()
  except KeyboardInterrupt:
  print 'CTRL+C: Saliendo...'
  server.socket.close()

Se utiliza la librería BaseHTTPServer de Python para crear el servidor web escuchando en el puerto 8080. En el manejador de peticiones se distinguen dos tipos, si se trata de una lectura del sensor (es una llamada GET con readsensor en la URL) se almacena la información. En caso contrario se muestra una gráfica en pantalla con las mediciones. Para generar la gráfica he optado por la librería Javascript Google Charts.

Lecturas de temperatura con DHT11

Más allá del prototipo

Para ir un paso más allá, además de mejorar el software tanto en el Arduino como en el servidor, habría que hacer algunas mejoras. De entrada, eliminar el Arduino y sustituirlo por un Atmega328P junto con su circuitería en una placa de circuito impreso. En lugar del módulo Wifly usaríamos un RN171 también en la placa, y probablemente con una antena externa. Finalmente, nos queda el asunto de la alimentación. Tanto si vamos a usar una pila como alimentación a través de un transformador o incluso una fuente de alimentación, necesitaremos al menos un regulador de tensión tipo 7805 para obtener los 5V para el sensor. Para obtener los 3.3V del RN171, podemos usar un 7833 o, si queremos ahorrárnoslo, un divisor de tensión para obtener 3.3V a partir del 7805. Pues con esto y una bonita caja, ya estaría listo nuestro dispositivo IoT.

Comentarios

Entradas populares de este blog

Creando firmas de virus para ClamAV

ClamAv es un antivirus opensource y multiplataforma creado por Tomasz Kojm muy utilizado en los servidores de correo Linux. Este antivirus es desarrollado por la comunidad, y su utilidad práctica depende de que su base de datos de firmas sea lo suficientemente grande y actualizado. Para ello es necesario que voluntarios contribuyan activamente aportando firmas. El presente artículo pretende describir de manera sencilla cómo crear firmas de virus para ClamAV y contribuir con ellas a la comunidad.

Ingeniería inversa de un parche de Microsoft Windows

A estas alturas ya hemos asumido que la seguridad total en Internet es, cuanto menos, un mito. Ningún software está libre de vulnerabilidades, y por mucha auditoría, test de intrusión o pruebas de fuzzing que nos empeñemos en hacer, ninguna metodología puede demostrar sin lugar a dudas que un software es 100% seguro. Ante este panorama, hay dos tendencias mayoritarias a la hora de hacer públicas las vulnerabilidades. Por un lado, están los que piensan que cuando se descubre un fallo ha de hacerse público de forma inmediata. En este escenario, la publicación de una vulnerabilidad es el pistoletazo de salida para una carrera entre el desarrollador para sacar el parche y los "malos" para lograr explotarla. Esta política es conocida como full disclosure . Por otro lado, tenemos a los siguen una política responsible disclosure , que abogan por mantener la vulnerabilidad en secreto hasta la salida del parche por parte del desarrollador. Sin entrar en cuestiones filosóficas que no...

Manejo de grafos con NetworkX en Python

El aprendizaje computacional es un área de investigación que en los últimos años ha tenido un auge importante, sobre todo gracias al aprendizaje profundo (Deep Learning). Pero no todo son redes neuronales. Paralelamente a estas técnicas, más bien basadas en el aprendizaje de patrones, también hay un auge de otras técnicas, digamos, más basadas en el aprendizaje simbólico. Si echamos la vista algunos años atrás, podemos considerar que quizá, la promesa de la web semántica como gran base de conocimiento ha fracasado, pero no es tan así. Ha ido transmutándose y evolucionando hacia bases de conocimiento basadas en ontologías a partir de las cuales es posible obtener nuevo conocimiento. Es lo que llamamos razonamiento automático y empresas como Google ya lo utilizan para ofrecerte información adicional sobre tus búsquedas. Ellos lo llaman Grafos de Conocimiento o Knowledge Graphs . Gracias a estos grafos de conocimiento, Google puede ofrecerte información adicional sobre tu búsqueda, ad...