Crear una estacion meteorologica con raspberry pi y un sensor dth11

Ya puestos a trastear con la raspberry y sus conexiones al GPIO, vamos a ver como podemos crear una pequeña estacion meteorologica con la raspberry pi, y un sensor dth11.

Que necesitamos??

Una raspberry pi
Un sensor dth11 (unos 2 € en dealextreme)
Cables para conectarlo

Notas sobre los materiales necesarios
El sensor que utilizo yo, y el que aparece en la imagen, viene con una resistencia de 10k(amarillo violeta rojo oro) incorparada entre el conector de señal y nuestra conexion al gpio. Si lo compramos suelto, habra que hacer un circuito en un protoboard tal como aparece en esta imagen:

Montaje de los componentes:

Conectamos el sensor dth11 al gpio de la raspberry asi:

RPi VCC (pin 1) -> DHT11 pin 1
RPi GPIO4 (pin 7) -> DHT11 pin 2
RPi GND (pin 6) -> DHT11 pin 4 (pin3 si solo tiene 3 pins)
 
Creando un programa para poder acceder al sensor y leer temperatura y humedad:
 
Una vez realizadas las conexiones, vamos a crearnos un programa que realice 
las lecturas, y que nos saque los resultados por la pantalla.
 
He elegido el lenguaje de programacion en C

Instalamos lo necesario:
nota: Todo lo voy a hacer desde el terminal. Esto me permitira hacerlo todo, 
con una conexion SSH hacia mi raspberry.


Me situo en mi directorio HOME
cd ~

Ejecuto estos comandos:
sudo apt-get install git-core build-essential
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
 
Con esto ya tenemos lista la libreria wiringPi, para poder usar el puerto GPIO 
de la raspberry de una manera mas sencilla
 
Creamos el siguiente archivo con este comando:
nano dth11.c
 
Escribimos el siguiente codigo:
 
------------------------------------------ 
CODIGO DESDE AQUI - Archivo dth11.c
------------------------------------------
 
 //Incluimos librerias necesarias
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

//Definimos constantes
#define MAX_TIME 85
#define DHT11PIN 7
#define ATTEMPTS 5

//Definimos un vector global
int dht11_val[5]={0,0,0,0,0};

/////////////////////////////////////////////////////////////
//Funcion principal para leer los valores del sensor.
int dht11_read_val(){
uint8_t lststate=HIGH;
uint8_t counter=0;
uint8_t j=0,i;
for(i=0;i<5;i++){
dht11_val[i]=0;
}
pinMode(DHT11PIN,OUTPUT);
digitalWrite(DHT11PIN,LOW);
delay(18);
digitalWrite(DHT11PIN,HIGH);
delayMicroseconds(40);
pinMode(DHT11PIN,INPUT);
for(i=0;i<MAX_TIME;i++){
counter=0;
while(digitalRead(DHT11PIN)==lststate){
counter++;
delayMicroseconds(1);
if(counter==255){
break;
}
}
lststate=digitalRead(DHT11PIN);
if(counter==255){
break;
}
//Las 3 primeras transiciones son ignoradas
if((i>=4)&&(i%2==0)){
dht11_val[j/8]<<=1;
if(counter>16){
dht11_val[j/8]|=1;
}
j++;
}
}

// Hacemos una suma de comprobacion para ver si el dato es correcto. Si es asi, lo mostramos
if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF))){
printf("%d.%d,%d.%dn",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);
return 1;
}else{
return 0;
}
}

////////////////////////////////////////////////////////////////
//Empieza nuestro programa principal.
int main(void){
//Establecemos el numero de intentos que vamos a realizar
//la constante ATTEMPTS esta definida arriba
int attempts=ATTEMPTS;

//Si la libreria wiringPi, ve el GPIO no esta listo, salimos de la aplicacion
if(wiringPiSetup()==-1){
exit(1);
}

while(attempts){
//Intentamos leer el valor del gpio, llamando a la funcion
int success = dht11_read_val();

//Si leemos con exito, salimos del while, y se acaba el programa
if (success){
break;
}

//Si no lee con exito, restamos 1, al numero de intentos
attempts--;

//Esperamos medio segundo antes del siguiente intento.
delay(500);
}
return 0;
}
 
