Invernadero automático
INVERNADERO AUTOMÁTICO
Grupo 7 – Arduino Uno
Antes de decantarnos por este proyecto, habíamos pensado en realizar una máquina de gancho, también conocida como «Claw Machine»: esta consiste en recoger los productos de su interior con un gancho colgante del techo el cual es controlado con un joystick. Era una idea bastante original y completa; sin embargo, sería necesario una gran cantidad de materiales, y esto mismo iba a causar que superáramos nuestro presupuesto.
Fue entonces cuando decidimos echar un vistazo al Kit Starter de Arduino y en base a eso fuimos evaluando las distintas ideas que se nos fueron ocurriendo. De entre ellas se encontraba la de un invernadero, y, aunque no éramos grandes fanáticos de las plantas y no teníamos gran capacidad para mantenerlas con vida durante un tiempo considerable, era una idea bastante completa de la que podríamos aprender bastante.
Así pues, a continuación, mostramos el proceso de creación de este, elaborado por:
- Sergio Ortiz Manso
- Mario Espasandín Hernández
- Leire Arranz Esteban
PRIMEROS PASOS
Al inicio, nuestra intención era desarrollar un invernadero, tanto manual como automático, con un sistema de regulación de temperatura mediante el control de una ventana, un ventilador y luces LED. Además, buscábamos incorporar un sistema de riego que respondiera a la humedad del suelo y a la disponibilidad de agua. También pensamos en la comodidad del usuario, por lo que ideamos una interfaz que incluyera una pantalla LCD y un potenciómetro para seleccionar y visualizar los datos del invernadero. Asimismo, implementamos un conjunto de LEDs indicadores para alertar sobre posibles problemas en caso de que los componentes mencionados no cumplieran con sus funciones.
No obstante, esta idea pronto se distorsionó debido a problemas con Arduino, como veremos más tarde.
Para ayudarnos a pensar bien en como sería nuestra idea, realizamos un sketch:
Idea general del proyecto
Apertura de la ventana con servomotor
Para llevar esto a cabo, hicimos una lista de componentes necesarios y nos pusimos manos a la obra en la búsqueda de aquellos que nos faltaban:
- 1 servomotor: Control de ventana según temperatura y para renovar aire automáticamente
- LEDs: Calentar ambiente + iluminar por la noche
- 1 ventilador: Enfriar ambiente (necesario un transistor y un diodo)
- 1 sensor de temperatura y humedad: Controla las LEDs, el ventilador y el sistema de riego
- 1 sensor de agua que detecte si hay suficiente agua para regar
- LEDs: Informan de errores: temperatura, humedad crítica e insuficiencia de agua
- 1 bomba de agua y un tubo de agua: Sistema de regadío (activado si la humedad es baja, y el detector de agua detecta suficiente agua), con interruptor para poder probarlo.
- Relé: Interruptor de la bomba.
- 1 sensor de luminosidad: Para encender luces nocturnas (LEDs nocturnas)
- 1 pantalla LCD: Mostrar datos y otros mensajes del invernadero:
- Temperatura
- Humedad
- Nivel de agua
- Cambio de modo
- 1 potenciómetro: Variar los datos mostrados en la pantalla
- Resistencias y cables oportunos
- Para el modo manual: Mando a distancia y detector de infrarrojos para realizar funciones.
- Bisagras y tornillos: Montaje de la estructura
- Madera: Base y estructura general
- Acetato: En vez de cristales. Necesitábamos un material que no fuera tan delicado y que pudiera empujar fácilmente el servomotor.
Bisagras
Madera
Acetato
COSTES
Podemos resumir el coste total de todo lo anterior en la siguiente tabla:
PROCEDIMIENTO
Una vez que ya teníamos los componentes, procedimos a montar la estructura:
Mientras tanto, fuimos elaborando el código y un Tinkercad para comprobar que todo funcionaba como estaba planeado:
La explicación del Tinkercad mostrado, se puede encontrar aquí:
Cabe mencionar que el sensor de temperatura que se encuentra en el pin analógico A0 no corresponde al sensor que poseemos, que es digital y se conectará al pin 12.
Luego, uniríamos la bomba y el sensor de agua, que no están en Tinkercad pero cuya conexión queda representada en las siguientes imágenes:
Conexión de la bomba a una pila de 5V
Conexión del sensor de nivel de agua
PROBLEMAS
Cuando lo pasamos a físico, encontramos una serie de problemas que nos obligaron a cambiar el funcionamiento del proyecto:
- Falta de pines digitales: Intentamos resolverlo con la implementación de un registro de desplazamiento de bits pero esto causó que la pantalla LCD no se encendiera.
- Conflicto entre librerías: Adafruit_LiquidCrystal con IRremote, tuvimos que eliminar más tarde la librería de terceros de Adafruit y usar simplemente la de LiquidCrystal, obligándonos a quitar el registro de desplazamiento de bits y a volver a tener el problema de falta de pines digitales.
- El programa parecía requerir más memoria de la que Arduino podía soportar, y entonces algunas funciones en el modo manual no se realizaban.
- La función servo.attach(servoPin) daba error en el programa y tuvimos que quitarlo, también debido a la falta de pines.
- Las luces de error tuvieron que suprimirse por la falta de pines también.
- Ventilador defectuoso: El cable del ground venía suelto, así que tuvimos que unirlo y sujetarlo con cinta adhesiva.
- Mando a distancia defectuoso: Tuvimos que usar un mando de televisión y obtener los nuevos códigos hexadecimales de señal para actualizar el código.
Así pues tuvimos que reestructurar todo nuestro código, optimizarlo, y alterar la forma en la que funcionaba además de los componentes utilizados:
- LDR: Este es el sensor de luminosidad. Cuando detecta que hay poca luz en el ambiente, activará unas LEDS a modo de bombillas para tener luz.
- Sensor de temperatura DHT11: Cuando la temperatura supere los 30 grados, activará un ventilador. Cuando la temperatura no supere los 10 grados, se encenderán unas LEDS a modo de luz térmica. Básicamente, produce valores de los que dependerá el funcionamiento automático del ventilador y las LEDs.
- Sensor de humedad de suelo: Cuando la humedad sea menor de un 75% y el sensor de nivel del agua detecta suficiente agua almacenada en el recipiente, activará la bomba de agua para el sistema de regadío.
- Sensor de nivel del agua: Cuando el nivel del agua sea estable para regar y la humedad ambiente no sea suficiente (75%), se permitirá activar la bomba de agua.
- Ventilador: Se activará cuando el sensor de temperatura lo indique (temperaturas mayores a 30ºC), regulando así la temperatura del invernadero hasta que ya no sea necesario y se apague (temperatura estable entre 10ºC y 30ºC).
- Bomba de agua: Es la encargada de regar cuando los valores de los sensores de humedad y nivel del agua sean los oportunos. De la bomba sale un tubo de plástico que recorre el invernadero por encima, tiene unos agujeros pequeños donde el agua caerá poco a poco para regar las plantas. Esta es controlada con un relé.
- Mando y detector de infrarrojos: Una vez el invernadero esté en modo manual, el mando podrá ejercer las funciones al pulsar un botón concreto:
- Botón 1 : Enciende LEDs
- Botón 2 : Apaga LEDs
- Botón 3 : Se muestra por el Serial Monitor el valor captado por los sensores
- Botón 4 : Activa el ventilador (2s)
- Botón 5 : Activa la bomba de agua (2s)
- Botón 6 : Activa la pantalla LCD y pone los valores de los sensores (2s)
- Botón 7 : Modo automático hasta que se presione algún otro botón (entonces entra en modo manual)
- Pantalla LCD: Va a ser la parte visual de la interfaz de nuestro código dónde veremos los niveles de humedad, agua, temperatura y luz. Se enciende con el mando.
- LEDs: Usadas para dar calor respecto a los valores del sensor de temperatura y para iluminar respecto a los valores del sensor de luminosidad.
- Cables, resistencias, diodos, transistores, una pila de 5V.
Como podemos notar, ha desaparecido la idea de las LEDs que indican errores, el potenciómetro, la ventana y el servo, y el registro de desplazamiento de bits 74HC595.
APARIENCIA FINAL DEL PROYECTO
Explicación del funcionamiento, el cableado y el código:
CÓDIGO
#include <IRremote.h> //#include <ServoTimer2.h> //#include <Servo.h> #include <DHT.h> //#include <Wire.h> //#include <Adafruit_PWMServoDriver.h> #include <LiquidCrystal.h> // Códigos hexadecimales de la señal de nuestro mando (cada mando tiene unos códigos diferentes) #define Tecla_1 0xFB040707 #define Tecla_2 0xFA050707 #define Tecla_3 0xF9060707 #define Tecla_4 0xF7080707 #define Tecla_5 0xF6090707 #define Tecla_6 0xF50A0707 #define Tecla_7 0xF30C0707 #define bombPin 13 // Pin digital para la bomba de agua #define tempPin 12 // Pin digital para el sensor de temperatura #define LED_PIN 11 // Pin digital para el LED #define fanPin 10 // Pin digital para el ventilador //#define servoPin 9 // Pin digital para el servomotor #define LIGHT_SENSOR A1 // Pin al que está conectado el sensor de luz #define HUMIDITYPIN A3 // Pin al que está conectado el sensor de humedad #define WATERLEVEL A0 const int IR = 8; // Asignar el ir al pin 8 int temperatura;// Variable para almacenar la temperatura int humedad; // Variable para almacenar la humedad int luz; // Variable para almacenar la lectura del sensor de luz int water; // Variable para almacenar el nivel de agua #define DHTTYPE DHT11 // Definimos el tipo de DHT DHT dht(tempPin, DHTTYPE); LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Servo servo_9; void setup() { Serial.begin(9600); //servo_9.attach(servoPin); // Si ponemos esto al pulsar cualquier boton se vuelve loco, probablemente haya algun tipo de conflicto entre las librerias IrReceiver.begin(IR, DISABLE_LED_FEEDBACK); pinMode(LED_PIN, OUTPUT); pinMode(fanPin, OUTPUT); // Configurar el pin del ventilador como salida pinMode(bombPin, OUTPUT); dht.begin(); // Iniciamos el dht lcd.begin(16,2); } void loop() { // Al iniciar el programa, está el modo manual activado por defecto if (IrReceiver.decode()) { Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Imprime el código hexadecimal que ha detectado el infrarrojo if (IrReceiver.decodedIRData.decodedRawData == Tecla_1) digitalWrite(LED_PIN, HIGH);// Al pulsar 1, encendemos LEDS if (IrReceiver.decodedIRData.decodedRawData == Tecla_2) digitalWrite(LED_PIN, LOW);// Al pulsar el botón 2, apagamos LEDS if (IrReceiver.decodedIRData.decodedRawData == Tecla_3) { // Al pulsar el botón 3, se muestran los valores de los sensores en el Serial Monitor, por si no funcionara la pantalla LCD // --- Lectura de la humedad --- humedad = analogRead(HUMIDITYPIN);// Leemos la humedad del sensor float humedad_porcentaje = map(humedad, 0, 1023, 0, 100); // Convertimos el valor a un valor porcentual (0-100) Serial.print("Humedad: "); Serial.print(humedad_porcentaje); Serial.println("%"); delay(1500); // --- Lectura de la luminosidad --- luz = analogRead(LIGHT_SENSOR); Serial.print("Luz: "); Serial.println(luz); delay(1500); // --- Lectura de la temperatura --- temperatura = dht.readTemperature(); // Lectura de la temperatura if (isnan(temperatura)) { // Si el valor de la temperatura es NaN, entonces lo indicamos Serial.println("Error obteniendo los datos del sensor DHT11"); } else { Serial.print("Temperatura: "); Serial.print(temperatura); Serial.println(" grados"); } delay(1500); // --- Lectura del nivel del agua --- water = analogRead(WATERLEVEL); // Leemos el nivel del agua Serial.print("Agua: "); Serial.println(water); delay(1500); } if (IrReceiver.decodedIRData.decodedRawData == Tecla_4) { // Al pulsar el botón 4, se enciende el ventilador durante 2 segundos // Activar el ventilador durante 2 segundos digitalWrite(fanPin, HIGH); delay(2000); // Desactivar el ventilador durante 2 segundos digitalWrite(fanPin, LOW); delay(2000); } if (IrReceiver.decodedIRData.decodedRawData == Tecla_5) { // Al pulsar el botón 5, se enciende la bomba de agua durante 2 segundos water = analogRead(WATERLEVEL); Serial.print("Agua: "); Serial.println(water); if(water > 20) { // Si el nivel del agua es mayor a 20, entonces se puede regar digitalWrite(bombPin, HIGH); delay(2000); // Desactivar la bomba de agua después de 2 segundos digitalWrite(bombPin, LOW); delay(1000); } else (Serial.println("No hay agua suficiente")); delay(200); } if (IrReceiver.decodedIRData.decodedRawData == Tecla_6) { // Al pulsar el botón 6, se enciende la LCD y muestra los valores de los sensores lcd.clear(); temperatura = dht.readTemperature(); humedad = analogRead(HUMIDITYPIN); // Leer la humedad del sensor float humedad_porcentaje = map(humedad, 0, 1023, 0, 100); // Convertir valor a porcentaje (0-100) lcd.setCursor(0,0); lcd.print("Temperatura: "); if (isnan(temperatura)) { // Si el valor de la temperatura es NaN, entonces lo indicamos Serial.println("?"); } else lcd.print(temperatura); lcd.setCursor(0,1); lcd.print("Humedad: "); lcd.print(humedad_porcentaje); delay(5000); // Los mensajes se muestran durante 5 segundos lcd.clear(); // Luego borramos la LCD y escribimos más valores delay(500); lcd.setCursor(0,0); luz = analogRead(LIGHT_SENSOR); lcd.print(" Luz: "); lcd.println(luz); lcd.setCursor(0,1); water = analogRead(WATERLEVEL); lcd.print(" Agua: "); lcd.println(water); delay(5000); // Los mensajes se muestran durante 5 segundos lcd.clear(); } if (IrReceiver.decodedIRData.decodedRawData == Tecla_7) { // Al pulsar el botón 7, se activa el funcionamiento automático hasta que se vuelva a pulsar otro botón humedad = analogRead(HUMIDITYPIN); // Leer la humedad del sensor float humedad_porcentaje = map(humedad, 0, 1023, 0, 100); // Convertir valor a porcentaje (0-100) water = analogRead(WATERLEVEL); temperatura = dht.readTemperature(); // Lectura de la temperatura luz = analogRead(LIGHT_SENSOR); if(luz < 120 || temperatura < 10){ if(luz < 120) Serial.println("Luz insuficiente, activando LEDS"); if(temperatura < 10) Serial.println("Temperatura baja, activando LEDS"); digitalWrite(LED_PIN, HIGH); } else digitalWrite(LED_PIN, LOW); if(humedad_porcentaje < 75){ Serial.print("Humedad baja, preparando la bomba de agua."); Serial.print("Nivel de agua: "); Serial.println(water); if(water > 20) { Serial.println("Agua suficiente. Activando la bomba"); digitalWrite(bombPin, HIGH); delay(2000); // Se riega durante 2 segundos digitalWrite(bombPin, LOW); delay(1000); } else (Serial.println("No hay agua suficiente. No se puede activar la bomba")); delay(2000); } if(temperatura > 30){ Serial.println("Temperatura elevada, activando ventilador"); // Activar el ventilador durante 2 segundos digitalWrite(fanPin, HIGH); delay(10000); // Desactivar el ventilador durante 2 segundos digitalWrite(fanPin, LOW); delay(2000); } } IrReceiver.resume(); } }
REFLEXIÓN FINAL
Estamos contentos con los resultados obtenidos y con las lecciones aprendidas durante la creación de nuestro proyecto. Nos enfrentamos a desafíos que pusieron a prueba nuestras habilidades creativas y de resolución de problemas, lo que resultó en un valioso crecimiento. Hemos perfeccionado nuestras técnicas de programación, ampliado nuestro conocimiento del hardware y, lo más crucial, hemos desarrollado la capacidad para superar obstáculos.
A pesar de estos logros, reconocemos que hubiéramos preferido no tener que simplificar nuestro primer prototipo hasta llegar a la versión actual. Lamentablemente, esto fue necesario, probablemente debido a las limitaciones de las librerías de terceros que utilizamos o a las restricciones del Arduino Uno, que no podía admitir todas nuestras funcionalidades.
Aunque nos satisface el resultado, nos queda el deseo de haber podido mantener más fielmente nuestra idea original sobre todo después del material que compramos precisamente para ello.
Esperamos que os haya parecido interesante nuestro proyecto
si, me pudieras proporcionar los valores de los diodos y los transistores