El Internet de las cosas III: Monitor de Temperatura

Hace tiempo que no tratamos el tema de el Internet de las cosas, en el anterior artículo hicimos que pudiésemos controlar unas luces a partir de una página web. Esta vez, vamos a tratar un asunto parecido, pero en este caso trataremos con sensores ya que es un aspecto importante en el internet de las cosas.

En este caso, vamos a crear un pequeño montaje para que vaya en todo momento guardando la temperatura en una base de datos y luego mostrar los datos en una web mostrando una gráfica. Utilizaremos un Arduino para realizar la medición y la Raspberry Pi para guardar los datos y mostrarlos en una gráfica a partir de un script CGI con Python.

Pero primero comenzaremos por mostrar los componentes que necesitaremos:

Tras tener todos los componentes, pasaremos a realizar el montaje. Para ello vamos a usar el programa Fritzing para mostraros como realizar el montaje de este ejemplo.

iotIII

Como podemos ver en el esquema, conectamos el sensor DHT11(podemos usar el DHT22 también), a nuestro Arduino y seguidamente conectamos nuestro Arduino a la Raspberry Pi por medio de un cable USB. Este cable será el que haga de canal de comunicación por medio de un puerto serie.

Con el montaje hecho, ya hemos terminado la parte fácil; ahora toca la parte de realizar el software que esta vez, vamos a mostrar un esquema distinto. Vamos a usar una base de datos Mysql para guardar los datos y mostrarlos posteriormente.

Seguiremos el siguiente esquema:

esquemaiotIII

Vemos como en primer lugar, el sensor envía los datos al Arduino, este manda una cadena en formato JSON, a la Raspberry Pi por medio del puerto serie a un proceso Python que se ejecuta en segundo plano. Este proceso recibe la información y lo envía a una base de datos Mysql.

Cuando un usuario accede a la web, se recoge la información de la base de datos y se muestra al usuario por medio de una gráfica.

Comenzaremos por el software que añadiremos al Arduino. Para poder leer del sensor DHT, necesitaremos su librería correspondiente que podemos encontrar aquí. Una vez descargada y añadida la librería a nuestro arduino, pasaremos a añadir el software. Dejamos seguidamente el código a crear para Arduino.

/*
  Internet de las cosas III: Monitor de temperatura
  Este programa mide la humedad y temperatura de un sensor DHT
   y manda los resultados por el puerto Serie como una cadena JSOn.
*/
#include <dht.h>
#define DHT_PIN 2//Pin de lectura 2
dht DHT;//Objeto del sensor
 
void setup() {
  //INicializacion del puerto serie.
  Serial.begin(9600);
 
 
}
 
void loop() {
 
 
  int dato = DHT.read11(DHT_PIN);//Lectura del dato.
  Serial.print("{\"humidity\":");
  Serial.print(DHT.humidity);
  Serial.print(",");
  Serial.print("\"temperature\":");
  Serial.print(DHT.temperature);
  Serial.println("}\n");
  delay(300000);//esperamos 5 minutos.
 
}

Con el software ya añadido a nuestro Arduino pasaremos a configurar nuestra Raspbery Pi para poder tanto conectarnos al puerto serie, crear y configurar nuestra base de datos y poder mandar los datos a esta.

En primer lugar, vamos a crear la base de datos; para ello, necesitaremos el motor de base de datos Mysql(También es válido MariaDB); por lo que usaremos el comando correspondiente para instalarlo(Suponemos que el lector esta usando la distribución Raspbian; si esta usando otra consulte la documentación de su distribución). para instalar Mysql, usaremos el siguiente comando:

#apt-get install mysql-server

Con el servidor ya instalado, vamos a pasar a crear una base de datos y a crear una tabla; para ello usaremos el siguiente comando para conectarnos a nuestra base de datos:

$mysql -u root -p

Introducimos la contraseña del usuario root que hemos tenido que crear al instalar Mysql. Ahora estamos dentro del interprete de Mysql y vamos a crear la base de datos. El siguiente comando creará una base de datos y crearemos una tabla dentro de dicha base de datos.

&gt;CREATE DATABASE temperatura;
>USE temperatura;
>CREATE TABLE temps(id BIGINT(20) PRIMARY KEY AUTO_INCREMENT , fecha datetime, temp DECIMAL, hum DECIMAL);
exit

Tras crear la tabla correctamente, ya estamos preparados para pasar a crear el proceso en segundo plano que inserte en la base de datos; para ello recurriremos a python y por lo tanto tenemos que instalar una serie de librerías necesarias para poder conectarnos en primer lugar al puerto serie USB y por otro lado poder guardar la información en la base de datos. En primer lugar, instalaremos la librería de conexión con base de datos para Python.