------------------------------------------ 
CODIGO HASTA AQUI-------- FIN DE ARCHIVO dth11.c
------------------------------------------
   
Se puede cambiar esto...:
printf("%d.%d,%d.%dn",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]); 

por esto:
printf("%d,%dn",dht11_val[0]*256+dht11_val[1],dht11_val[2]*256+dht11_val[3]); 
 
Y asi saldra correctamente los datos. Gracias a seta43 por el aviso! 
 
Una vez escrito, lo compilamos con el siguiente comando:
gcc -o dth11 dth11.c -L /usr/local/lib -l wiringPi

 
Si compila bien, ejecutamos con este comando:
sudo ./dth11
 
(GRACIAS A seta43 por la advertencia!!, habia confundido dth11 por dht11, asi que cuidar a ver!)
 
Deberia mostrarnos la temperatura, y la humedad separadas por comas.
 
 
Siguiente paso!!!
 
Como lo que nos interesa realmente, es tener unos datos actualizados cada minuto, 
y en forma de grafica, vamos a instalar un servidor web, y crearnos asi una
pagina web donde podamos consultar los resultados que nos dara nuestra medicio
de una forma grafica. Para eso, instalamos apache, y creamos la web necesaria.
 
Instalacion de apache:
 
Ejecutamos el siguiente comando:
apt-get install apache2
 
Arrancamos apache:
service apache2 start
 
Una vez instalado el 
 
 
Creacion automatica de la medicion de temperatura y humedad:

Vamos a crearnos un fichero, para que vaya guardando de forma automatica
los valores de temperatura y humedad, asi como la fecha en la que se ha 
tomado dicha medicion.

Nos situamos de nuevo en el directorio HOME:
cd ~

Creamos el siguiente fichero con el siguiente codigo:
nano dth11.sh

------------------------------------------ 
CODIGO DESDE AQUI - Archivo dth11.sh
------------------------------------------

#!/bin/bash
FECHA=$(date +%Y%m%d%H%M%S)
COMA=","
TEMP=$(/home/usuario/dth11)
echo "$FECHA$COMA$TEMP" >> /var/www/temp.log
 
------------------------------------------ 
CODIGO HASTA AQUI-------- FIN DE ARCHIVO dth11.sh
------------------------------------------ 
 
Con esto lo que hacemos, es un script que nos dara como resultado la fecha
en el formato adecuado, seguido de la temperatura y humedad, y lo almacenara 
en un archivo llamado temp.log, en el directorio raiz de APACHE por defecto, 
para su lectura posterior.
 
Tarea programada con cron
 
A continuacion, le vamos a decir a cron (nuestro programador de tareas en linux), 
que ejecute el script cada minuto. Para eso ejecutamos el siguiente comando:
 
sudo crontab -e
 
Y añadimos la siguiente linea al final:
 
* * * * * /home/usuario/dth11.sh
 
Creamos la pagina web para mostrarnos los resultados leidos:
 
Nos situamos en el directorio de nuestro servidor web con el siguiente comando:
cd /var/www 

Si existe un archivo index.html, lo borramos con el comando:
rm index.html

Descargamos la libreria dygraphs para poder generar la grafica:
wget -P /var/www http://dygraphs.com/dygraph-combined.js
 
Nos creamos el archivo index.html para almacenar la web:
nano index.html
 
------------------------------------------ 
CODIGO DESDE AQUI - Archivo index.html
------------------------------------------
 
 
<html>
<head>
<script type="text/javascript" src="dygraph-combined.js"></script>
</head>
<body>

<h1>Grafica con temperaturas y humedad</h1>

