Vous êtes sur la page 1sur 19

SISTEMA DE RIEGO AUTOMATIZADO PARA IMPLEMENTACIN EN

LOS HUERTOS URBANOS INTELIGENTES

ELEMENTOS UTILIZADOS:
Arduino MEGA 2560

Electrovlvula

Sensor Higrmetro

Sensor de Temperatura LM35

Sensor Electrodo PH

Mdulo de 4 Rels

Microcontrolador PIC18f4550

Tarjeta Master-Prog

Mdulo Convertidor Serial a TTL

Fuente de Voltaje

Tarjeta USBP1x

SOFTWARE UTILIZADO:
Microsoft Visual Studio C#

Compilador PIC C

Programador Arduino

Virtual Serial Port Driver

En primer lugar, se cre una interfaz en C# para la comunicacin entre la tableta del controlador y
una computadora laptop.

Esta pantalla muestra en tiempo real:

los valores de los 6 sensores de humedad (higrmetros)


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 vlvula abre o cierra
el valor actual del timer del controlador (junto con la opcin de poderlo modificar para
calibrarlo en caso de algun desfazamiento)
una grfica donde se muestran las ltimas variaciones en los valores de humedad y
temperatura

Adems, cada valor recibido de los sensores de humedad y temperatura es depositado en un


cuadro de texto lo que permite su identificacin, y junto a ellos, la posibilidad de ajustar los lmites
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 vlvula de alguna cama de cultivo.
A continuacin se presenta el cdigo en C# de este programa:
using
using
using
using
using
using
using
using
using

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

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)

{
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

{
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)

{
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;*/

}
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 comunicacin y recepcin de variables.

Despus, 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. Adems, 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 rpida configuracin tanto de puertos de salidas y entradas como de
comunicacin serial. A esta tableta se le conect el mdulo de 4 rels para controlar las
electrovlvulas 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 haba 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 permita el paso de agua para el riego).
Se sercior que el valor de temperatura estuviese registrando los cambios correspondientes a lo
largo del riego.
Despus, mediante el uso de temporizadoes, se program el controlador Arduino para que a lo largo
del da se hicieran dos sesiones de riego en las camas de cultivo, una a las 7 de la maana, y otra a
las 9 de la noche. Debido a las variaciones en la presin hidrulica, se consider evitar que ms de
una electrovlvula se abriesen al mismo tiempo, para lo cual se les dio a cada una un tiempo de 5
minutos para abrirse, y cerrarse al trmino de este tiempo o al momento en que el sensor
higromtrico lo determinase, esto con la finalidad de asegurar que cada cultivo recibiera la
suficiente cantidad de agua.
Adems, para prevenir casos de falla en el suministro elctrico 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 podra reducir a valores ms aceptables (variaciones
en minutos en lugar de horas).
A continuacin se presenta el cdigo 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;

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()

{
Serial.println(minutes);
//RIEGO DE LA MAANA
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);

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 comunicacin RS232, aunque el mdulo 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 comunicacin con una tableta Raspberry la cual ser proporcionada despus por la
carrera de Ingeniera en Sistemas.

Se emple tambin una tarjeta PICKIT para la instalacin del controlador debido a que esta ya
contaba con los pines necesarios para la conexin con el mdulo de 4 rels, el convertidor Serial a
TTL y la baquela con transistores.

A continuacin se presenta el cdigo 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;

#int_TIMER1
//Interrupcin Timer1
void temp1s(void) //Funcin
{
/////////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);

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 interrupcin general
while(1)
{
/*set_timer1(15500);
enable_interrupts(INT_TIMER1);*/
ind='A';
hum1=194;
}
}
Finalmente, es necesario mencionar los objetivos que an 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 nmero de sensores para obtener valores ms
precisos sobre la eficiencia del riego. Un solo microcontrolador PIC18f4550 consta de 13
entradas ADC, lo que en consecuencia limita a 13 el nmero de sensores disponibles. Si se
considera que cada una de las seis camas utiliza 2 sensores de hmedad y temperatura,

lmita a solo poder instalar un nico sensor de PH. Se sugiere un protocolo de esclavomaestro para los microcontroladores.
Probar, programar e instalar el sensor de PH en cada una de las camas.
Se sugiere redisear 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). Tambin
se puede considerar que el nuevo diseo sea cncavo en la base para que, mediante
escurrimiento del agua, se concentre en un solo punto el valor de PH a medir.

En este punto se
sugiere instalar el
sensor de PH para
una medicin ms
precisa de la variable.

Es necesario agregar en la brevedad posible la comunicacin WiFi debido, en primer lugar,


a que el microcontrolador por s solo no puede evitar el desfasamiento en los
temporizadores programados. Cuando la comunicacin se encuentre disponible, el valor del
temporizador podra a llegar a actualizarse constantemente para evitar este problema.
Para la fertilizacin de los cultivos, an falta la adaptacin de los depsitos del fertilizante.
Ya se cuenta con la tubera de entrada, como se puede apreciar en la siguiente imagen.

Vous aimerez peut-être aussi