#apt-get install python-mysqldb

Instalada la librería de Python, pasaremos a instalar la librería Pyserial para conectarnos por puerto serie a nuestro Arduino. Para instalar esta librería utilizaremos la utilidad Pip para Python.

#pip install pyserial

ya hemos terminado de configurar todo lo necesario para crear el proceso en segundo plano. Seguidamente crearemos un fichero .py y añadiremos el siguiente código donde recoge la información y la manda a la base de datos.

#!/usr/bin/env python
 
import serial
import json
import MySQLdb
 
arduino = serial.Serial('/dev/ttyACM0',9600)
print arduino.readline()
print arduino.readline()
while True:
    character= arduino.readline()   
    MyJson = character
    db = MySQLdb.connect("localhost","root","&lt;password&gt;","temperatura")
    if character != '\n':
        try:
            data=json.loads(character)
            print data
            print data['humidity']
            curs = db.cursor()
            curs.execute("INSERT INTO temps(fecha,hum,temp)values(now(),"+str(data['humidity'])+","+str(data['temperature'])+")")
            db.commit()
        except ValueError:
            print ""
 
 
arduino.close()

El Script anterior se conecta al Arduino por puerto serie y cada vez que recibe los datos en JSON, lo pasea y después lo inserta en la base de datos por medio de una sentencia SQL into. Podemos comprobar que todo se ha hecho correctamente por medio de una consulta SQL; conectándonos a nuestra Raspberry Pi y entrando de nuevo al interprete SQL. En el interprete ejecutamos la siguiente sentencia.

SELECT * FROM temps;

Si todo va correctamente, debería de aparecer algo así:

Captura de pantalla 2015-10-29 a las 22.00.10

 

Una vez que tenemos este proceso listo, vamos a pasar a crear la web. para ello vamos a crear un script CGI para Python. Para lo cual necesitaremos instalar el servidor web apache. Para instalarlo, usaremos el siguiente comando.

#apt-get install apache2

Si todo va correctamente, podemos acceder desde el navegador de nuestra raspberry pi con la dirección http://localhost y aparecerá una web que dice “IT WORKS”. Seguidamente vamos a crear el siguiente Script llamado Index.py en la carpeta /usr/lib/cgi-bin, con el siguiente contenido.

#! /usr/bin/env python
import cgi,cgitb
import MySQLdb
 
print "Content-Type: text/html;charset=utf-8"
print "\n\n"
print ""
print ""
print    "<script type=\"text/javascript\"" print "src=\"https://www.google.com/jsapi?autoload={" print "'modules':[{" print "'name':'visualization'," print "'version':'1'," print "'packages':['corechart']" print "}]" print "}\"></script>"
 
print    "<script type=\"text/javascript\">"
print      "google.setOnLoadCallback(drawChart);"
db = MySQLdb.connect("localhost","root","becario2011","temperature")
curs = db.cursor()
curs.execute("SELECT * FROM Data order By date DESC limit 0,100")
print      "function drawChart() {"
print       " var data = google.visualization.arrayToDataTable(["
print          "['Fecha', 'Humedad', 'Temperatura']"
for data in curs.fetchall():
    print ",['"+str(data[1])+"',"+str(data[2])+","+str(data[3])+"]"
print        "]);"
db.close() 
print"        var options = {"
print          "title: 'Internet Of Things',"
print          "curveType: 'function',"
print          "legend: { position: 'bottom' }"
print        "};"
 
print        "var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));"
 
print        "chart.draw(data, options);"
print      "}"
print    "</script>"
print " "
print  ""
print   "


print ”

"
print ""

Este script muestra la página web, como una gráfica a partir de los datos obtenidos de la base de datos. Una vez añadido este script, hay que añadirle permisos para que pueda ser ejecutado para ello ponemos los siguientes permisos al archivo con el siguiente comando.

#chmod 644 /usr/lib/cgi-bin/index.py

Una vez todo listo, vamos a pasar a encender el sistema; en primer lugar encenderemos el proceso en segundo plano con el siguiente comando.

#python iot3.py &amp;

y por último, si todo va bien, solo tenemos que acceder a la dirección web: http://localhost/cgi-bin/index.py; desde nuestra Raspberry Pi y aparecerá en pantalla lo siguiente.

2015-10-29-215245_976x736_scrot

Con esto último ya hemos visto como crear un monitor de temperatura y humedad para poder tener datos y poder visualizarlos en una página web. En otras sesiones añadiremos el soporte del CLoud para transformar nuestro Sistema de Internet de las cosas en el futuro cercano de El internet del todo.