<p>Esta gr&aacute;fica, esta generada a partir de las mediciones tomadas por un sensor dth11, conectado a una raspberry pi. Se accede al sensor mediante lenguaje de programacion C, usando las librerias wiringPi, para poder leer y utilizar el conector GPIO de la raspberry Pi.</p>



<hr/>

<div id="graphdiv" style="width:750px; height:400px;"></div>
<script type="text/javascript">

//Funcion para añadir ceros a los numeros de un solo digito
function addZero(num){
var s=num+"";
if (s.length < 2){
s="0"+s;
}
return s;
}

//Funcion para dar formato a la fecha, devolviendo la misma formateada
function dateFormat(indate){
var hh = addZero(indate.getHours());
var MM = addZero(indate.getMinutes());
//var ss = addZero(indate.getSeconds()); //No usamos los segundos
var dd = addZero(indate.getDate());
var mm = addZero(indate.getMonth()+1);
var yyyy = addZero(indate.getFullYear());
return dd+'/'+mm+' '+hh+':'+MM;
}

//Funcion principal para generar el grafico. Se genera en el id="graphdiv"
g = new Dygraph(
document.getElementById("graphdiv"),
"temp.log",
{
xValueParser: function(x) {
var date = new Date(x.replace(
/^(d{4})(dd)(dd)(dd)(dd)(dd)$/,
'$4:$5:$6 $2/$3/$1'
));
return date.getTime();
},
axes: {
x: {
ticker: Dygraph.dateTicker,
axisLabelFormatter: function(x) {
return dateFormat(new Date(x));
},
valueFormatter: function(x) {
return dateFormat(new Date(x));
}
}
},
labelsDivWidth: 310,
rollPeriod: 30,
strokeWidth: 2.0,
labels: ['Date','Humedad (%)','Temp (&deg;C)']
}
);
</script>

<hr/>

</body>
</html>
 
------------------------------------------ 
CODIGO HASTA AQUI-------- FIN DE ARCHIVO index.html
------------------------------------------
 
Probandolo todo!!!

Si todo va bien, podemos probar que todo esto funciona, desde nuestro navegador
de paginas web, apuntando a la direccion ip de nuestra raspberry

http://ip.de.mi.pi

Deberia aparecer algo como esto:




Resumen:

Espero que os sirva de utilidad. A mi me ha funcionado todo a la perfeccion.

Un saludo a todos!!!


Fuente de informacion:

http://chrisbaume.wordpress.com/2013/02/10/beer-monitoring/

http://dygraphs.com/

http://rpidude.blogspot.com.es/2012/11/temp-sensor-and-wiringpi.html

http://dx.com/es/p/arduino-digital-temperature-humidity-sensor-module-121350

http://ubuntuone.com/6mT9cTREz90BUfvQD1AGNy


Agradecimientos:

Muchas gracias a Alberto, que me ha dejado todo el hardware necesario para poder
hacer mis pinitos con todo esto. Un abrazo!!!

 




			

Usar un cable ide de disquetera, para conectar el gpio de la raspberry pi, y poder jugar con las conexiones

A continuación pongo un esquema de como quedaria la relaciones de pines, si usamos un cable ide de disquetera (de 32 pines), para no ir tocando continuamente los pines del gpio de la raspberry pi.

Seguir leyendo para verlo en mas detalle.

Fijaos muy bien en el dibujo, porque el lado de la derecha del dibujo, que es el que no tiene los cables cruzados, y los deja a la izquierda en el otro extremo, se conecta a la raspberry, dejando 8 agujeros del cable libre. Hay que tener en cuenta que es un cable de 32 pines, y el gpio de la raspberry tiene 26

IMPORTANTE: Hay muchos cables que vienen con uno de los agujeros tapados!! buscar un cable que no lleve los agujeros tapados!!

Aqui os pongo otro dibujo en grande con la correlacion de pines:

Si por ejemplo, queremos usar el pin 3 y el pin 6 de la raspberry (Tabla de arriba), buscamos su numero en la tabla de abajo, y usamos ese hueco del cable.

Espero que os sirva de ayuda!! a mi me ha servido!!

Un saludo!