Estación Meteorológica – Capturando Temperatura, Humedad y Luminosidad en MySQL usando Apache, php, Arduino + Ethernet Shield
Uno de nuestros tutoriales mas comentados es Capturando datos en MySQL usando Apache, php, Arduino + Ethernet Shield. Por este motivo quise darle una actualización y al mismo tiempo responder con un ejemplo a muchas de las consultas que nos realizaron en ese tutorial, a continuación los pasos para implementar una estación meteorológica usando el sensor DHT11, un LDR, un Arduino y una Ethernet Shield.
Este proyecto es similar al anterior, un Arduino Uno con una Ethernet Shield, pero esta vez agregué 2 variables mas, ahora mide temperatura, humedad y luminosidad; estos datos los envía al igual que antes mediante una instrucción GET a un servidor remoto y aquí algo nuevo, el servidor remoto responde en XML indicándole al Arduino cual de los tres leds que posee debe encender o apagar. Les parece interesante?
1. Materiales
- Arduino Uno Release 3
- Ethernet Shield
- Sensor DHT11 o DHT22
- LDR – Fotoresistencia
- 3 Leds
- 2 resistencias de 10K (Ppara los sensores)
- 3 resistencias de 1k (Para los leds)
- Cables de conexión
- Protoboard
- Servidor Web Apache / PHP / MySQL
2. Diagrama
El proyecto al tener mas componentes se ve un poco mas complejo, pero con observación y cuidado es fácil construir el prototipo en el protoboard.
Hay que tener cuidado con la polaridad de los LEDs y los 4 pines del sensor DHT11 (o DHT22 según sea el caso).
Otro punto importante a recordar es que Arduino usa los pines 10, 11, 12 y 13 (SPI) para comunicarse con la Ethernet Shield por lo cual no pueden ser utilizados como Entrada/Salida.
3. Programación de Arduino
El sketch para Arduino esta basado en los que utilizamos en los tutoriales Midiendo Temperatura y Humedad con Arduino y el sensor DHT11 y Capturando datos en MySQL usando Apache, php, Arduino + Ethernet Shield, este sketch es una fusion de ambos considerando eso si que ahora agregamos un sensor mas y 3 leds. Recomiendo leer ambos tutoriales para entender mejor como trabaja este proyecto.
Esquema de Pines
Arduino Pin 2 : Pin 2 del Sensor DHTxx Arduino Pin 5 : + Led 1 Arduino Pin 6 : + Led 2 Arduino Pin 7 : + Led 3 Arduino Pin A0: - LDR Arduino +5V : + Protoboard Arduino GRD : - Protoboard
Las demas conexiones deben verse en el diagrama.
El sketch que pueden copiar y pegar en la interfaz de desarrollo para Arduino es el siguiente:
// InternetDeLasCosas.cl // Script que obtiene la temperatura y humedad desde un sensor DHTxx // y envia estos datos a un servidor web. // El servidor web procesa los datos y responde en xml indicando que // Leds deben ser encendidos o apagados en el Arduino // // Escrito por @joniuz #include <SPI.h> #include <Ethernet.h> // Libreria para Sensores DHT #include "DHT.h" #define DHTPIN 2 // Pin del Arduino al cual esta conectado el pin 2 del sensor // Descomentar segun el tipo de sensor DHT usado #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302) //#define DHTTYPE DHT21 // DHT 21 (AM2301) // Inicializa el sensor DHTxx DHT dht(DHTPIN, DHTTYPE); // Configuracion de fotocelda int fotocelda = 0; int luminosidad; // Configuracion Ethernet Shield // Mac unica de cada EthernetShield byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x4E, 0xD7 }; // Direccion IP Fija en caso de que no pueda obtenerla por DHCP IPAddress ip(172,17,17,217); // Direccion del DSN en caso de que no pueda obtenerla por DHCP //IPAddress myDns(172,17,17,1); // Inicializa la instancia client EthernetClient client; // Direccion del servidor (cambiar por su direccion) char server[] = "www.iot.cl"; // Ultima conexion al servidor medida en millisegundos unsigned long ultimaConexion = 0; // Intervalo en milisegundos entre conexiones const unsigned long intervaloConexion = 20000; // Leds conectados a Salidas Digitales int led_1; // Umbral de temperatura int led_2; // Umbral de humedad int led_3; // Umbral de luminosidad // Setup de Arduino void setup() { // Configura salidas digitales para los Leds pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); // Inicializa puerto serial Serial.begin(9600); Serial.println("######### Internetdelascosas.cl #########"); Serial.print("Sensor de temperatura-humedad DHT"); Serial.print(DHTTYPE); Serial.println(" / web"); Serial.println(); // Espera 1 segundo para que se inicie la tarjeta Ethernet delay(1000); // Intenta inicializar la EthernetShield via DCHCP Serial.println("Iniciando EthernetShield via DHCP"); if(!Ethernet.begin(mac)) { // Si el DHCP falla, inicia la EthernetShield con IP estatica Serial.println("Falla al obtener IP desde DHCP, iniciando con IP estatica"); Ethernet.begin(mac, ip); } // Imprime la direccion IP de la tarjeta Serial.print("Direccion IP: "); Serial.println(Ethernet.localIP()); Serial.println(); // Inicializa Sensor DHTxx Serial.print("Iniciando Sensor DHT"); Serial.println(DHTTYPE); Serial.println(); dht.begin(); // Espera dos segundos para dar tiempo al sensor mientras obtiene muestra delay(2000); } // Loop principal void loop() { // Si hay conexion con el servidor if (client.connected()) { if (client.available()) { // Obtiene la respuesta del servidor y busca los tags xml <led_1> <led_2> y <led_3> if(client.find("<led_1>")) { led_1 = client.parseInt(); } if(client.find("<led_2>")) { led_2 = client.parseInt(); } if(client.find("<led_3>")) { led_3 = client.parseInt(); } // Imprime valores enviados por servidor Serial.println("Valores enviados por servidor"); Serial.print("Led 1: "); Serial.println(led_1); Serial.print("Led 2: "); Serial.println(led_2); Serial.print("Led 3: "); Serial.println(led_3); // Cierra conexion Serial.println("Cerrando conexion..."); Serial.println(); client.stop(); // Enciende Leds segun valores if (led_1) digitalWrite(5, HIGH); else digitalWrite(5, LOW); if (led_2) digitalWrite(6, HIGH); else digitalWrite(6, LOW); if (led_3) digitalWrite(7, HIGH); else digitalWrite(7, LOW); } } else if(millis() - ultimaConexion > intervaloConexion) { httpRequest(); } } // Fin del loop principal // Funcion que realiza la conexion http al servidor y obtiene la respuesta void httpRequest() { // Obtiene los datos del sensor DHTxx // Obtiene la Humedad float h = dht.readHumidity(); // Obtiene la Temperatura en Celsius float t = dht.readTemperature(); // Control de errores, valida que se obtuvieron valores para los datos medidos if (isnan(h) || isnan(t)) { Serial.println("Falla al leer el sensor DHTxx!"); return; } Serial.print("Temperatura: "); Serial.println(t); Serial.print("Humedad: "); Serial.println(h); // Obtiene datos de la fotocelda luminosidad = analogRead(fotocelda); Serial.print("Luminosidad = "); Serial.print(luminosidad); Serial.println(); // Se conecta al servidor en el puerto 80 (web) if (client.connect(server, 80)) { // Envia el dato al puerto serial Serial.println("Iniciando conexion..."); // Envia el requerimiento via GET client.print("GET /sensorarduino.php?id=joniuz&temperatura="); client.print(t); client.print("&humedad="); client.print(h); client.print("&luminosidad="); client.print(luminosidad); client.println(" HTTP/1.1"); client.print("Host: "); client.println(server); client.println("User-Agent: Arduino-Ethernet"); client.println("Connection: close"); client.println(); // Actualiza el tiempo en milisegundos de la ultima conexion ultimaConexion = millis(); } }
Este sketch envia informacion para verificar como esta operando el Arduino a la interfaz serial asi que recomiendo que la observen cuando comiencen las pruebas.
4. Servidor Apache – MySQL – PHP
Asumimos que el servidor posee Apache, PHP y MySQL y que estos se encuentran configurados y funcionando sin problemas.
Utilizaremos la misma tabla que en el proyecto anterior llamada “variable” que se puede crear con el siguiente script:
CREATE TABLE IF NOT EXISTS `variable` ( `fecha` datetime NOT NULL, `id` varchar(30) NOT NULL, `nombre` varchar(100) NOT NULL, `valor` float NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
El script que recibira las variables desde el Arduino se debe llamar sensorarduino.php y debe ser puesto en la raíz del sitio web ya que el código del Arduino lo llama con un “GET /sensorarduino.php…” donde el “/” hace referencia a la raíz del servidor. El codigo del script es el siguiente:
<?php // www.internetdelascosas.cl // // Script para recolectar datos enviados por arduinos conectados a la red // // contacto@internetdelascosas.cl // // Parametros para encender leds $umbralTemperatura = 22; $umbralHumedad = 80; $umbralLuminosidad = 500; // Parametros de base de datos $mysql_servidor = "localhost"; $mysql_base = "iot"; $mysql_usuario = "iot"; $mysql_clave = "contraseña_super_segura_que_no_es_hola123"; $id = htmlspecialchars($_GET["id"],ENT_QUOTES); $temperatura = htmlspecialchars($_GET["temperatura"],ENT_QUOTES); $humedad = htmlspecialchars($_GET["humedad"],ENT_QUOTES); $luminosidad = htmlspecialchars($_GET["luminosidad"],ENT_QUOTES); // Valida que esten presente todos los parametros if (($id!="") and ($temperatura!="") and ($humedad!="") and ($luminosidad!="")) { mysql_connect($mysql_servidor,$mysql_usuario,$mysql_clave) or die("Imposible conectarse al servidor."); mysql_select_db($mysql_base) or die("Imposible abrir Base de datos"); $sql = "insert into variable (fecha, id, nombre, valor) values (NOW(),'$id','temperatura','$temperatura')"; mysql_query($sql); $sql = "insert into variable (fecha, id, nombre, valor) values (NOW(),'$id','humedad','$humedad')"; mysql_query($sql); $sql = "insert into variable (fecha, id, nombre, valor) values (NOW(),'$id','luminosidad','$luminosidad')"; mysql_query($sql); // Genera respuesta en XML para que el Arduino lo procese if ($temperatura < $umbralTemperatura) echo "<led_1>1</led_1>"; else echo "<led_1>0</led_1>"; if ($humedad > $umbralHumedad) echo "<led_2>1</led_2>"; else echo "<led_2>0</led_2>"; if ($luminosidad < $umbralLuminosidad) echo "<led_3>1</led_3>"; else echo "<led_3>0</led_3>"; echo "\n"; } ?>
Recuerden cambiar las credenciales de la base de datos MySQL por las de su base de datos.
Este código php genera una salida en XML como la siguiente
<led_1>1</led_1><led_2>0</led_2><led_3>0</led_3>
La cual es procesada por el Arduino el cual lee el valor encerrado en cada tag XML (<led_1> </led_1>) como el valor binario de encendido o apagado del led que corresponde al tag.
5. Prueba Final
Si han realizado todos los pasos correctamente entonces al verificar la interfaz serial del Arduino deberían ver el mensaje de inicio, la dirección IP que asume el Arduino, los valores que se obtienen desde los sensores y que son enviados al servidor y la respuesta que el servidor envía procesada por el Arduino que indica en binario (0/1) si el led debe encenderse o no
Y al revisar el registro log en el servidor web deberian ver las conexiones que realiza el Arduino
[root@iot]# tail -f /var/log/httpd/iot.cl_access_log 210.1.221.117 - - [14/Jul/2014:18:39:14 +0400] "GET /sensorarduino.php?id=joniuz&temperatura=20.00&humedad=48.00&luminosidad=685 HTTP/1.1" 200 49 "-" "Arduino-Ethernet" 210.1.221.117 - - [14/Jul/2014:18:40:14 +0400] "GET /sensorarduino.php?id=joniuz&temperatura=20.00&humedad=47.00&luminosidad=687 HTTP/1.1" 200 49 "-" "Arduino-Ethernet"
No hay comentarios:
Publicar un comentario