26 Comments on "El Internet de las cosas III: Monitor de Temperatura"

  1. Hola, Tengo unas cuantas dudas.
    Esto puede reproducirse para diferentes codigos en arduino, es decir si la parte que se hace en la raspberry es será la misma aún si yo cambio de sensor y de codigo? Porque noto que el codigo de arduino lo unico que hace es tomar el dato e imprimirlo por el puerto serial, y en la parte del codigo de arduino, en la parte del #include, cual es la libreria que importa? Otra duda es, se puede aplicar a varios sensores?

    Gracias!!

    • Hola jaime:

      Efectivamente el codigo de arduino puede reproducirse tantas veces como quieras. Por supuesto puede hacerlo de manera que puedas tener varios sensores y mandarlos a una misma raspberry. Con respecto a la librería se trata de la libreria DHTLib que permite leer de un sensor DHT. Obviamente todo esto se puede aplicar a varios sensores.

  2. Saludos amigos,
    En qué parte del proceso crearon el archivo iot3.py

    Cuál es el contenido del archivo?

    Agradezco su atención.

    • Hola Juan:

      El fichero iot3.py, el contenido lo tienes en el mismo post.


      #!/usr/bin/env python

      import serial
      import json
      import MySQLdb

      arduino = serial.Serial('/dev/ttyACM0',9600)
      print arduino.readline()
      print arduino.readline()
      while True:
      character= arduino.readline()
      MyJson = character
      db = MySQLdb.connect("localhost","root","<password>","temperatura")
      if character != '\n':
      try:
      data=json.loads(character)
      print data
      print data['humidity']
      curs = db.cursor()
      curs.execute("INSERT INTO temps(fecha,hum,temp)values(now(),"+str(data['humidity'])+","+str(data['temperature'])+")")
      db.commit()
      except ValueError:
      print ""

      arduino.close()

  3. Hola,

    Una duda rápida, por qué únicamente aparecen números enteros en los valores de la temperatura y humedad?

  4. Hola. Estoy intentando hacer lo mismo pero con un sensor de luz, el problema es que al momento de ejcutar el .py con todos los parametros, nunca sube los datos al servidor. Todos los datos que salen del Arduino lo hacen en formato Json o hay que hacer algo?. Gracias.

    • Hola Wilfer:

      Comprueba que recibes correctamente del arduino los datos y además, que conectar correctamente a la base de datos MySQL los datos. Seguramente será por configuración con la base de datos, o que no esta correctamente configurado el puerto USB.

  5. Muy buenas. Mi enhorabuena por el artículo. Me parece super completo y sintetizado. He aprendido un montón de cosas con él ya que no tenía ni idea de mysql ni apache2.
    Me está siendo muy útil para medir los niveles de humedad de una habitación de casa a la cual le vamos a poner un “cacharro” para que absorba la humedad y quiero comprobar su eficacia.
    Al final he hecho una variante. He prescindido de arduino y he conectado directamente el DHT22 a la raspberry con la librería para python hecha por adafruit.
    Me gustaría comentar unos problemillas con los que me he encotrado y que posiblemente otro investigador urbano se pueda encontrar y no llevar a buen puerto la idea de este gran artículo.
    En el script de la página web se llama a la base de datos en inglés. En lugar de temperatura, se le llama temperature y donde la contraseña estaría bien que pusiera “escribe aquí tu contraseña” o algo así en lugar de becario2011. db = MySQLdb.connect(“localhost”,”root”,”becario2011″,”temperature”).
    Por otro lado la sentecia SQL llama a una tabla y campo que no hemos definido previamente en nuestra base de datos:
    curs.execute(“SELECT * FROM Data order By date DESC limit 0,100”) tendría que ser curs.execute(“SELECT * FROM temps order By fecha DESC limit 0,100”).
    Y por último para darle permisos al script me ha funcionado con sudo chmod +x /usr/lib-bin/Index.py. No se porque con el 644 no.

    De nuevo daros las gracias y enhorabuena por este artículo.

    Un cordial saludo.

  6. mayra corrales herrera | noviembre 3, 2016 en 12:32 am | Responder

    disculpa tengo una duda en donde generas el archivo de fichero.py en el escritorio de la rasp o tiene que ir en una carpeta especifica

    • Hola Mayra:

      En principio puedes guardarlo en el escritorio de la Raspberry Pi o cualquiera(el archivo que recibe los datos desde el arduino) ya que este se ejecutará con el interprete de python(python fichero.py) el otro fichero, debe estar en la carpeta correspondiente de tu servidor web; normalmente es la cgi-bin que tenga configurado por ejemplo en apache.

      Un saludo y espero que tu duda este resuelta.

  7. Buenos días, me gustaría que me orientara para aprender a conectar la tarjeta esp 2866 con sql server en forma remota para luego subir el control a la web con asp. La parte de asp-sql server la domino suficientemente bien, lo que no se es como recibir y enviar datos al arduino mediante la interfase sql server.

    Podría ayudarme, enviarme algún tutorial o ejemplos? Gracias, Dios lo bendiga.

  8. Muy buen articulo, gracias por el aporte, solo tengo una duda, que hace la siguiente linea en tu código python.

    if character != ‘\n’:

    Saludos

  9. Muchísimas gracias por el aporte me fue de gran ayuda. Tienes algún tutorial de como hacer esto mismo de conectar un arduino a una raspberry pi con una conexión wireless?

    Saludos

  10. Muchas gracias por el aporte me fue de muchísima ayuda. Tienes algún material de hacer esto mismo pero que la conexión entre el rasperry pi y el arduino sea por wireless?

    Saludos.

    • administracion | julio 7, 2016 en 5:31 pm | Responder

      Buenas Myriam:

      Te recomendamos que busques información sobre el componente ESP8266 para poder tener wifi con tu arduino y así poder mandar a través de wifi información desde arduino a Raspberry Pi.

  11. Buenas amigo, excelente tutorial, pero dime es posible hacer esto:

    arduino = serial.Serial(‘/dev/ttyACM0’,9600)
    arduino = serial.Serial(‘/dev/ttyACM1’,9600)
    arduino = serial.Serial(‘/dev/ttyACM2’,9600)
    arduino = serial.Serial(‘/dev/ttyACM3’,9600)

    En el caso que tuvieras mas de un arduino conectado por usb y usar unicamente la variable arduino?

    • import os, sys
      Se me ocurrió hacerlo de esta manera, no se si sea la mejor manera, pero tengo un solo arduino para probar, pero la idea es que no haya necesidad de tocar el código cada vez que metas un arduino distinto, o tengas mas de uno.
      /////////////////////////////////////////////////////////////////

      Open a file

      path = “/dev/serial/by-id/”
      dirs = os.listdir( path )

      This would print all the files and directories

      for file in dirs:
      arduino = serial.Serial(‘/dev/serial/by-id/’+file,9600)

      • administracion | abril 9, 2016 en 9:27 am | Responder

        Buenas David:

        En principio puedes crear un programa que directamente te detecte los puertos serie del sistema y puedas seleccionarlos. Para no tener que modificar el código cada vez. En breve pondremos un artículo sobre este tema.

        Un saludo

        • Gracias por tu comentario :), seria buenísimo un Internet de las cosa IV, y reemplazar el USB por Bluetooth 🙂

          Saludos

          • administracion | abril 13, 2016 en 4:54 pm |

            Buenas; estamos preparando un nuevo articulo de el Internet de las cosas IV pero no con bluetooth sino con wifi utilizando ESP 2866. Estamos esperando que nos lleguen las piezas.

            En breve tendrás más articulos.

            Un saludo.

  12. Felipe Rimenschneider | enero 15, 2016 en 8:29 pm | Responder

    Buenas sabes que muy buena información lo único que me esta acomplejando es que al momento de hacer las lecturas todas muestran en 0, y me asegure que estuviera bien la conexión física del arduino y el sensor. Aun así todos los 0 llegan a la base de datos si pudieras ayudarme con ese problema seria genial. Saludos, gracias

    • Por lo que veo puede ser que nano estés leyendo bien el sensor en Arduino. Comprueba que esta todo correctamente conectado y que recibes todo correctamente en tu Raspberry Pi.
      Un saludo y cualquier cosa me dices.

  13. Buenas, me viene muy bien este articulo, muchas gracias.
    Me gustaría conectar dos arduinos al raspberry y cada uno con un sensor de temperatura, como podría identificar la información que me envían los arduinos, a que arduino pertenece los datos del sensor de temperatura? Seria poner un identificador a a cada arduino en la tabla temperatura? Ya que me gustaría identificar la temperatura de cada habitación.
    Y mas adelante podría reemplazar la conexión por usb a bluetooth.

    Saludos Cordiales

    • Hola Manuel. Lo mejor es que como tu has dicho poner un identificador a cada arduino o que el propio proceso de recogida(como va cada uno por un puerto serie distinto) identifique que habitación es y directamente lo guarde para cada habitación en la base de datos.

      Con respecto a usar bluetooth sería más sencillo y serviría para no tener que estar poniendo cables(te recomiendo que si vas a hacerlo uses Bluetooth LE que consume menos y la configuración es más sencilla. Eso si, más caro el componente).

      Un saludo.

Deja un comentario.

Tu dirección de correo no será publicada.


*


*