viernes, 14 de febrero de 2014

Estación meteorológica I: cuando el señor DS1307 conoció a la señora DHT11

Mi curiosidad me arrastra irremediablemente a una nueva aventura de impredecibles resultados. He tomado la determinación, tras navegar por los procelosos océanos de internet, de desarrollar mi propia estación meteorológica.

¿Por qué? pues porque existe un abundantísimo material sobre esta temática, lo cual a priori supone una ventaja fundamental, a saber: podré aprender de, y sin caer en, los errores ajenos, pero también supone una clara desventaja, que no es otra que la de tratar de realizar desde la más absoluta ignorancia, alguna aportación de provecho a un campo donde otros han trabajado mucho y bien.

Bien, una vez realizada esta declaración de intenciones y reconocida la apriorística inaptitud personal, voy a entrar ya en materia.

Inicialmente, he hecho uso de un sensor DHT11 adquirido a través de ebay por 2,03 euros, este sensor nos permite medir al mismo tiempo, tanto temperatura como humedad. Podéis echar un vistazo al datasheet de este sensor para ampliar información.

Sensor DHT11

Este sensor internamente está compuesto por un sensor de humedad capacitativo y un termistor calibrados de fábrica. Su manejo resulta relativamente fácil haciendo uso de las diversas librerías, como la que aquí os dejo, que existen para este sensor en internet, y además sólo se necesita un pin para la transmisión de datos.

Todo proyecto para la medición de variables medioambientales como temperatura, humedad, presión atmosférica, etc, debe tener una referencia temporal. Nuestra querida placa arduino carece de un reloj que permita llevar este seguimiento del tiempo, por lo que para esta finalidad nos serviremos de un módulo con el conocidísimo chip DS1307 adquirido en ebay al módico precio de 1,77 euros. Os dejo el datasheet de este componente.

DS1307_parte_circuito
Módulo RTC DS1307 (parte circuito)

Este tipo de módulos incorporan frecuentemente, además del chip DS1307, una memoria EEPROM AT24C32 de 32kilobits de la cual no haremos uso. Habitualmente suelen encontrarse bajo la denominación de RTC (Real Time Clock), o en dicho en lengua cervantina: "Reloj en Tiempo Real".

Suelen disponer los componentes en una de las caras del circuito, mientras que en la otra cara se incorpora un contenedor para albergar una pila tipo botón que alimenta el chip DS1307 cuando está desconectado y de esta forma, evitar la pérdida de la hora y día que haya sido introducida. Tanto el chip DS1307, como la memoria EEPROM AT24C32 hacen uso del interface I2C, por lo que su utlización con nuestra placa arduino es relativamente sencilla, ya que simplemente debemos conectar los terminales SCL y SDA que figuran en el módulo, a los entradas analógicas A5 y A4, respectivamente, además de, por supuesto, conectar la alimentación a 5V y a GND del módulo.

En caso de utilizar una placa arduino Mega, los terminales SCL y SDA del módulo deberán conectarse a las entradas digitales D21 y D20, respectivamente.

DS1307_parte_batería
Módulo RTC DS1307 (parte contenedor de batería)

Gracias al siguiente sketch podremos grabar cada cinco minutos en una tarjeta SD y en formato .CSV, los valores de humedad y temperatura.

/* Programa para registrar datos de temperatura y humedad */

#include <Wire.h>
#include "date.h"
#include "DHT.h"
#include <SPI.h>
#include <SD.h>

#define DIR 0x68

char date_array[20];
File myFile;
DHT dht;
unsigned long i=0;

void setup() {
  date d;
  byte aux = 0;
  Wire.begin();
  Serial.begin(57600);
  d.hours = 2;
  d.minutes =50;
  d.day = 25;
  d.month = 1;
  d.year = 2014;
  //setDate(DIR,0,t);
  Serial.println("Initializing SD card...");
  pinMode(10, OUTPUT);  
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  myFile = SD.open("datos.csv", FILE_WRITE);
  if (SD.exists("datos.csv"))
    SD.remove("datos.csv");
  Serial.println("initialization done.");
  Serial.println();
  Serial.println(" Hora    Fecha  Status    Humedad (%)     Temperatura (C)");
  dht.setup(2); // data pin 2
}

void loop() {
  date d;
  myFile = SD.open("datos.csv", FILE_WRITE);
  if (myFile) {
    delay(dht.getMinimumSamplingPeriod());
    float humidity = dht.getHumidity();
    float temperature = dht.getTemperature();
    getDate(DIR,0);
    enviarFecha();
    Serial.print(dht.getStatusString());
    Serial.print(" ");
    Serial.print(humidity, 1);
    Serial.print(" ");
    Serial.println(temperature, 1);
    myFile.print(date_array);
    myFile.print(" ");
    myFile.print(humidity, 1);
    myFile.print(" ");
    myFile.println(temperature, 1);
  }
  myFile.close();
  delay(300000);
}

