sistema de riego automatizado

19
SISTEMA DE RIEGO AUTOMATIZADO PARA IMPLEMENTACIÓN EN LOS HUERTOS URBANOS INTELIGENTES ELEMENTOS UTILIZADOS: Arduino MEGA 2560 Electroválvula Sensor Higrómetro

Upload: jorge-enrique-jimenez-manzo

Post on 10-Dec-2015

273 views

Category:

Documents


4 download

DESCRIPTION

Manual para crear Sistema de Riego Automatizado

TRANSCRIPT

Page 1: Sistema de Riego Automatizado

SISTEMA DE RIEGO AUTOMATIZADO PARA IMPLEMENTACIÓN EN

LOS HUERTOS URBANOS INTELIGENTES

ELEMENTOS UTILIZADOS:

Arduino MEGA 2560

Electroválvula

Sensor Higrómetro

Page 2: Sistema de Riego Automatizado

Sensor de Temperatura LM35

Sensor Electrodo PH

Módulo de 4 Relés

Page 3: Sistema de Riego Automatizado

Microcontrolador PIC18f4550

Tarjeta Master-Prog

Módulo Convertidor Serial a TTL

Fuente de Voltaje

Page 4: Sistema de Riego Automatizado

Tarjeta USBP1x

SOFTWARE UTILIZADO:

Microsoft Visual Studio – C#

Compilador PIC C

Page 5: Sistema de Riego Automatizado

Programador Arduino

Virtual Serial Port Driver

Page 6: Sistema de Riego Automatizado

En primer lugar, se creó una interfaz en C# para la comunicación entre la tableta del controlador y

una computadora laptop.

Esta pantalla muestra en tiempo real:

los valores de los 6 sensores de humedad (higrómetros)

los valores de los 6 sensores de temperatura LM35

el dato actual recibido por parte del PIC

el valor enviado al controlador para determinar si alguna electro válvula abre o cierra

el valor actual del timer del controlador (junto con la opción de poderlo modificar para

calibrarlo en caso de algun desfazamiento)

una gráfica donde se muestran las últimas variaciones en los valores de humedad y

temperatura

Además, cada valor recibido de los sensores de humedad y temperatura es “depositado” en un

cuadro de texto lo que permite su identificación, y junto a ellos, la posibilidad de ajustar los límites

tanto superior como inferior (superior refiriendose a un exceso de humedad o temperatura, e

inversamente, inferior refiriendose a un valor de humedad bajo y una temperatura baja) con lo cual

se pretende determinar si es necesario abrir o cerrar la válvula de alguna cama de cultivo.

A continuación se presenta el código en C# de este programa:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;

Page 7: Sistema de Riego Automatizado

