El siguiente proyecto presenta el diseño e implementación de un controlador de llenado automático. El controlador realiza el monitoreo de los niveles de agua en la cisterna y el tinaco mediante sensores ultrasónicos, permitiendo controlar el llenado del tinaco de acuerdo con los parámetros establecidos por el usuario, el controlador también tiene la capacidad de establecer las medidas del tinaco y la cisterna, por lo que se puede adaptar a cualquier sistema de llenado.
El funcionamiento de este sistema implica que, cuando el nivel de agua en el tinaco esta por debajo de un cierto umbral establecido por el usuario, el sensor detecta esta condición y envía una señal al controlador. El controlador, a su vez, activa la bomba para permitir que el agua fluya hacia el tinaco hasta que alcance a llenarse, momento en el cual la bomba se desactiva.
Este tipo de sistema es beneficioso para garantizar un suministro constante de agua, evitar el desperdicio y prevenir desbordamientos. Además, proporciona comodidad al usuario al eliminar la necesidad de supervisar manualmente el nivel de agua en el tinaco.
Circuito controlador de llenado
Sensor Ultrasónico JSN-SR04T
El sensor ultrasónico JSN-SR04T es un dispositivo que mide distancia que por medio de ultrasonido (sonar) en un rango de 25 a 450 cm; es ideal por su tamaño pequeño, bajo consumo energético, buena precisión y especialmente por su resistencia al agua.
El sensor ultrasónico JSN-SR04T es útil en aplicaciones donde el sensor estará expuesto a la intemperie compatible con una gran variedad de microcontroladores, posee una protección contra agua para poder tener usos rudos o acuáticos, por lo que es ideal para la implementación en el sistema de llenado automático.
Convertidor AC-DC HLK-5M
El convertidor HLK-5M es un pequeña fuente de alimentación que soporta un voltaje de entrada AC desde 100VAC hasta 240VAC y entrega una salida de voltaje DC fija de 5V, por lo que es ideal para alimentar el controlador de llenado.
Relevador 5V DC SRD-5VDC-SL-C
El relevador SRD-5VDC-SL-C permite controlar dispositivos que trabajen máximo a 250V/10A / 125V/10A AC y 30V/10A DC por medio de una señal de control de 5V, pueden controlar de manera aislada voltajes y corrientes alternos o directos, relativamente altos, por lo que es ideal para poder conectar una bomba de agua y activarla o desactivarla mediante el microcontrolador.
Controlador de llenado PCB
Componentes:
- Microcontrolador: PIC18F4550
- Sensores: Sensores Ultrasónicos JSN-SR04T —- x2
- Pantalla: LCD 16×2
- Convertidor AC-DC: HLK-PM01
- Relevador: SRD-5VDC-SL-C
- Transistor: 2N2222A
- Diodo: 1N4001
- LED: Verde 3mm / Rojo 3mm (opcional)
- Botones: Push Button 4 pines MicroSwitch —- x3
- Resistencias: 10k—-x3 / 330 —-x2
- Potenciometro: Trimpot 10K ohms
- Terminales: Terminal Block Phoenix 5.08mm 2p —- x2
- Conectores: JST_XH 2.50mm 4p —- x2
Parámetros
El controlador cuenta con un menu que permite establecer los parámetros del sistema de llenado:
- Inicio de llenado
- Inicio de vaciado
- Altura Cisterna
- Altura Tinaco
Cada uno de estos parámetros permite que el controlador se adapte al sistema de llenado y a las necesidades del usuario.
Inicio de llenado
Si el nivel del tinaco esta por debajo del valor establecido por el usuario, el controlador activara la bomba de agua para llenar el tinaco*.
*Siempre y cuando la cisterna tenga suficiente agua y este por encima del valor de «inicio vaciado» establecido.
Inicio de vaciado
Si el nivel del vaciado esta por encima del valor establecido por el usuario, el controlador permitirá activar la bomba de agua para llenar el tinaco.
Altura de Cisterna
Establece la distancia entre la punta del sensor y la punta del tubo que succiona el agua de la cisterna.
Altura de Tinaco
Establece la distancia entre la punta del sensor y la salida del agua del tinaco.
Altura tinaco y cisterna
Porcentaje de agua en tinaco y cisterna
En la pantalla LCD se mostraran dos valores, el primero es el porcentaje de agua en el tinaco, y el segundo el porcentaje de agua en la cisterna, el nivel de 100% de agua se establece a 20cm por debajo del sensor, esto debido a las especificaciones del sensor donde se especifica que tiene la capacidad medir la distancia desde 20 a 400 cm.
Bomba de agua activada
Cando se activa la bomba de agua el tinaco comenzara a llenarse, en este caso existirán 2 formas de desactivar la bomba, sí el tinaco se llena hasta el 99% o sí la cisterna se vacía hasta el 1%, dejando un 1% de tolerancia en ambos casos.
Código CCS (PIC C Compiler)
#include "internal_eeprom.c"
#FUSES NOMCLR
#define LCD_RS_PIN PIN_B0 // ASIGNAMOS EL PIN "B1" COMO SALIDA PARA RSW
#define LCD_RW_PIN PIN_B1 // ASIGNAMOS EL PIN "B2" COMO SALIDA PARA RW
#define LCD_ENABLE_PIN PIN_B2// ASIGNAMOS EL PIN "B0" COMO SALIDA PARA E
#define LCD_DATA4 PIN_B3 // ASIGNAMOS EL PIN "B3" COMO SALIDA PARA D4
#define LCD_DATA5 PIN_B4 // ASIGNAMOS EL PIN "B4" COMO SALIDA PARA D5
#define LCD_DATA6 PIN_B5 // ASIGNAMOS EL PIN "B5" COMO SALIDA PARA D6
#define LCD_DATA7 PIN_B6 // ASIGNAMOS EL PIN "B6" COMO SALIDA PARA D7
#include "lcd.c"
#define trig pin_D0 /*triger pin ultrasonico*/
#define echo pin_D1 /*echo pin ultrasónico*/
#define trig2 pin_D2 /*triger pin ultrasonico2*/
#define echo2 pin_D3 /*echo pin ultrasónico2*/
#define menu_ok input(pin_D4) /*botón de menu/ok*/
#define menos input(pin_D5) /*botón de menos*/
#define mas input(pin_D6) /*botón de más*/
#define motor pin_B7 /*señal de salida para activar/desactivar motor*/
int16 tinaco = 0, cisterna = 0;
int16 altura_cisterna = 0, altura_tinaco = 0;
int8 llenado = 0, vaciado = 0;
int1 estado_motor = 0;
void sensor_cisterna();
void sensor_tinaco();
void mostrar();
void menu();
void cisterna_select();
void tinaco_select();
void llenado_select();
void vaciado_select();
void activar_motor();
void main()
{
delay_ms(2000);
lcd_init ();
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
altura_cisterna=read_int16_eeprom(1);
altura_tinaco=read_int16_eeprom(3);
llenado = read_int16_eeprom(5);
vaciado = read_int16_eeprom(7);
if(altura_cisterna >= 400){altura_cisterna = 400;}
if(altura_tinaco >= 400){altura_tinaco = 400;}
if(llenado >= 100){llenado = 100;}
if(vaciado >= 100){vaciado = 100;}
mostrar();
while(TRUE)
{
sensor_cisterna();
sensor_tinaco();
mostrar();
activar_motor();
while(menu_ok)
{
delay_ms(10);
if(!menu_ok)
{
menu();
}
}
delay_ms(100);
}
}
void sensor_cisterna()
{
int16 tiempo;
int16 distancia;
output_bit(trig,1); /* enviamos pulso de la señal*/
delay_us(100); /* con 100us de ancho de pulso */
output_bit(trig,0);
while(!input(echo)) /* flanco de bajada */
{}
set_timer1(0); /* inicializa el conteo de tiempo para recibir la señal */
while(input(echo)) //flanco de subida
{}
tiempo=get_timer1(); /* cuando se recibe la señal guarda el tiempo que tardo en regresar*/
distancia = ((float)tiempo*0.0172);/* hacemos una conversion para calcular la distancia*/
if (distancia <= 20){distancia = 20;}
if (distancia >= altura_cisterna){distancia = altura_cisterna;}
cisterna = altura_cisterna*100 - distancia*100;
cisterna = cisterna / (altura_cisterna - 20);
}
void sensor_tinaco()
{
int16 tiempo;
int16 distancia;
output_bit(trig2, 1); /* enviamos pulso de la señal*/
delay_us(100); /* con 100us de ancho de pulso */
output_bit(trig2, 0);
while(!input(echo2)) /* flanco de bajada */
{}
set_timer1(0); /* inicializa el conteo de tiempo para recibir la señal */
while(input(echo2)) //flanco de subida
{}
tiempo=get_timer1(); /* cuando se recibe la señal guarda el tiempo que tardo en regresar*/
distancia=((int16)tiempo*0.0172);/* hacemos una conversion para calcular la distancia*/
if (distancia <= 20){distancia = 20;}
if (distancia >= altura_tinaco){distancia = altura_tinaco;}
tinaco = altura_tinaco*100 - distancia*100;
tinaco = tinaco / (altura_tinaco - 20);
}
void activar_motor()
{
if(estado_motor)
{
if (cisterna <= 1 || tinaco >= 99)
{
output_bit(motor, 0); //desactivando la etapa de potencia / relevador;
estado_motor = 0;
}
}else if (cisterna >= vaciado && tinaco <= llenado)
{
output_bit(motor, 1); //activando la etapa de potencia / relevador;
estado_motor = 1;
}
}
void mostrar()
{
lcd_gotoxy (1, 1);printf(LCD_PUTC, "TINACO: %03lu%% ",tinaco);
lcd_gotoxy (1, 2);printf(LCD_PUTC, "CISTERNA: %03lu%% ",cisterna);
}
void menu()
{
int8 opcion = 3;
while (true)
{
switch (opcion)
{
case 3:
lcd_gotoxy (1, 1);printf(LCD_PUTC, "INICIO LLENADO< ");
lcd_gotoxy (1, 2);printf(LCD_PUTC, "INICIO VACIADO ");
break;
case 2:
lcd_gotoxy (1, 1);printf(LCD_PUTC, "INICIO LLENADO ");
lcd_gotoxy (1, 2);printf(LCD_PUTC, "INICIO VACIADO< ");
break;
case 1:
lcd_gotoxy (1, 1);printf(LCD_PUTC, "ALTURA CISTERNA<");
lcd_gotoxy (1, 2);printf(LCD_PUTC, "ALTURA TINACO ");
break;
case 0:
lcd_gotoxy (1, 1);printf(LCD_PUTC, "ALTURA CISTERNA ");
lcd_gotoxy (1, 2);printf(LCD_PUTC, "ALTURA TINACO< ");
break;
}
while(mas)
{
delay_ms(10);
if(!mas)
{
if(opcion == 3){break;}
opcion++;
}
}
while(menos)
{
delay_ms(10);
if(!menos)
{
if(opcion == 0){break;}
opcion--;
}
}
while(menu_ok)
{
delay_ms(10);
if(!menu_ok)
{
lcd_gotoxy (1, 1);printf(LCD_PUTC, "\f");
if (opcion == 3){llenado_select();}
if (opcion == 2){vaciado_select();}
if (opcion == 1){cisterna_select();}
if (opcion == 0){tinaco_select();}
return;
}
}
}
}
void cisterna_select()
{
while(true)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "ALTURA CISTERNA");
lcd_gotoxy (1,2);printf(LCD_PUTC, "%03lucm", altura_cisterna);
while(mas)
{
delay_ms(10);
if(!mas)
{
if(altura_cisterna == 400){break;}
altura_cisterna++;
}
}
while(menos)
{
delay_ms(10);
if(!menos)
{
if(altura_cisterna == 0){break;}
altura_cisterna--;
}
}
write_int16_eeprom(1, altura_cisterna); // guarda el valor en la memoria EEPROM
while(menu_ok)
{
delay_ms(10);
if(!menu_ok)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "\f");
return;
}
}
}
}
void tinaco_select()
{
while(true)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "ALTURA TINACO");
lcd_gotoxy (1,2);printf(LCD_PUTC, "%03lucm", altura_tinaco);
while(mas)
{
delay_ms(10);
if(!mas)
{
if(altura_tinaco == 400){break;}
altura_tinaco++;
}
}
while(menos)
{
delay_ms(10);
if(!menos)
{
if(altura_tinaco == 0){break;}
altura_tinaco--;
}
}
write_int16_eeprom(3, altura_tinaco); // guarda el valor en la memoria EEPROM
while(menu_ok)
{
delay_ms(10);
if(!menu_ok)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "\f");
return;
}
}
}
}
void llenado_select()
{
while(true)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "INICIO LLENADO");
lcd_gotoxy (1,2);printf(LCD_PUTC, "%03u%%", llenado);
while(mas)
{
delay_ms(10);
if(!mas)
{
if(llenado == 100){break;}
llenado++; // incrementa la variable
}
}
while(menos)
{
delay_ms(10);
if(!menos)
{
if(llenado == 0){break;}
llenado--; // decrementa la variable
}
}
write_int16_eeprom(5, llenado); // guarda el valor en la memoria EEPROM
while(menu_ok)
{
delay_ms(10);
if(!menu_ok)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "\f");
return;
}
}
}
}
void vaciado_select()
{
while(true)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "INICIO VACIADO");
lcd_gotoxy (1,2);printf(LCD_PUTC, "%03u%%", vaciado);
while(mas)
{
delay_ms(10);
if(!mas)
{
if(vaciado == 100){break;}
vaciado++; // incrementa la variable
}
}
while(menos)
{
delay_ms(10);
if(!menos)
{
if(vaciado == 0){break;}
vaciado--; // decrementa la variable
}
}
write_int16_eeprom(7, vaciado); // guarda el valor en la memoria EEPROM
while(menu_ok)
{
delay_ms(10);
if(!menu_ok)
{
lcd_gotoxy (1,1);printf(LCD_PUTC, "\f");
return;
}
}
}
}
#use delay(internal=4000000)