Invernadero Domótico Inteligente: Control Climático Automatizado con Arduino
Componentes y materiales
| Arduino MKR1000 | 1 |
| Arduino UNO | 1 |
| Sensor de temperatura y humedad DHT22 | 1 |
| Shield WiFi 101 para Arduino | 1 |
| Dispositivo Android | 1 |
| Shield de control de motor DC con BTN8982 para Arduino (Infineon) | 1 |
Aplicaciones y servicios en línea
- Arduino IDE
- Eclipse
Descripción del proyecto
Visión general
Las condiciones ambientales en un invernadero cambian continuamente, por lo que se requiere un sistema de monitoreo eficiente. Un sistema automático ofrece múltiples ventajas: reduce la mano de obra, permite a los usuarios supervisar sus cultivos desde casa mediante PC o smartphone, y posibilita el almacenamiento histórico de datos en una base de datos, factor clave para la rentabilidad. Además, el control en tiempo real permite intervenir de inmediato ante cualquier anomalía, previniendo pérdidas en la cosecha.
El sistema de monitoreo automático se compone de sensores que leen datos ambientales y actuadores denominados "Esclavos". Estos se comunican de forma inalámbrica con un dispositivo central llamado "Maestro". El Maestro envía posibles cambios a los esclavos (como nuevos umbrales) y transmite los datos vía WiFi a un servidor web.
1. ¿Cómo funciona?
El proyecto se divide en tres partes principales:
- Maestro (Master)
- Esclavo (Slave)
- Servidor Web
Se utiliza un Arduino/Genuino MKR1000 como Maestro y un Arduino/Genuino Uno como Esclavo. El Maestro se comunica con el Servidor Web vía WiFi (chip WINC1500 integrado), mientras que el Esclavo adquiere temperatura y humedad mediante el sensor DHT22 y envía estos datos al Maestro vía WiFi (shield WiFi WINC1500).
2. Maestro
El Maestro opera en "Modo Punto de Acceso" (Access Point) y espera la conexión del Esclavo para recibir los datos de temperatura y humedad, que procesa y envía al Servidor Web.
El Maestro verifica si hay datos disponibles; en ese caso, crea un paquete UDP formado por los nuevos umbrales y un CRC. Calcula el CRC que el Esclavo usará para validar la configuración recibida. Tras salir del modo AP, el Maestro se conecta a la red WiFi para enviar los datos al Servidor Web, donde se representan gráficamente.
3. Esclavo
El Esclavo lee temperatura y humedad del sensor DHT22 y, cada 5 minutos, envía los datos al Maestro. Crea un paquete UDP, se conecta al Maestro y transmite la información. Posteriormente, espera posibles datos de configuración (nuevos umbrales). Si los recibe, calcula el CRC usando la fórmula Dallas-Maxim y lo compara con el CRC recibido del Maestro. Si coinciden, guarda la nueva configuración en la EEPROM.
4. Servidor Web
El Servidor Web almacena todos los datos para su histórico. Se utiliza un script PHP que se conecta a la base de datos y muestra la información de dos formas:
- En un gráfico, mediante otro script PHP
- En una app Android, en formato JSON mediante otro script PHP
5. Aplicación Android
La app permite consultar los datos almacenados en la base de datos. En la pantalla principal, se selecciona el rango temporal a visualizar y, al pulsar "GRÁFICO", contacta con el servicio web y obtiene los datos para representarlos gráficamente.
Código
Generar gráfico (PHP)
Script para crear gráficos con la librería JPGraph:
<?php
define('__ROOT__', dirname(dirname(__FILE__)));
require_once ('../jpgraph.php');
require_once ('../jpgraph_line.php');
require_once ('../jpgraph_error.php');
$parameter1 = array();
$parameter2 = array();
$time_axis = array();
$i = 0;
$con = mysqli_connect("localhost","user","pass","my_db");
if (mysqli_connect_errno()) {
echo "Falló la conexión a MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT your_parameter FROM your_raw");
while($row = mysqli_fetch_array($result)) {
$parameter1[$i] = $row["parameter1"];
$parameter2[$i] = $row["parameter2"];
$time_axis[$i] = $row["date"];
$i++;
}
mysqli_close($con);
$graph = new Graph(300,250);
$graph->SetScale("textlin");
$theme_class = new UniversalTheme;
$graph->SetTheme($theme_class);
$graph->img->SetAntiAliasing(false);
$graph->title->Set('Título');
$graph->SetBox(false);
$graph->img->SetAntiAliasing();
$graph->yaxis->HideZeroLabel();
$graph->yaxis->HideLine(false);
$graph->yaxis->HideTicks(false,false);
$graph->xgrid->Show();
$graph->xgrid->SetLineStyle("solid");
$graph->xaxis->SetTickLabels($time_axis);
$graph->xgrid->SetColor('#E3E3E3');
$graph->xaxis->SetLabelAngle(90);
$graph->legend->SetPos(0.5,0.08,'center','top');
$p1 = new LinePlot($parameter1);
$graph->Add($p1);
$p1->SetColor("#6495ED");
$p1->SetLegend('Parámetro 1');
$graph->yscale->SetGrace(0);
$p2 = new LinePlot($parameter2);
$graph->Add($p2);
$p2->SetColor("#B22222");
$p2->SetLegend('Parámetro 2');
$graph->yscale->SetGrace(0);
$graph->legend->SetFrameWeight(1);
$graph->Stroke();
?>
Script de conexión web (PHP)
Guarda los datos en la base de datos:
<?php
$servername = "localhost";
$username = "user";
$password = "pass";
$dbname = "my_db";
$id = $_GET["name"];
$temp = $_GET["parameter1"];
$umid = $_GET["parameter2"];
$conn = mysqli_connect($servername, $username, $password, $dbname);
if (!$conn) {
die("Conexión fallida: " . mysqli_connect_error());
}
$sql = "INSERT INTO greenhouse (name, parameter1, parameter2) VALUES ('".$id."', '".$temp."', '".$umid."')";
if (mysqli_query($conn, $sql)) {
echo "Registro creado correctamente";
} else {
echo "Error: " . $sql . "
" . mysqli_error($conn);
}
mysqli_close($conn);
?>
Crear tabla (SQL)
CREATE TABLE IF NOT EXISTS `greenhouse` ( `id` int(11) NOT NULL, `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `temp` float NOT NULL, `umid` float NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Código del Maestro (C/C++)
Controla la comunicación WiFi, recepción de datos del Esclavo vía UDP, cálculo de CRC y envío al servidor web.
/* Proyecto Automatización Invernadero */
/* Autores: Antonio La Mura, Umberto Festa */
/* Fecha: 03/03/2016 */
#include <SPI.h>
#include <WiFi101.h>
#include <RTCZero.h>
#include <WiFiUDP.h>
char ssid[] = "SSID";
char pass[] = "pass";
int keyIndex = 0;
char ssid_ap[] = "Arduino";
char pass_ap[] = "";
int status = WL_IDLE_STATUS;
unsigned int localPort = 2390;
char server[] = "www.cormaz.altervista.org";
WiFiServer server_ap(80);
WiFiClient client_ap;
WiFiUDP Udp;
RTCZero rtc;
WiFiClient client;
char packetBuffer[255];
char ReplyBuffer[255];
float humax = 0, humin = 0, tumax = 0, tumin = 0;
boolean flag = false;
boolean threshold_available = false;
void setup() {
Serial.begin(9600);
while (!Serial) { ; }
Serial.println();
}
void loop() {
// ... código completo en el repositorio original
// Funcionalidades: modo AP, recepción UDP, parsing de datos,
// cálculo CRC-8 (Dallas/Maxim), envío a servidor web HTTP
}
byte CRC8(const byte *data) {
byte crc = 0x00;
while (*data) {
byte extract = *data++;
for (byte tempI = 8; tempI; tempI--) {
byte sum = (crc ^ extract) & 0x01;
crc >>= 1;
if (sum) crc ^= 0x8C;
extract >>= 1;
}
}
return crc;
}
Código del Esclavo (C/C++)
Lee sensor DHT22, envía datos al Maestro vía UDP, recibe nuevos umbrales, valida CRC y controla actuadores (calefactor, humidificador, ventilador).
/* Esclavo - Invernadero Domótico */
#include <SPI.h>
#include <WiFi101.h>
#include <WiFiUdp.h>
#include <EEPROM.h>
#include <DHT22.h>
#define HUMIDIFIER A4
#define HEATER A5
#define DHT22_PIN 4
DHT22 myDHT22(DHT22_PIN);
// ... código completo: conexión WiFi, envío UDP cada 10 min,
// recepción de umbrales, validación CRC, guardado en EEPROM,
// control de actuadores según umbrales
byte CRC8(const byte *data) {
byte crc = 0x00;
while (*data) {
byte extract = *data++;
for (byte tempI = 8; tempI; tempI--) {
byte sum = (crc ^ extract) & 0x01;
crc >>= 1;
if (sum) crc ^= 0x8C;
extract >>= 1;
}
}
return crc;
}
Script getdati (PHP)
Conecta la app con la base de datos para obtener registros en JSON:
<?php
$username = "root";
$password = "";
$hostname = "localhost";
$dbhandle = mysql_connect($hostname, $username, $password) or die("No se puede conectar a MySQL");
$selected = mysql_select_db("serra",$dbhandle) or die("No se pudo seleccionar la base de datos");
$datada = $_GET["datada"];
$dataa = $_GET["dataa"];
$result = mysql_query("SELECT hum,temp,date FROM record WHERE date >= '".$datada."' and date <=' ".$dataa."'");
$records = array();
while ($row = mysql_fetch_array($result)) {
$tmp = array("hum"=>$row{'hum'}, "temp"=>$row{'temp'}, "date"=>$row{'date'});
array_push($records,$tmp);
}
echo json_encode($records);
mysql_close($dbhandle);
?>
Esquemáticos
Conexión: Arduino UNO - DHT22 - Relé
Proceso de manufactura
- Guía Profesional de Animación Bitmap en Pantalla Táctil ILI9341 2.4″ con Shield para Arduino
- Sistema de Iluminación DMX Controlado por Web – Controlador Maestro Arduino
- Construye un Spybot controlado por Bluetooth con Arduino
- FlickMote: Mando IR por gestos para Smart Home
- TV‑B‑Gone DIY con Arduino: Mando universal para apagar cualquier TV
- Construye un Reloj Maestro LED Personalizado con Alarma – Visible desde 12 Metros
- Reloj HSV: Reloj Vibrante y Personalizable para Entusiastas de Arduino
- Vehículo Controlado por Android con Raspberry Pi, Arduino y Motor Shield: Guía Completa
- Find Me: Localizador Inteligente de Objetos con Arduino y Bluetooth
- Soluciones de Alimentación Optimizadas para Proyectos Arduino
- Shield de Programación Inalámbrica para Arduino con HC-05 Bluetooth – Sin Cable USB