using System.IO.Ports; using System.Threading; using System.Text.RegularExpressions; namespace Aspersor { public partial class Form1 : Form { char cara; double conv = 0; string Recibirdato; string BufferEnvio="0"; string BufferIn; string sensor; char index; char index2; public Form1() { InitializeComponent(); if (!serialPort1.IsOpen) { try { serialPort1.Open(); } catch (System.Exception ex) { MessageBox.Show(ex.ToString()); } serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Recibir); } } private void Recibir(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { Recibirdato = ""; Thread.Sleep(250); Recibirdato += serialPort1.ReadExisting(); if (serialPort1.BytesToRead > 0) Recibirdato += serialPort1.ReadExisting(); string linea; linea = Recibirdato; this.Invoke(new EventHandler(actualizar)); } private void actualizar(object sender, EventArgs e) { //int IniAN0 = Recibirdato.IndexOf("W"); //int FinAN0 = Recibirdato.IndexOf("X"); int Tamanio = Recibirdato.Length; cara = Recibirdato[Recibirdato.Length - 1]; try { index = Recibirdato[0]; index2 = Recibirdato[1]; } catch (Exception ex)

Page 8: Sistema de Riego Automatizado

{ index = 'C'; index2 = 'C'; } label8.Text = index2.ToString()+Recibirdato.Length.ToString() + Recibirdato; if (Recibirdato.Length > 8) { Recibirdato = ""; } Recibirdato = Regex.Replace(Recibirdato,"[^0-9]+",string.Empty); // /*if (Recibirdato.Length >= 1) { int temp = Convert.ToInt32(Recibirdato); switch (temp) { case 0: BufferEnvio = "0"; break; case 1: BufferEnvio = "1"; break; case 2: BufferEnvio = "2"; break; case 3: BufferEnvio = "3"; break; case 4: BufferEnvio = "4"; break; case 5: BufferEnvio = "5"; break; case 6: BufferEnvio = "6"; break; case 7: BufferEnvio = "7"; break; case 8: BufferEnvio = "8"; break; case 9: BufferEnvio = "9"; break; default: break; } sensor = "Sensor 1"; temp = 0; }*/ switch (index) { case 'A': try

Page 9: Sistema de Riego Automatizado

{ conv = (Convert.ToDouble(Recibirdato) * 5.7) / 10.24; //conv = Convert.ToDouble(Recibirdato); tbxSensorT3.Text = conv.ToString(); if (Convert.ToInt16(conv) < numTmin3.Value) { tbxSensorT3.BackColor = Color.LightBlue; BufferEnvio = "0"; } else if (Convert.ToInt16(conv) > numTmax3.Value) { tbxSensorT3.BackColor = Color.OrangeRed; BufferEnvio = "1"; } else { tbxSensorT3.BackColor = Color.YellowGreen; BufferEnvio = "0"; } } catch(Exception ex) { } break; default: break; case 'T': switch (index2) { case 'X': lblHora.Text = Recibirdato; break; case 'C': tbxSensorT1.Text = Recibirdato; if (Convert.ToInt16(Recibirdato) < numTmin1.Value) { tbxSensorT1.BackColor = Color.LightBlue; } else if (Convert.ToInt16(Recibirdato) > numTmax1.Value) { tbxSensorT1.BackColor = Color.OrangeRed; } else { tbxSensorT1.BackColor = Color.YellowGreen; } break; case 'A': conv = (Convert.ToDouble(Recibirdato) * 5.7) / 10.24; //conv = Convert.ToDouble(Recibirdato); tbxSensorT3.Text = conv.ToString(); if (Convert.ToInt16(conv) < numTmin3.Value) { tbxSensorT3.BackColor = Color.LightBlue; BufferEnvio = "0"; } else if (Convert.ToInt16(conv) > numTmax3.Value)

Page 10: Sistema de Riego Automatizado

{ tbxSensorT3.BackColor = Color.OrangeRed; BufferEnvio = "1"; } else { tbxSensorT3.BackColor = Color.YellowGreen; BufferEnvio = "0"; } break; default: break; } break; /*case 'H': switch (index2) { case 'C': tbxSensorH1.Text = Recibirdato; /*if (Convert.ToInt16(Recibirdato) < numTmin1.Value) { tbxSensorT1.BackColor = Color.LightBlue; } else if (Convert.ToInt16(Recibirdato) > numTmax1.Value) { tbxSensorT1.BackColor = Color.OrangeRed; } else { tbxSensorT1.BackColor = Color.YellowGreen; } break; case 'A': conv = (Convert.ToDouble(Recibirdato) * .57) / 10.24; //conv = Convert.ToDouble(Recibirdato); tbxSensorH3.Text = conv.ToString(); if (Convert.ToInt16(conv) < numHmin3.Value) { tbxSensorH3.BackColor = Color.LightBlue; BufferEnvio = "2"; } else if (Convert.ToInt16(conv) > numHmax3.Value) { tbxSensorH3.BackColor = Color.OrangeRed; BufferEnvio = "3"; } else { tbxSensorH3.BackColor = Color.YellowGreen; BufferEnvio = "2"; } break; default: break; } break; default: break;*/

Page 11: Sistema de Riego Automatizado

} Monitor.Text = ""; Monitor.Text += Recibirdato+"\r\n"+BufferEnvio+" --> "+index2; chart1.Series["Temperatura"].Points.Clear(); chart1.Series["Temperatura"].Points.AddXY(""+sensor+"", ""+Recibirdato+""); chart1.Update(); //serialPort1.DiscardOutBuffer(); //serialPort1.Write(BufferEnvio); Recibirdato = ""; } private void btnSalir_Click(object sender, EventArgs e) { Close(); } private void btnSendTime_Click(object sender, EventArgs e) { string hora, minu, segu; if(numHora.Value.ToString().Length<2) { hora="0"+numHora.Value.ToString(); } else { hora = numHora.Value.ToString(); } if (numMinu.Value.ToString().Length < 2) { minu = "0" + numMinu.Value.ToString(); } else { minu = numMinu.Value.ToString(); } if (numSegu.Value.ToString().Length < 2) { segu = "0" + numSegu.Value.ToString(); } else { segu = numSegu.Value.ToString(); } lblHoraEnvio.Text = hora+":"+minu+":"+segu; BufferEnvio = "XX"+hora+minu+segu; serialPort1.DiscardOutBuffer(); serialPort1.Write(BufferEnvio); } } }

Se utilizó el software Virtual Serial Port Driver para emular los puertos COM al momento de las simulaciones con Proteus para la correcta comunicación y recepción de variables.

Page 12: Sistema de Riego Automatizado

Después, a cada sensor de temperatura y de humedad, se les soldaron alrededor de 7 metros de cable UTP (para cubrir la distancia del centro de la cama de cultivo a la baquelita donde estaba instalado el controlador) y se aislaron contra el agua algunas partes expuestas. Además, se tuvo que instalar una baquela con capacitores para reducir las interferencias causadas principalmente por las distancias tan largas de los cables. Se utilizó una tableta Arduino Mega 2560 para realizar las primeras demostraciones del sistema de

riego, debido a su sencilla y rápida configuración tanto de puertos de salidas y entradas como de

comunicación serial. A esta tableta se le conectó el módulo de 4 relés para controlar las

electroválvulas instaladas en las camas de cultivo y la baquela de capacitores de los sensores.

Durante las primeras pruebas, se emplearon únicamente un sensor de humedad y uno de

temperatura. El sensor de humedad determinaba, a partir de cierto valor de voltaje, si la tierra bajo

riego había alcanzado un valor de humedad aceptable (lo que cerraba el paso de agua), y en caso

contrario, si los valores de humedad eran muy bajos (lo cual permitía el paso de agua para el riego).

Se sercioró que el valor de temperatura estuviese registrando los cambios correspondientes a lo

largo del riego.

Después, mediante el uso de temporizadoes, se programó el controlador Arduino para que a lo largo

del día se hicieran dos sesiones de riego en las camas de cultivo, una a las 7 de la mañana, y otra a

las 9 de la noche. Debido a las variaciones en la presión hidráulica, se consideró evitar que más de

una electroválvula se abriesen al mismo tiempo, para lo cual se les dio a cada una un tiempo de 5

minutos para abrirse, y cerrarse al término de este tiempo o al momento en que el sensor

higrométrico lo determinase, esto con la finalidad de asegurar que cada cultivo recibiera la

suficiente cantidad de agua.

Además, para prevenir casos de falla en el suministro eléctrico de CFE, se consideró que el valor de

las variables del temporizador se almacenasen en la memoria EEPROM del controlador. Si bien, esto

no previene los desfazamientos, al menos los podría reducir a valores más aceptables (variaciones

en minutos en lugar de horas).

A continuación se presenta el código escrito para el Arduino MEGA 2560:

#include <EEPROM.h> // avr-libc library includes #include <avr/io.h> #include <avr/interrupt.h> #define VALVPIN1 2 #define VALVPIN2 3 #define VALVPIN3 4 #define VALVPIN4 5 int sf=0; int ss=1; int sm=2; int sh=3;

Page 13: Sistema de Riego Automatizado

int flag; int seconds=0; int minutes=0; int hours=7; String envio; void setup() { pinMode(VALVPIN1, OUTPUT); pinMode(VALVPIN2, OUTPUT); pinMode(VALVPIN3, OUTPUT); pinMode(VALVPIN4, OUTPUT); digitalWrite(VALVPIN1,HIGH); digitalWrite(VALVPIN2,HIGH); digitalWrite(VALVPIN3,HIGH); digitalWrite(VALVPIN4,HIGH); flag = EEPROM.read(sf); if(flag==0) { seconds = EEPROM.read(ss); minutes = EEPROM.read(sm); hours = EEPROM.read(sh); } // initialize Timer1 cli(); // disable global interrupts TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B // set compare match register to desired timer count: OCR1A = 15624; // turn on CTC mode: TCCR1B |= (1 << WGM12); // Set CS10 and CS12 bits for 1024 prescaler: TCCR1B |= (1 << CS10); TCCR1B |= (1 << CS12); // enable timer compare interrupt: TIMSK1 |= (1 << OCIE1A); // enable global interrupts: sei(); Serial.begin(9600); } void loop()

Page 14: Sistema de Riego Automatizado

{ Serial.println(minutes); //RIEGO DE LA MAÑANA if((minutes>=0 && minutes<5) && hours==7) { digitalWrite(VALVPIN1,LOW); } if((minutes>=5 && minutes<10) && hours==7) { digitalWrite(VALVPIN2,LOW); digitalWrite(VALVPIN1,HIGH); } if((minutes>=10 && minutes<15) && hours==7) { digitalWrite(VALVPIN3,LOW); digitalWrite(VALVPIN2,HIGH); } if((minutes>=15 && minutes<20) && hours==7) { digitalWrite(VALVPIN4,LOW); digitalWrite(VALVPIN3,HIGH); } if(minutes>=20 && hours==7) { digitalWrite(VALVPIN4,HIGH); } //RIEGO DE LA NOCHE if((minutes>=0 && minutes<5) && hours==21) { digitalWrite(VALVPIN1,LOW); } if((minutes>=5 && minutes<10) && hours==21) { digitalWrite(VALVPIN2,LOW); digitalWrite(VALVPIN1,HIGH); } if((minutes>=10 && minutes<15) && hours==21) { digitalWrite(VALVPIN3,LOW);

Page 15: Sistema de Riego Automatizado

digitalWrite(VALVPIN2,HIGH); } if((minutes>=15 && minutes<20) && hours==21) { digitalWrite(VALVPIN4,LOW); digitalWrite(VALVPIN3,HIGH); } if(minutes>=20 && hours==21) { digitalWrite(VALVPIN4,HIGH); } } ISR(TIMER1_COMPA_vect) { seconds++; if (seconds >= 60) { seconds = 0; minutes++; } if(minutes >= 60) { minutes=0; hours++; } if(hours >= 24) { hours=0; } EEPROM.write(ss, seconds); EEPROM.write(sm, minutes); EEPROM.write(sh, hours); EEPROM.write(sf, 0); //digitalWrite(LEDPIN, !digitalRead(LEDPIN));*/ } En la etapa final del proyecto, se sustituyó el controlador Arduino por el microcontrolador

PIC18f4550. Las funciones principales que realizaba el anterior controlador se mantuvieron y se

agregaron las funciones de comunicación RS232, aunque el módulo Serial a TTL no quedó instalado

al final debido a que no era necesario para las funciones que realiza actualmente el controlador,

esto es, la comunicación con una tableta Raspberry la cual será proporcionada después por la

carrera de Ingeniería en Sistemas.

Page 16: Sistema de Riego Automatizado

Se empleó también una tarjeta PICKIT para la instalación del controlador debido a que esta ya

contaba con los pines necesarios para la conexión con el módulo de 4 relés, el convertidor Serial a

TTL y la baquela con transistores.

A continuación se presenta el código escrito para controlador PIC 18f4550:

#include <18f4550.h> #device adc=8 #use delay(clock=48M) #fuses HS #fuses HSPLL #fuses PLL5 #fuses CPUDIV1 #fuses PUT #fuses NOWRT #fuses NOWDT #fuses NOBROWNOUT #fuses NOPROTECT #fuses NODEBUG #include <LCD_D.c> #use rs232(baud=9600, parity=N, xmit=pin_c6, rcv=pin_c7, bits=8) #define vv1 PIN_B3 //////VALVULA/RELAY 1 #define vv2 PIN_B4 //////VALVULA/RELAY 2 #define vv3 PIN_B5 //////VALVULA/RELAY 3 #define vv4 PIN_B6 //////VALVULA/RELAY 4 int8 hum1=0,hum2=0,hum3=0,hum4=0; int seg=0,min=0,hor=18; char ind; int8 cont=0; int8 e1=0,e2=0,e3=0,e4=0,e5=0,e6=0,e7=0,e8=0;

Page 17: Sistema de Riego Automatizado

#int_TIMER1 //Interrupción Timer1 void temp1s(void) //Función { /////////TIEMPO//////////// if(cont>=25) { seg++; cont=0; /*printf("TX%u:%u:%u",hor,min,seg); ind='A'; /*set_adc_channel(0); hum1=read_adc(); printf("H%c%u",ind,hum1); /*ind='B'; set_adc_channel(1); hum2=read_adc(); printf("%c%u",ind,hum2); ind='C'; set_adc_channel(2); hum3=read_adc(); printf("%c%u",ind,hum3); ind='D'; set_adc_channel(3); hum4=read_adc(); printf("%c%u",ind,hum4);*/ } if(seg>=60) { min++; seg=0; } if(min>=60) { hor++; min=0; } if(hor>=24) { hor=0; } ////////RUTINAS DIARIAS////////// if((hor==7 && (min>=0 && min<5))||(hor==21 && (min>=0 && min<5))) { output_LOW(vv1); } if((hor==7 && (min>=5 && min<10))||(hor==21 && (min>=5 && min<10))) { output_HIGH(vv1);

Page 18: Sistema de Riego Automatizado

output_LOW(vv2); } if((hor==7 && (min>=10 && min<15))||(hor==21 && (min>=10 && min<15))) { output_HIGH(vv2); output_LOW(vv3); } if((hor==7 && (min>=15 && min<20))||(hor==21 && (min>=15 && min<20))) { output_HIGH(vv3); output_LOW(vv4); } if((hor==7 && min>20)||(hor==21 && min>20)) { output_HIGH(vv4); } set_timer1 (5536); //recarga del TMR1 cont++; } void main() { port_b_pullups(TRUE); //setup_adc_ports(AN0); setup_adc(ADC_CLOCK_INTERNAL); enable_interrupts(INT_RDA); setup_timer_1 (T1_INTERNAL |T1_DIV_BY_8); set_timer1(5536); enable_interrupts(INT_TIMER1); enable_interrupts(global); //habilita interrupción general while(1) { /*set_timer1(15500); enable_interrupts(INT_TIMER1);*/ ind='A'; hum1=194; } } Finalmente, es necesario mencionar los objetivos que aún quedan pendientes por completar:

Crear una baquelita capaz de albergar al menos 3 microcontroladores con la finalidad de que en un futuro se necesiten ampliar el número de sensores para obtener valores más precisos sobre la eficiencia del riego. Un solo microcontrolador PIC18f4550 consta de 13 entradas ADC, lo que en consecuencia limita a 13 el número de sensores disponibles. Si se considera que cada una de las seis camas utiliza 2 sensores de húmedad y temperatura,

Page 19: Sistema de Riego Automatizado

límita a solo poder instalar un único sensor de PH. Se sugiere un protocolo de esclavo-maestro para los microcontroladores.

Probar, programar e instalar el sensor de PH en cada una de las camas.

Se sugiere rediseñar la estructura de las camas de cultivos actuales debido a que no cuentan con un espacio para albergar lo cables (los cuales estan expuestos a la intemperie). También se puede considerar que el nuevo diseño sea cóncavo en la base para que, mediante escurrimiento del agua, se concentre en un solo punto el valor de PH a medir.

Es necesario agregar en la brevedad posible la comunicación WiFi debido, en primer lugar,

a que el microcontrolador por sí solo no puede evitar el desfasamiento en los

temporizadores programados. Cuando la comunicación se encuentre disponible, el valor del

temporizador podría a llegar a actualizarse constantemente para evitar este problema.

Para la fertilización de los cultivos, aún falta la adaptación de los depósitos del fertilizante.

Ya se cuenta con la tubería de entrada, como se puede apreciar en la siguiente imagen.

En este punto se

sugiere instalar el

sensor de PH para

una medición más

precisa de la variable.