Construcción de un huerto automatizado
Abstract
El objetivo de este trabajo es el diseño y construcción de un modelo a escala de un huerto circular que realice diversas funciones de manera autónoma, como bien pueden ser el monitoreo de la temperatura del terreno o el riego de este mismo. Para satisfacer las necesidades del sistema, se utilizará un microprocesador de bajo coste con interfaz Wi-Fi que gestione el funcionamiento del resto de elementos que lo conforman y subirá la información a la red para ser consultada de forma remota. Por último, se considerarán las posibles opciones de mejora que tendría el diseño de cara a crear otras versiones futuras que contemplen funcionalidades añadidas.
Full text
Proyecto Fin de Carrera Ingeniería de Telecomunicación Formato de Publicación de la Escuela Técnica Superior de Ingeniería Autor: F. Javier Payán Somet Tutor: Juan José Murillo Fuentes Dep. Teoría de la Señal y Comunicaciones Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2013 Trabajo Fin de Grado Ingeniería Electrónica, Robótica y Mecatrónica Construcción de un huerto automatizado Autor: Jaime García Ramírez Tutor: Alfredo Pérez Vega-Leal Dpto. Ingeniería Electrónica Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2024
Trabajo Fin de Grado Ingeniería Electrónica, Robótica y Mecatrónica Construcción de un huerto automatizado Autor: Jaime García Ramírez Tutor: Alfredo Pérez Vega-Leal Profesor Titular Dpto. Ingeniería Electrónica Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2024
Trabajo Fin de Grado: Construcción de un huerto automatizado Autor: Jaime García Ramírez Tutor: Alfredo Pérez Vega-Leal El tribunal nombrado para juzgar el trabajo arriba indicado, compuesto por los siguientes profesores: Presidente: Vocal/es: Secretario: acuerdan otorgarle la calificación de: El Secretario del Tribunal Fecha:
Agradecimientos L a culminación de este trabajo supone el fin de una etapa cuyo inicio se me hace muy lejano, pero a la vez muy reciente. Parece que fue ayer cuando llegué a la ETSI, cargado de miedos pero también de esperanzas, de temor a no ser capaz de superar los desafíos que se encontraban frente a mi, a fracasar, a decepcionar a todos. Pero hoy estoy aquí, este trabajo es la prueba de que pude lograrlo, de que superé el camino, pero también es la prueba de que estoy rodeado de muchas personas maravillosas que me han apoyado en cada uno de mis pasos, por eso no sólo este trabajo, si no todo este recorrido va dedicado a ellos, a mis padres, que me han apoyado desde el minuto uno y me han dado fuerzas para continuar cuando yo mismo no me veía capaz de lograrlo, a mi pareja, que se unió en el trayecto y me ha dado los momentos de paz que necesitaba y todo su apoyo, a mis amigos, por tantas tardes de estudio, prácticas y ratitos que hicieron mas ameno el peso de los exámenes, a mis profesores que me han guiado a cada paso, en especial a Alfredo, mi tutor en este proyecto, a mi tío Antonio, que me ha dado la posibilidad de construir mi sistema, a mis abuelos, tanto los que están aquí como los que ya nos han dejado, que me hacen saber lo orgullosos que están de mí cada dia, y por supuesto a toda mi familia, que siempre han estado ahí para mi, por todo esto solo puedo deciros una cosa. Gracias. Jaime García Ramírez Sevilla, 2024 I
Resumen E l objetivo de este trabajo es el diseño y construcción de un modelo a escala de un huerto circular que realice diversas funciones de manera autónoma, como bien pueden ser el monitoreo de la temperatura del terreno o el riego de este mismo. Para satisfacer las necesidades del sistema, se utilizará un microprocesador de bajo coste con interfaz Wi-Fi que gestione el funcionamiento del resto de elementos que lo conforman y subirá la información a la red para ser consultada de forma remota. Por último, se considerarán las posibles opciones de mejora que tendría el diseño de cara a crear otras versiones futuras que contemplen funcionalidades añadidas. III
2Capítulo 1. Introducción Por último, añadir que este dispositivo busca ser Plug and Play, de forma que la única intervención que el usuario deba realizar, a parte de proporcionar los datos de su red Wi-Fi, sea conectarlo ,o desconectarlo, a una toma de corriente. Figura 1.1 Boceto de Huerto Automatizado. 1.3 Hardware En esta sección se listarán cada uno de los dispositivos electrónicos utilizados para la construcción del sistema y se explicará cómo funcionan. 1.3.1 Feather HUZZAH ESP8266 El microcontrolador a utilizar para el desarrollo de este proyecto es el Feather Huzzah ESP8266, fabricado por la empresa Adafruit. Figura 1.2 Feather HUZZAH ESP8266 [2]. Este microcontrolador cuenta con todo lo necesario para abordar las funciones que debe desempeñar durante el funcionamiento de nuestro sistema, contando además con un precio reducido, lo que lo convierte
1.3 Hardware 3 en una opción ideal teniendo en cuenta nuestros objetivos. El ESP8266 incluye por defecto un adaptador Wi-Fi y es compatible con los protocolos IP y TCP, lo que nos permitirá convertir nuestro huerto en un dispositivo IoT [ 3 ] y subir nuestros datos a la red para ser consultados remotamente. Además de su predisposición para conetarse a Internet, también cuenta otras características que nos permitirán conectar, controlar y alimentar el resto de dispositivos que conforman el sistema, las más relevantes de estas características son las siguientes: Tabla 1.1 Características Feather HUZZAH ESP8266 [2]. Especificaciones Frecuencia de reloj 80MHz o 160 MHz Memoria Flash 4 MB Pines GPIO 9 Protocolos de comunicación I2C,SPI, UART yWi-Fi Voltaje de señales lógicas 3.3V Pines de salida de Voltaje 3.3V, 5V 3.7Va aPara disponer de este pin de salida es necesario conectar una batería de litio externa Una vez conocido de lo que es capaz este microcontrolador, debemos ser conscientes de qué puertos nos dan acceso a sus diferentes funcionalidades, además de tener en cuenta que ciertos pines,como los pines 0, 2 y 15, no pueden ser usados como entradas, ya que tienen conectados a ellos resistencias internas que pueden intervenir con las medidas en el caso de los pines 2 y 15, o tienen otras limitaciones en el caso del pin 0 [ 2 ]. Figura 1.3 Pinout Feather HUZZAH ESP8266 [2]. 1.3.2 Servomotores Analógicos de Rotación Continua Los encargados de dotar de movimiento a todo el mecanismo que acciona el huerto son los servomotores de rotación continua fabricados por Multicomp Pro. A diferencia de los servomotores convencionales, estos no se enuentran limitados a un rango de 180º grados, lo que nos permite realizar acciones sobre una zona mayor que si utilizaramos su homólogo universal,
4Capítulo 1. Introducción Figura 1.4 Servomotor Analógico de Rotación Continua [4]. además estos motores cuentan con la posibilidad de regular la velocidad y el sentido en el que giran, lo que los vuelve una opción casi perfecta para las funciones que deben realizar en nuestro proyecto. Por otro lado, estos cuentan con una desventaja respecto a los ya mecionados servomotores clásicos, a diferencia de estos, los servomotores de rotación continua funcionan en bucle abierto, lo que significa que no podemos conocer en qué posición se encuentra situado este, ni fijarlo en una posición específica, por lo que será necesario informar de otra forma al microcontrolador de que se ha alcanzado la posición deseada. [5] Dependiendo de si conectamos el servomotor al pin de alimentación de 5V proporcionado por el microcontrolador, o a una fuente externa que lo alimente a 6V, conseguiremos diferentes valores en el desempeño: Tabla 1.2 Especificaciones Eléctricas Servomotor Analógico de rotación continua a diferentes voltajes [4]. Especificaciones 4.8V 6V Corriente de Reposo 5mA 6mA Velocidad sin carga 110RPM 130RPM Corriente en funcionamien- to(sin carga) 100mA 120mA Par máximo de Parada 1.3Kg-cm 1.5Kg-cm Corriente crítica 550mA 650mA El control sobre el sentido de giro y la velocidad a la que se realiza es análogo a controlar la posición de un servomotor convencional. Este se realiza a través de señales PWM de 50Hz que varían de 1 a 2 ms. Detener el servomotor es igual a colocar uno de los servomotores convencionales en una posición de 90º 1 , mientras que valores de PWM que situarían al servomotor convencional en ángulos menores a este, supondrán que el servomotor continuo gire en el sentido de las agujas del reloj, aumentando su velocidad hasta alcanzar el máximo en un valor equivalente a 0º, de igual forma, para girar en sentido antihorario debemos proporcionar pulsos equivalentes a ángulos mayores a 90º, alcanzando la máxima velocidad en este sentido en 180º. [5] Figura 1.5 Control de un servomotor convencional a través de pulsos PWM [5]. 1En la práctica, este valor puede encuentrarse desplazado dependiendo del servomotor
1.3 Hardware 5 1.3.3 Termómetro Infrarrojo MLX90614 Como ya se ha comentado en apartados anteriores, deseamos medir la temperatura a la que se encuentra el terreno sin interactuar con él, función para la que un termómetro infrarrojo compacto y sin un elevado precio como este es perfecto. Figura 1.6 Termómetro Infrarrojo MLX90614 [6]. El funcionamiento de estos termómetros se basa en que mientras mayor sea la temperatura de un objeto, mayor será el movimiento de sus partículas, lo que producirá que emitan una mayor cantidad de luz infrarroja, estos dispositivos son capaces de medir esa radiación y convertirla en temperatura. El termómetro infrarrojo calcula la diferencia entre la radiación IR que emite el objeto a medir y la del entorno, a partir de esa diferencia calcula la temperatura del objeto. [7] Existen diferentes modelos dentro de esta familia de dispositivos, nosotros utilizaremos el modelo BAA, que admite un rango de temperaturas entre -40ºC a 125ºC para la temperataura ambiente, y desde -70ºC hasta 380ºC en el caso de la temperatura de la superficie a medir. [6] Dependiendo del valor de estas temperaturas, la precisión del valor arrojado por el termómetro puede variar drásticamente. Figura 1.7 Precisión del MLX90614 en función de la Temperatura ambiente y de la Temperatura de la superficie a medir [6].
6Capítulo 1. Introducción Afortunadamente, nuestras temperaturas siempre se encontrarán dentro de un rango en el cual el termómetro infrarrojo ofrece la mayor precisión con la que es capaz de medir, por lo que los valores que obtengamos tendrán un error de ±0.5ºC. [6] El sensor puede ser alimentado con valores de entre 2.6V hasta 3.6V, siendo lo convencional 3V [ 6 ], sin embargo, el modelo que nosotros tenemos también admite alimentarse a 5V gracias a que posee un regulador de tensión incorporado [7]. Otro punto a tener en cuenta con respecto a la utilización de este sensor es el campo de visión(FOV) y la distancia del objeto a medir. El FOV es un ángulo en el que se promedian todas las temperaturas que detecta el sensor, si el objeto a medir no lo ocupa por completo, el resultado será el promedio de las temperaturas pertenecientes a los objetos que se encuentren dentro del FOV, cuanto más cerca estemos del objeto cuya temperatura deseemos calcular, menos probable será que esto ocurra [ 7 ]. Por suerte, en nuestro caso deseamos obtener la temperatura del terreno, por lo que prácticamente siempre el FOV será totalmente ocupado por el objeto que deseamos medir. Figura 1.8 FOV de un termómetro infrarrojo [7]. Por último, cabe resaltar que la comunicación entre el sensor y el microcontrolador se realiza a través del protocolo I2C, el cuál será comentado en capítulos posteriores. 1.3.4 RTC DS3231 Para que nuestro sistema sea consciente de cuándo debe regar, será necesario que conozca qué hora es en todo momento, el encargado de suplir esta necesidad será el RTC DS3231. Figura 1.9 RTC Ds3231 [8].
1.3 Hardware 7 Este tipo de componentes hacen uso de un oscilador de cristal, el cuál se ajusta por sí solo a los cambios de temperatura , para calcular el paso del tiempo. Dichos dispositivos funcionan a una frecuencia de 32 kHz, la misma que usan los relojes de cuarzo y otros relojes similares. Además, el propio RTC tiene en cuenta el final de los meses con una cantidad de días menor a 31 de forma automática. [9] La ventaja de usar un RTC frente a los temporizadores internos que los microcontroladores suelen incluir es que estos cuentan con una alimentación externa, usualmente una batería de litio, aunque también se usan supercondensadores en modelos más novedosos, gracias a los cuales son capaces de seguir calculando la hora y fecha actual a pesar de que el sistema se desconecte de la corriente, evitando que pierdan la referencia de tiempo y la hora se resetee. [8] Figura 1.10 Pila de litio de 3V [10]. El modelo DS3231, el cuál vamos a utilizar, tiene ciertas ventajas en cuanto a precisión frente a otros modelos como el DS1307, sobretodo a temperaturas elevadas. También cuenta con otras funcionalidades, como la capacidad de generar una onda cuadrada de varias frecuencias que puede servir como señal de reloj para otros componentes, una memoria EEPROM y una alarma, la cual otros modelos no poseen, aunque ninguna de estas son de utilidad en este proyecto. Al conjunto de todo el circuito integrado se le conoce como ZS-042. [8] Al igual que el otro sensor, este también hace uso del protocolo I2C, por lo que deberán compartir el bus de comunicación. 1.3.5 Bomba de agua JT-DC3L Es evidente que de alguna forma debemos transportar el agua desde nuestro depósito hasta el terreno para que este pueda ser regado, para ello usaremos la bomba de agua JT-DC3L. Figura 1.11 Bomba de agua JT-DC3L [11]. Este es uno de los elementos más simples del proyecto, simplemente cuenta con un cable positivo y otro negativo, al conectarlos, la bomba de agua empezará a funcionar inmediatamente. Es importante recalcar que no se debe activar cuando esta se encuentra fuera del agua, si esto ocurriera la bomba se fundiría, por lo que es vital evitar que el depósito se encuentre totalmente vacío a la hora de regar. [11]
8Capítulo 1. Introducción Las principales características de este dispositivo son las siguientes: Tabla 1.3 Características Bomba de agua JT-DC3L [11]. Especificaciones Voltaje de entrada 2,5-6 V Corriente 130-220 mA Flujo 80-120 L/h Altura máxima de bombeo 1 m Como este dispositivo no cuenta de ningún tipo de control para activar o detener su funcionamiento, será necesario hacer uso de otro elemento para realizar este trabajo, ya que los pines del microcontrolador no son capaces de suministrarle suficiente corriente y voltaje a la bomba. 1.3.6 Relé de 5V El dispositivo que realizará la tarea comentada en el apartado anterior será un relé de 5V, lo que nos permitirá alimentar a la bomba directamente desde el pin de 5V suministrado por el microcontrolador. Figura 1.12 Relé de 5V [12]. Un relé es un aparato eléctrico que funciona como un interruptor, abriendo y cerrando el paso de la corriente eléctrica, pero accionado eléctricamente. Existen diferentes tipos de relés, los más comunes y utilizados, y a los cuáles pertenece este, son los relés electromecánicos. Estos están compuestos por un electroimán, que al ser excitado, atrae a la armadura, cerrando o abriendo los contactos dependiendo de si estos son NA o NC. [13] Figura 1.13 Esquema de un relé electromecánico [14]. En nuestro caso, la bomba se conectará al contacto NC, de forma que se active cuando se cierre el relé.
1.3 Hardware 9 1.3.7 Otros Dispositivos Para el desarrollo de este proyecto también se ha hecho uso de otros elementos, los cuales se listan a continuación: •1 Protoboard para alojar el resto de componentes. Figura 1.14 Protoboard [15]. •2 resistencias de 10 KΩ. Figura 1.15 Resistencias de 10 KΩ. [16]. •2 finales de carrera. Figura 1.16 Final de Carrera [17].
10 Capítulo 1. Introducción •Cables Macho-hembra, Macho-macho y Hembra-hembra. Figura 1.17 Cables Macho-hembra [18]. •1 Portapilas de 4 pilas de 1.5 V. Figura 1.18 Portapilas de 4 pilas [19]. 1.4 Software En esta sección se comentarán las diferentes plataformas que se usaron de cara a programar el sistema y representar sus resultados. 1.4.1 Arduino IDE Arduino IDE es un editor de texto para escribir código desarrollado por la empresa del mismo nombre, además de esto, también cuenta con otras herramientas que pueden ser útiles a la hora de programar código, como son una consola de texto donde se reportarán los errores o warnings que tenga el programa, o un monitor serie para observar lo que nuestro microcontrolador retransmite a través de su puerto serie, el cuál será nuestra principal forma de comunicación con él. [ 20 ] Este software ha sido específicamente desarrollado para las placas propias de Arduino, sin embargo, haciendo uso del paquete de placas ESP8266 es posible programar nuestro microcontrolador con este programa. [2] La sencillez de su lenguaje junto a la gran comunidad que lo respalda, convierte a Arduino IDE en un entorno ideal para el desarrollo de proyectos como este, cuya programación se simplifica gracias a las numerosas librerías que podemos encontrar, de las cuáles nosotros usaremos las siguientes:
1.4 Software 11 Figura 1.19 Interfaz de Arduino IDE. •Wire.h: Permite al microcontrolador comunicarse con dispositivos que usan el bus I2C. •RTClib.h: Proporciona comandos para el uso del módulo RTC. •ThingSpeak.h: Añade instrucciones para la publicación de datos en ThingSpeak. • Adafruit_MLX90614.h: Cuenta con comandos que facilitan el uso del termómetro infrarrojo MLX90614. •ESP8266WiFi.h: Esta librería posibilita que el microcontrolador se conecte a una Red Wi-Fi. •Servo.h: Gracias ella podemos controlar los servomotores de forma sencilla. 1.4.2 ThingSpeak ThingSpeak es una plataforma de análisis de dispositivos IoT desarrollada por MathWorks, creadores de Matlab. ThingSpeak permite subir a la nube datos en vivo para ser visualizados o analizados de forma sencilla sin necesidad de construir servidores o desarrollar software web. Esta plataforma almacena los datos en canales, que permiten crear hasta 8 campos de datos por canal, en nuestro caso sólo se usará uno, pero esto nos da la posibilidad de añadir futuros sensores que obtengan otro tipo de datos sin necesidad de migrar la forma en la que son almacenados. [21] Figura 1.20 Canal de ThingSpeak perteneciente al proyecto.
3 Funcionamiento del Huerto Automatizado El verdadero signo de la inteligencia no es el conocimiento sino la imaginación. Albert Einstein E n este capítulo se comentará el comportamiento que tendrá el huerto automatizado durante su operación sobre el terreno, además de explicar el código que hace que actúe de tal manera. 3.1 Funcionamiento General Lo más recomendable a la hora de regar una planta es hacerlo una vez al día y temprano en la mañana, ya que en esos instantes las temperaturas son más suaves y el agua se evaporará más lentamente, además, en estas horas las plantas inician su actividad metabólica, por lo que es un momento conveniente para proporcionarles nutrientes, vitaminas e hidratación. Teniendo en mente estos hechos, configuraremos el sistema para que riegue a las 9 en punto de la mañana durante dos minutos, tiempo más que suficiente para que la bomba de agua se active, el agua alcance el final del tubo de riego e hidrate el terreno circular. Para recorrer todo el terreno, la boca de riego será desplazada en movimientos circulares por la "grúa" que se encuentra en el centro del huerto. La grúa realizará giros en sentido horario y antihorario de forma alternativa, recogiendo o alargando el brazo, en cuya punta se encuentra la boca de riego cada vez que se complete una vuelta en uno de los sentidos, para así alcanzar tanto las zonas interiores como exteriores del huerto. De forma simultánea, el sensor de temperatura, que también se encuentra en el extremo del brazo, irá recogiendo datos y publicándolos en ThingSpeak cada 20 segundos. Cuando no sea hora de regar, el sensor recogerá los datos de un punto estático. Para tomar datos de otros puntos del huerto, cada vez que transcurra una hora la grúa hará al MLX90614 recorrer el huerto completo tres veces. Figura 3.1 Boceto del Movimiento de la grúa. 19
20 Capítulo 3. Funcionamiento del Huerto Automatizado A la vista de este planteamiento, es evidente que el código puede dividirse en dos partes, una máquina de estados que gobierne el movimiento y el riego, y otro bloque que se encargue de recoger los datos de los sensores y publicarlos en ThingSpeak. 3.2 Máquina de Estados: Movimiento y Riego Una máquina de estados (o máquina de estados finitos) es una representación de un sistema reactivo basado en eventos que pasa de un estado a otro si se cumple la condición que controla el cambio. [27] En nuestro caso, se utilizará para definir en qué momento comenzar a mover la grúa con los servomotores y qué movimiento realizar en cada ocasión, además, también se decidirá si activar la salida de riego o no. El diagrama de nuestra máquina de estados es el siguiente: Figura 3.2 Máquina de estados de Movimiento y Riego. A continuación se explicará el funcionamiento de cada estado, además de incluir el código que rige su comportamiento: •Estado 0: Recoger el brazo. Este es el primer estado en el que entra el sistema cuando se conecta. Su única función es activar el servomotor que controla la longitud del brazo durante un segundo para recogerlo, de esta forma, cuando se inicie la secuencia de movimiento siempre empezará desde la misma posición. Al terminar el tiempo estipulado pasará directamente al siguiente estado.
3.2 Máquina de Estados: Movimiento y Riego 21 Código 3.1 Código de Estado 0: Recoger el brazo. ///////Estado Inicial para recoger el brazo en caso de que se encuentre alargado///////// case 0: servoEngranaje.write(120); //activamos el servomotor para recoger el brazo delay(1000); //Detenemos un segundo con el motor girando servoEngranaje.write(80);//parar servomotor del brazo estado=1; break; //////////////////////////////////////////////////////////////////// •Estado 1: Colocar el brazo en Posición Inicial. Al igual que el estado anterior, su único objetivo es dirigir a la grúa central hacia la posición de inicio, en este caso se hará girar al servomotor de la base en sentido antihorario hasta que se active el final de carrera 1, de forma que esta termine en el límite derecho. Una vez que se cumpla la condición se pasará al siguiente estado. Código 3.2 Código de Estado 1: Colocar el brazo en Posición Inicial. ////////////Estado Colocación de brazo en posición inicial//////////// case 1: servoBase.write(93);//giramos la base en sentido antihorario Pulsador=digitalRead(14); if (Pulsador==HIGH) { servoBase.write(76); estado=2; } break; //////////////////////////////////////////////////////////////////// •Estado 2: Espera de Movimiento. Este estado sirve para detener el funcionamiento del huerto cuando no sea necesario moverse, solo permitirá que la maquina de estados entre en el siguiente estado si se cumple una de las tres condiciones posibles: 1. Es hora de regar (entre las 9:00 AM y las 9:02 AM). 2. Ha pasado una hora desde la última vez que se activo. 3. Es la primera vez que pasa por este estado tras conectarse.
22 Capítulo 3. Funcionamiento del Huerto Automatizado Código 3.3 Código de Estado 2: Espera de Movimiento.. ////////Estado para esperar a que sea la hora de regar, o que pase una hora, al iniciar se pasara directamente a moverse/////////////// case 2: if((now.hour()==9 && now.minute()>=0 && now.minute()<=1) || (horaact==-1 && minact==-1) || (horaact<now.hour() && minact==now.minute())) { horaact=now.hour(); minact=now.minute(); vueltas=0; tiempoInicio = millis(); estado=3; } break; //////////////////////////////////////////////////////////////////// •Estado 3: Vuelta de Riego Interior. Una vez pasado el estado 2, entramos en lo que podemos llamar "ciclo de movimiento", en este primer estado del ciclo se completará la vuelta interior. El microcontrolador ordenará al servomotor de la base girar en sentido horario hasta que se active el final de carrera 2 o haya un timeout, este tiempo límite se incluye debido a que en ciertas ocasiones los servomotores pueden tardar más tiempo del debido en pulsar los finales de carrera, quedando atorados temporalmente intentando que estos se cierren, el timeout evita que esto suceda. En este estado además se comprobará si se debe activar o no la bomba de agua para regar y se aumentarán la cuenta de vueltas en 1. Código 3.4 Código de Estado 3: Vuelta de Riego Interior. /////////Estado Vuelta de riego Interior//////////////////// case 3: //Si es hora de regar, activar la bomba if((now.hour()==9 && now.minute()>=0 && now.minute()<=1)) digitalWrite(12, HIGH); else digitalWrite(12, LOW); servoBase.write(65);//giramos la base en sentido horario //cuando se pulse el final de carrera. paramos y preparamos para recoger el brazo Pulsador=digitalRead(16); if (Pulsador==HIGH || (millis() - tiempoInicio) > timeoutgiro) //Detener si se pulsa el final de carrera o pasa el timeout { servoBase.write(76); vueltas++; tiempoInicio = millis(); estado=4; } break; ////////////////////////////////////////////////////////////////////
3.2 Máquina de Estados: Movimiento y Riego 23 •Estado 4: Extender el brazo. Este estado es similar al estado 1, su única función es extender el brazo para poder comenzar la vuelta de riego exterior, tras transcurrir un segundo, que es el tiempo que el servomotor tarda en extender el brazo, se pasará al siguiente estado. Código 3.5 Código de Estado 4: Extender el brazo. ///////Estado Extender brazo////////////////////////// case 4: if ((millis() - tiempoInicio) < tiempoBrazo) { //girar mientras estemos dentro de tiempo servoEngranaje.write(40); } else{ servoEngranaje.write(80); tiempoInicio = millis(); estado=5; } break; //////////////////////////////////////////////////////////////////// •Estado 5: Vuelta de Riego Exterior. Este caso es exactamente igual que el estado 3, con la única diferencia de que el giro es en sentido antihorario y se atiende a la activación del final de carrera 1. Código 3.6 Código de Estado 5: Vuelta de Riego Exterior. ////////////////Estado Vuelta de Riego Exterior///////////////// case 5: //Si es hora de regar, activar la bomba if((now.hour()==9 && now.minute()>=0 && now.minute()<=1)) digitalWrite(12, HIGH); else digitalWrite(12, LOW); servoBase.write(93);//giramos la base en sentido antihorario //cuando se pulse el final de carrera. paramos y preparamos para alargar el brazo Pulsador=digitalRead(14); if (Pulsador==HIGH || (millis() - tiempoInicio) > timeoutgiro) //Detener si se pulsa el final de carrera o pasa el timeout { servoBase.write(76); tiempoInicio = millis(); estado=6; } break; //////////////////////////////////////////////////////////////////// •Estado 6: Recoger el brazo. Esta es la última fase del ciclo de movimiento, su funcionamiento es totalmente igual al estado 4, con la diferencia de que el giro se realiza en sentido contrario.
24 Capítulo 3. Funcionamiento del Huerto Automatizado Cuando este estado finalice se comprobará si se han completado 3 ciclos, en caso afirmativo, se pasará al estado 2 para esperar a que sea de nuevo momento de moverse, en caso contrario, saltará al estado 3 para completar las vueltas restantes. Código 3.7 Código de Estado 6: Recoger el brazo. //////////////////Estado Recoger brazo//////////////////////// case 6: if (((millis() - tiempoInicio) < tiempoBrazo)) { //girar mientras estemos dentro de tiempo servoEngranaje.write(120); } else{ servoEngranaje.write(80); if(vueltas>=3) estado=2; //comprobar si se han dado 3 vueltas else estado=3; } break; //////////////////////////////////////////////////////////////////// 3.3 Recogida de Datos y Publicación en ThingSpeak A parte de la máquina de estados, el código cuenta, como ya hemos comentado, con otra sección que será la encargada de gestionar la obtención de datos por parte del sensor de temperatura y publicar tal información tanto en ThingSpeak como en el puerto serie para compararla con la existente en el canal. Esta sección se activará cada 20 segundos, ya que ThingSpeak solo permite publicar un nuevo dato cada 15 segundos. 5 segundos extra han sido añadidos para asegurar que no se provocan errores en la subida debido a no respetar el espaciado temporal entre datos. Una vez que se active, el código actualizará el tiempo correspondiente a la última vez que publicó, ordenará al sensor que tome la temperatura del terreno y publicará esta información en el canal asignado en ThingSpeak. Tras esto, indicará por puerto serie si pudo publicar correctamente, junto con la temperatura medida y la hora que proporciona el RTC. Código 3.8 Código de Recogida de Datos y Publicación en ThingSpeak. ///////////Subida de datos a ThingSpeak///////////////////////// // Comprobar si se ha reiniciado el temporizador if (millis() < ultimoTiempo) { // Asignar un nuevo valor ultimoTiempo = millis(); tiempoInicio= millis(); } if ((millis() - ultimoTiempo) > intervaloEnvio) { // Marca de tiempo para el siguiente intervalo ultimoTiempo = millis(); // Obtener temperatura Objeto grados Celsius float temperaturaCampo = termometroIR.readObjectTempC();
3.3 Recogida de Datos y Publicación en ThingSpeak 25 //Definimos que en el campo 1 vamos a subir la variable temperaturaCampo ThingSpeak.setField(1,temperaturaCampo); //Subimos los datos al canal de Thingspeak int x = ThingSpeak.writeFields(ChannelNumber, WriteAPIKey); if (x == 200) { //En caso de exito Serial.println("Canal actualizado."); } else { //Si falla Serial.println("Problema actualizando Canal, HTTP error code " + String(x)); } //Mostramos info de RTC y sensor por puerto Serie Serial.print(now.day()); Serial.print(’/’); Serial.print(now.month()); Serial.print(’/’); Serial.print(now.year()); Serial.print(" "); Serial.print(now.hour()); Serial.print(’:’); Serial.print(now.minute()); Serial.print(’:’); Serial.print(now.second()); Serial.println(); Serial.print("Temp. Terreno => "); Serial.print(temperaturaCampo); Serial.println("o ¯C"); } ////////////////////////////////////////////////////////////////////
4 Construcción del Huerto Automatizado Los científicos estudian el mundo tal como es; los ingenieros crean el mundo que nunca ha sido. Theodore von Kármán E n este capítulo se explicará cómo se conectan los diferentes elementos electrónicos pertenecientes al sistema y cómo se construyó la estructura que conforma el huerto automatizado. 4.1 Conexionado El núcleo de nuestro sistema es el microcontrolador ESP8266, prácticamente todos los otros dispositivos se encuentran conectados a él de alguna forma, además, este se encarga de alimentar a la amplia mayoría de ellos con una de sus salidas de voltaje. El esquema eléctrico es el siguiente: Figura 4.1 Esquema eléctrico del huerto automático. • Tanto el sensor MLX90614 como el RTC se conectan en sus puertos SCL y SDA a los pines 4 y 5 respectivamente, los cuáles se corresponden a la comunicación a través del bus I2C. Adicionalmente, será necesario conectarlos a tierra y al pin de 3.3 V para su alimentación. • El relé se conectará al pin de 5 V y a tierra, además de al pin 12, que estará configurado como salida, para recibir la señal de cierre cuando sea necesario. A su vez, su entrada NA también se conectará a 5 V, mientras que en su entrada común encontraremos el pin positivo de la bomba a ser controlada, cuyo pin negativo se encuentra conectado a tierra. 27
7 Anexo Código 7.1 Código Completo del Huerto Automático. #include <Wire.h> #include <RTClib.h> //Libreria RTC #include "ThingSpeak.h" //Libreria comandos Thingspeak #include <Adafruit_MLX90614.h> //Libreria sensor de temperatura infrarrojo #include <ESP8266WiFi.h> //Libreria Wifi #include <Servo.h> //libreria Servos //variables para controlar la maquina de estados int estado=0,vueltas=0; int Pulsador=0; //variable estado finales de carrera DateTime now; //variable hora actual int horaact=-1,minact=-1; //variables ultima activacion //Variables para controlar los servos Servo servoBase, servoEngranaje; //servoEngranaje cruz servoBase palo int tiempoBrazo = 1000;//tiempo que tarda en alargar el brazo(ajustar con todo conectado) int timeoutgiro = 4000;//tiempo para girar hacia el otro lado si el brazo se atasca unsigned long tiempoInicio; //variables de tiempo para determinar cuando se inicia el movimiento //const char* ssid = "DIGIFIBRA-sdZ6"; //El SSID (nombre) del wifi al que vamos a conectarnos (casa) //const char* password = "P3bueuAkQNRd"; // Contraseña del wifi (casa) const char* ssid = "Jaime"; // El SSID (nombre) del wifi al que vamos a conectarnos (movil) const char* password = "calleolivares21"; //Contraseña del wifi (movil) WiFiClient client; //Datos acceso Canal ThingSpeak unsigned long ChannelNumber = 2439693; const char * WriteAPIKey = "1HHYTQP3FEUAGVKK"; //Temporizador ThingSpeak 20 seg 35
36 Capítulo 7. Anexo unsigned long ultimoTiempo = 0; // almacena la ultima vez que se lanzo nuestro evento unsigned long intervaloEnvio = 20000; // 20 segundos // Declaramos un RTC DS3231 RTC_DS3231 rtc; //Declaramos un MLX90614 Adafruit_MLX90614 termometroIR = Adafruit_MLX90614(); void setup () { Serial.begin(115200); //Iniciar comunicacion por puerto serie a 115200 baudios delay(10); Serial.println(’\n’); servoBase.attach(13); //Pin Servo de la Base 13 servoEngranaje.attach(15); //Pin Servo del brazo 15 servoBase.write(76); //Parar los servos servoEngranaje.write(80); WiFi.begin(ssid, password); // Nos conectamos a la red Serial.print("Connecting to "); Serial.print(ssid); Serial.println(" ..."); int i = 0; while (WiFi.status() != WL_CONNECTED) { // Esperamos la conexion al wifi, reintentando cada segundo delay(1000); Serial.print(++i); Serial.print(’ ’); } Serial.println(’\n’); Serial.println("Connection established!"); Serial.print("IP address:\t"); Serial.println(WiFi.localIP()); // Manda por puerto serie la IP del ESP 8266 // Iniciar termómetro infrarrojo con Arduino termometroIR.begin(); delay(3000); // Comprobamos si tenemos el RTC conectado if (! rtc.begin()) { Serial.println("No hay un módulo RTC"); while (1); } // Ponemos en hora, solo la primera vez, luego comentar y volver a cargar. // Ponemos en hora con los valores de la fecha y la hora en que el sketch ha sido compilado. //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); ThingSpeak.begin(client); // Inicializamos ThingSpeak pinMode(12, OUTPUT);//Pin del relé para la bomba de agua 12 pinMode(14, INPUT); //Pin del final de carrera 1 pinMode(16, INPUT); //Pin del final de carrera 2
37 } void loop () { DateTime now = rtc.now(); //Obtener hora del RTC // Comprobar si se ha reiniciado el temporizador if (millis() < tiempoInicio) { // Asignar un nuevo valor tiempoInicio = millis(); } switch(estado){ //Maquina de estados del huerto ////Estado Inicial para recoger el brazo en caso de que se encuentre alargado //// case 0: servoEngranaje.write(120); //activamos el servomotor para recoger el brazo delay(1000); //Detenemos un segundo con el motor girando servoEngranaje.write(80);//parar servomotor del brazo estado=1; break; ///////////////////////////////////////////////// /////////Estado Colocación de brazo en posición inicial//////////// case 1: servoBase.write(93);//giramos la base en sentido antihorario Pulsador=digitalRead(14); if (Pulsador==HIGH) { servoBase.write(76); estado=2; } break; ////////////////////////////////////////////////////////////////////// ////////////Estado para esperar a que sea la hora de regar, o que pase una hora , al iniciar se pasara directamente a moverse/////////// case 2: if((now.hour()==9 && now.minute()>=0 && now.minute()<=1) || (horaact==-1 && minact==-1) || (horaact<now.hour() && minact==now.minute())) { horaact=now.hour(); minact=now.minute(); vueltas=0; tiempoInicio = millis(); estado=3; } break; /////////////////////////////////////////////////////////
38 Capítulo 7. Anexo ////////////Estado Vuelta de riego Interior//////////////////////// case 3: //Si es hora de regar, activar la bomba if((now.hour()==9 && now.minute()>=0 && now.minute()<=1)) digitalWrite(12, HIGH); else digitalWrite(12, LOW); servoBase.write(65);//giramos la base en sentido horario //cuando se pulse el final de carrera. paramos y preparamos para recoger el brazo Pulsador=digitalRead(16); if (Pulsador==HIGH || (millis() - tiempoInicio) > timeoutgiro) //Detener si se pulsa el final de carrera o pasa el timeout { servoBase.write(76); vueltas++; tiempoInicio = millis(); estado=4; } break; /////////////////////////////////////////////////////// ///////////////Estado Extender brazo/////////////////////////////// case 4: if ((millis() - tiempoInicio) < tiempoBrazo) { //girar mientras estemos dentro de tiempo servoEngranaje.write(40); } else{ servoEngranaje.write(80); tiempoInicio = millis(); estado=5; } break; ////////////////////////////////////////////////// ///////////////Estado Vuelta de Riego Exterior///////////////////// case 5: //Si es hora de regar, activar la bomba if((now.hour()==9 && now.minute()>=0 && now.minute()<=1)) digitalWrite(12, HIGH); else digitalWrite(12, LOW); servoBase.write(93);//giramos la base en sentido antihorario //cuando se pulse el final de carrera. paramos y preparamos para alargar el brazo Pulsador=digitalRead(14); if (Pulsador==HIGH || (millis() - tiempoInicio) > timeoutgiro) //Detener si se pulsa el final de carrera o pasa el timeout { servoBase.write(76); tiempoInicio = millis(); estado=6; } break;
39 ///////////////////////////////////////////////////////////// ////////////////////Estado Recoger brazo////////////////////// case 6: if (((millis() - tiempoInicio) < tiempoBrazo)) { //girar mientras estemos dentro de tiempo servoEngranaje.write(120); } else{ servoEngranaje.write(80); if(vueltas>=3) estado=2; //comprobar si se han dado 3 vueltas else estado=3; } break; /////////////////////////////////////////////////////////// } ///////////Subida de datos a ThingSpeak/////////////////////// // Comprobar si se ha reiniciado el temporizador if (millis() < ultimoTiempo) { // Asignar un nuevo valor ultimoTiempo = millis(); tiempoInicio= millis(); } if ((millis() - ultimoTiempo) > intervaloEnvio) { // Marca de tiempo para el siguiente intervalo ultimoTiempo = millis(); // Obtener temperatura Objeto grados Celsius float temperaturaCampo = termometroIR.readObjectTempC(); //Definimos que en el campo 1 vamos a subir la variable temperaturaCampo ThingSpeak.setField(1,temperaturaCampo); //Subimos los datos al canal de Thingspeak int x = ThingSpeak.writeFields(ChannelNumber, WriteAPIKey); if (x == 200) { //En caso de exito Serial.println("Canal actualizado."); } else { //Si falla Serial.println("Problema actualizando Canal, HTTP error code " + String(x)); } //Mostramos info de RTC y sensor por puerto Serie Serial.print(now.day()); Serial.print(’/’); Serial.print(now.month()); Serial.print(’/’); Serial.print(now.year()); Serial.print(" "); Serial.print(now.hour()); Serial.print(’:’); Serial.print(now.minute()); Serial.print(’:’);
40 Capítulo 7. Anexo Serial.print(now.second()); Serial.println(); Serial.print("Temp. Terreno => "); Serial.print(temperaturaCampo); Serial.println("o ¯C"); } ////////////////////////////////////////////////////////////////// }
Índice de Figuras 1.1 Boceto de Huerto Automatizado 2 1.2 Feather HUZZAH ESP8266 [2] 2 1.3 Pinout Feather HUZZAH ESP8266 [2] 3 1.4 Servomotor Analógico de Rotación Continua [4] 4 1.5 Control de un servomotor convencional a través de pulsos PWM [5] 4 1.6 Termómetro Infrarrojo MLX90614 [6] 5 1.7 Precisión del MLX90614 en función de la Temperatura ambiente y de la Temperatura de la superficie a medir [6] 5 1.8 FOV de un termómetro infrarrojo [7] 6 1.9 RTC Ds3231 [8] 6 1.10 Pila de litio de 3V [10] 7 1.11 Bomba de agua JT-DC3L [11] 7 1.12 Relé de 5V [12] 8 1.13 Esquema de un relé electromecánico [14] 8 1.14 Protoboard [15] 9 1.15 Resistencias de 10 KΩ. [16] 9 1.16 Final de Carrera [17] 9 1.17 Cables Macho-hembra [18] 10 1.18 Portapilas de 4 pilas [19] 10 1.19 Interfaz de Arduino IDE 11 1.20 Canal de ThingSpeak perteneciente al proyecto 11 2.1 Topología tipo estrella [23] 13 2.2 Conexiones del bus I²C con resistencias de pull-up y esquema de drenador abierto [22] 14 2.3 Inicio de transmisión en el protocolo I²C [22] 14 2.4 Secuencia de lectura en el protocolo I²C [22] 14 2.5 Conexionado de dos UART con buses de datos [24] 15 2.6 Paquete UART [24] 15 2.7 Transmisión UART [24] 16 2.8 Esquema de conexiones al ESP8266 en modo AP [26] 16 2.9 Esquema de conexiones dek ESP8266 en modo ST [26] 17 3.1 Boceto del Movimiento de la grúa 19 3.2 Máquina de estados de Movimiento y Riego 20 4.1 Esquema eléctrico del huerto automático 27 4.2 Esquema Eléctrico de una resistencia de pull-down [28] 28 4.3 Interior de la base del Huerto Automático 29 4.4 Terreno del Huerto Automático 29 4.5 Grúa del Huerto Automático 30 41
Índice de Tablas 1.1 Características Feather HUZZAH ESP8266 [2] 3 1.2 Especificaciones Eléctricas Servomotor Analógico de rotación continua a diferentes voltajes [4] 4 1.3 Características Bomba de agua JT-DC3L [11] 8 43
50 Glosario ms Milisegundo. 4 MSB Most Significant Bit. 14 NA Normalmente abierto. 8, 27, 28 NC Normalmente cerrado. 8 PWM Pulse Width Modification. 4, 28, 41 RPM Revoluciones por minuto. 4 RTC Real Time Clock. 6, 7, 11, 24, 27, 41, VII SCL Serial Clock. 13–15, 27 SDA Serial Data. 13–15, 27 SPI Serial Peripheral Interface. 3 ST Station. 17, 41 TCP Transmission Control Protocol. 3, 16 UART Universal Asynchronous Receiver / Transmitter. 3, 15, 16, 41, VII USB Universal Serial Bus. 28 VVoltio. 3, 4, 6–8, 10, 27, 28, 41, VII