void getDate(byte dir, byte reg) {
  byte aux;
  byte numDatos = 7;
  Wire.beginTransmission(dir);
  Wire.write(0);
  Wire.endTransmission();
  
  Wire.requestFrom(dir,numDatos);                                      // Siete datos a leer
  while (Wire.available() < numDatos);
  
  date_array[5] = date_array[2] = ':';
  date_array[8] = ' ';
  date_array[11] = date_array[14] = '/';
  
  aux = Wire.read();                                    // Segundos
  date_array[6] = (aux >> 4)+48;
  date_array[7] = (aux & 0x0F)+48;
  
  aux = Wire.read();                                    // Minutos
  date_array[3] = (aux >> 4)+48;
  date_array[4] = (aux & 0x0F)+48;
  
  aux = Wire.read();                                    // Horas
  date_array[0] = (aux >> 4)+48;
  date_array[1] = (aux & 0x0F)+48;
  
  aux = Wire.read();                                    // Dia del mes
  aux = Wire.read();
  date_array[9] = (aux >> 4)+48;
  date_array[10] = (aux & 0x0F)+48;
  
  aux = Wire.read();                                    // Mes
  date_array[12] = (aux >> 4)+48;
  date_array[13] = (aux & 0x0F)+48;
  
  aux = Wire.read();                                    // Año
  date_array[15] = '2';
  date_array[16] = '0';
  date_array[17] = (aux /10)+48;
  date_array[18] = (aux % 10)+48;
  
  Wire.endTransmission();
}

void setDate(byte dir, byte reg, date d) {
  byte aux;
  Wire.beginTransmission(dir);
  Wire.write(reg);
  
  aux = (((byte)(d.seconds/10))<<4) + (d.seconds % 10);
  Wire.write(aux);
  
  aux = (((byte)(d.minutes/10))<<4) + (d.minutes % 10);
  Wire.write(aux);
  
  aux = (((byte)(d.hours/10))<<4) + (d.hours % 10);
  Wire.write(aux);
  
  Wire.write(3);
  
  aux = (((byte)(d.day/10))<<4) + (d.day % 10);
  Wire.write(aux);
  
  aux = (((byte)(d.month/10))<<4) + (d.month % 10);
  Wire.write(aux);
  
  aux = (byte)(d.year-2000);
  Wire.write(aux);

  Wire.endTransmission();
}

void enviarFecha() {
  //char msg[30];
  //sprintf(msg, "%d:%d:%d %d/%d/%d", d.hours,d.minutes,d.seconds,d.day,d.month,d.year);
  Serial.print(date_array);
  Serial.print("  ");
}

En el directorio del sketch deberemos igualmente crear un fichero date.h con la estructura de datos de fecha y hora de la siguiente forma:

typedef struct {
  int seconds;
  int minutes;
  int hours;
  int day;
  int month;
  int year;
} date;

La función enviarFecha() permite fijar la hora del DS1307, por lo que es recomendable que activemos esta función la primera vez que carguemos el programa. Resulta recomendable darse un paseo por el datasheet del DS1307 para entender mejor el funcionamiento de este sketch. 

La siguiente gráfica, generada mediante Google Docs, ha sido creada con los datos de lectura de temperatura y humedad obtenidos el sábado 26 de enero de 2014 en Lora del Río (Sevilla). En el eje horizontal figura la hora, mientras que en el eje vertical izquierdo he situado la temperatura en grados centígrados y en el eje vertical derecho la humedad en porcentaje.



De las conclusiones que he obtenido del trabajo realizado hasta aquí, de cara a desarrollar nuestra estación meteorológica, podemos destacar la necesidad de estudiar el cambio del modelo de sensor empleado, sustituyendo el DHT11 por un DHT22, ya que una mayor precisión y rango de medidas sería deseable en principio. En la siguiente tabla, y a modo de resumen, se recogen las principales diferencias entre ambos sensores.


De lo cual se desprende claramente que cuando la temperatura registrada baje de cero grados centígrados, el sensor DHT11 nos resultará insuficiente. El coste del sensor DHT22 como es lógico es superior, sin llegar a ser prohibitivo, ya que he podido obtenerlo por 3,18 euros.

Ya estoy trabajando en una próxima entrada donde os presentaré los resultados obtenidos del estudio que estoy realizando sobre el sensor BMP180, el cual permite medir tanto temperatura, como presión barométrica. Por otra parte, trataré de ir creando código lo más optimizado y claro posible para gestionar los diversos sensores que incorporaré a la estación meteorológica.

No hay comentarios:

Publicar un comentario