Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
PROYECTO FINAL
MEDIDOR DE NIVEL DE TANQUE DE AGUA INALÁMBRICO CON ALARMA
PARTICIPANTES:
EST. MARCELO JUAN LLANOS CASTRO
EST. RIMER ORELLANA CAMACHO
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
1. INTRODUCCION
El monitoreo y control de los niveles de agua en tanques de almacenamiento es
fundamental en diversos entornos, como en sistemas de riego, industrias, edificios
residenciales y comerciales. Un sistema eficiente de medición de nivel de agua
permite optimizar el uso del recurso hídrico, evitar desbordamientos y garantizar un
suministro adecuado. Tradicionalmente, se han utilizado métodos manuales o
sistemas cableados para medir el nivel de agua, lo cual puede ser poco práctico,
propenso a errores y costoso en términos de instalación y mantenimiento. En este
contexto, el presente proyecto propone una solución inalámbrica y automatizada
para medir el nivel de agua en un tanque, utilizando tecnologías como Arduino y
módulos de comunicación inalámbrica.
2. OBJETIVO
Objetivo general: Desarrollar un sistema inalámbrico de medición de nivel de agua en un
tanque, utilizando Arduino y componentes electrónicos, que permita monitorear de forma
remota y eficiente el nivel de agua, brindando alertas visuales y sonoras en caso de niveles
críticos.
Objetivos específicos:
3. Diseñar y construir un circuito electrónico que integre un sensor ultrasónico para
medir el nivel de agua en el tanque.
4. Implementar un sistema de comunicación inalámbrica basado en módulos HC-12 para
transmitir los datos de nivel de agua desde el tanque a una unidad receptora.
5. Programar el microcontrolador Arduino para procesar los datos del sensor, calcular el
porcentaje de nivel de agua y enviar la información a través del módulo inalámbrico.
6. Desarrollar una interfaz de usuario en la unidad receptora, utilizando una pantalla
LCD, para visualizar el nivel de agua en tiempo real.
7. Incorporar alertas visuales (LEDs) y sonoras (zumbador) que indiquen niveles críticos
de agua, tanto para niveles bajos como altos.
8. Implementar funciones adicionales, como botones de control para silenciar las alarmas
y ajustar el contraste de la pantalla LCD.
9. DESCRIPCION DEL PROTOTIPO
10. DESARROLLO DEL PROYECTO
10.1. MATERIALES
No MATERIAL CANTIDAD DESCRIPCION GRAFICA
.
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
1 Led Rojo 1
2 Resistores de 4
220 ohmios
3 Pantalla LCD 1
16x2
4 Buzzer 1
5 Sensor 1
Ultrasónico HC-
SR04
6 Modulo 2
Inalámbrico HC-
12
7 Placa Arduino 2
Uno
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
8 Led Verde 1
9 Led Amarillo 1
10 Botones 2
Pulsadores
11 Resistor de 120 3
ohmios
10.2. ETAPAS DEL DESARROLLO RESPALDO CON
FOTOGRAFIAS
11. PROGRAMA ARDUINO
CODIGO DEL TRANSMISOR
# include <SoftwareSerial.h>
SoftwareSerial HC12(4, 5);
// Cambia los valores para calibrar el medidor
int MinLevel = 24; // Lectura del sensor cuando el tanque está vacío
int MaxLevel = 102; // Lectura del sensor cuando el tanque está lleno
int power = 6;
long dist_1 = 0;
long dist_2 = 0;
int Time = 0;
int trig = 3; // Pin de trigger del sensor ultrasónico
int echo = 2; // Pin de echo del sensor ultrasónico
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
void setup() {
// Para calibrar el sensor, descomenta la siguiente línea
// [Link](9600);
[Link](9600);
pinMode(trig, OUTPUT);
digitalWrite(trig, LOW);
pinMode(echo, INPUT);
pinMode(power, OUTPUT);
digitalWrite(power, 1);
}
void loop() {
Time++;
// Código estándar para obtener el valor del sensor ultrasónico
digitalWrite(trig, LOW);
delayMicroseconds(5);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
dist_1 = (pulseIn(echo, HIGH)) * 0.034 / 2; // Obtiene el valor en centímetros
if (dist_1 < MaxLevel + 100) { // Cambia si es necesario
Send_data(dist_1);
}
// Código de depuración
// [Link](dist_1);
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
// [Link]('\n');
delay(500);
}
void Send_data(int dist_1) {
// Mapea los valores del sensor a un número entre 0 y 100
int sent = map(dist_1, MinLevel, MaxLevel, 100, 0);
// Envía datos cada 100 ms
if (Time == 100) {
[Link](sent);
Time = 0;
}
// Envía datos instantáneamente cuando cambia el nivel del agua
if (dist_1 != dist_2) {
[Link](sent);
dist_2 = dist_1;
}
}
// Unidad Receptora
// Pines
/*
* --LCD--
* RS: pin D12
* E: pin D11
* D4: pin D2
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
* D5: pin D3
* D6: pin D4
* D7: pin D5
* Vo: A4
* D13: gnd
*
* --HC 12--
* Tx: pin 7
* Rx: pin 8
*
* --Botón--
* B1: pin 9
* B2: pin 10
*
* --Pines LED--
* G_led: pin A1
* R_led: pin A0
* Y_led: pin A2
*
* buzzer: A3
*/
// Definiendo bibliotecas
#include <LiquidCrystal.h> // para LCD
#include <SoftwareSerial.h> // para módulo inalámbrico HC-12
SoftwareSerial HC12(7, 8);
LiquidCrystal lcd{12, 11, 2, 3, 4, 5};
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
int tiempo_luz_fondo = 30000; // El tiempo que la luz de fondo del LCD está
encendida en milisegundos
int frecuencia_buzzer = 1000; // Frecuencia del zumbador
int tiempo_rellenar = 17000; // Tiempo de demora para el mensaje "rellenando..."
int tiempo_rellenar_mostrar = 35000; // Tiempo de visualización del mensaje
"rellenando..."
int tiempo_max_rellenar = 0;
int boton1 = 9;
boolean estado_luz_fondo = 0;
boolean estado_boton2 = 0;
boolean chequeo_boton = 0;
int estado_boton2_array[3] = { 0, 0, 0 }; // para verificar si se presionó el botón2
cuando el nivel es bajo
int valor1 = 0;
int chequeo1 = 0;
int valor2 = 0;
boolean chequeo_rellenar[3] = {0, 0, 0}; // para verificar si se presionó el botón2
cuando el nivel es alto
int data = 50;
int data_previa = 0;
int boton2 = 10;
int led_rojo = A0;
int led_amarillo = A2;
int led_verde = A1;
int buzzer = A3;
int tierra = 13;
int contraste = A4;
int luz_fondo = A5;
// Variables para multitarea
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
long p3Mili = 0;
long p1Mili = 0;
long p2Mili = 0;
long p4Mili = 0;
long p5Mili = 0;
// Caracteres personalizados para la barra de porcentaje
byte p10[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B00000,
B00000};
byte p20[8] = {B10000, B10000, B10000, B10000, B10000, B10000, B10000,
B10000};
byte p40[8] = {B11000, B11000, B11000, B11000, B11000, B11000, B11000,
B11000};
byte p60[8] = {B11100, B11100, B11100, B11100, B11100, B11100, B11100,
B11100};
byte p80[8] = {B11110, B11110, B11110, B11110, B11110, B11110, B11110,
B11110};
byte p100[8] = {B11111, B11111, B11111, B11111, B11111, B11111, B11111,
B11111};
CODIGO DEL RECEPTOR
void setup() {
// [Link](9600);
[Link](16, 2);
[Link](9600);
pinMode(boton1, INPUT);
pinMode(boton2, INPUT);
pinMode(led_rojo, OUTPUT);
pinMode(led_amarillo, OUTPUT);
pinMode(led_verde, OUTPUT);
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
pinMode(buzzer, OUTPUT);
pinMode(contraste, OUTPUT);
pinMode(tierra, OUTPUT);
pinMode(luz_fondo, OUTPUT);
[Link](0, p10);
[Link](1, p20);
[Link](2, p40);
[Link](3, p60);
[Link](4, p80);
[Link](5, p100);
analogWrite(contraste, 10);
digitalWrite(tierra, 0);
// Mensaje de inicio
[Link](0, 0);
[Link](" BIENVENIDO ");
[Link](0, 1);
[Link](" -Manusha-");
}
void loop() {
unsigned long tiempo_actual = millis(); // Obtener el temporizador actual para
multitarea
boolean estado_boton1 = digitalRead(boton1); // Botón para la luz de fondo
encender_luz_fondo(estado_boton1);
while ([Link]()) {
[Link]();
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
data = [Link]();
if ((data < 104) || (data >= 0)) {
data_previa = data;
}
if ((data > 103) || (data < 0)) {
data = data_previa;
}
mostrar_barra(data);
miniNota(data);
mostrar_porcentaje(data);
}
estado_boton2 = chequeo_boton2(data); // Botón para silenciar
nivel_1(data); // Control del LED y alarma
rellenar(data);
valor1 = data;
if (valor2 < valor1) {
chequeo_rellenar[0] = 1;
}
if ((valor2 != valor1) & (valor2 != (valor1 + 1))) {
tiempo_max_rellenar = 0;
}
valor2 = valor1;
if ((data > 90) & (data < 110)) { // Para silenciar la alarma de relleno
if (chequeo_boton == 0) {
chequeo_boton = digitalRead(boton2);
}
} else chequeo_boton = 0;
}
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
int rellenar(int data) {
unsigned long tiempo_actual = millis();
if (chequeo_rellenar[0] == 1) { // Iniciar el temporizador para verificar un valor
secundario.
if (chequeo_rellenar[1] == 0) {
chequeo1 = data;
p4Mili = tiempo_actual;
chequeo_rellenar[1] = 1; // Inicia la segunda condición
}
}
if (chequeo_rellenar[1] == 1) {
if (tiempo_actual - p4Mili > tiempo_rellenar) {
if (chequeo1 < data) {
chequeo_rellenar[2] = 1; // Comienza a mostrar el mensaje de relleno
chequeo_rellenar[0] = 0;
chequeo_rellenar[1] = 0;
p4Mili = tiempo_actual;
} else {
chequeo_rellenar[0] = 0;
chequeo_rellenar[1] = 0;
}
}
}
if (chequeo_rellenar[2] == 1) {
if ((tiempo_actual - p5Mili < tiempo_rellenar_mostrar) & ((data >= 0) & (data <
100)) & (tiempo_max_rellenar < 12000)) {
tiempo_max_rellenar++;
[Link](0, 1);
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
[Link]("Rellenando...");
boolean estado_boton1 = 1; // Enciende la luz de fondo
encender_luz_fondo(estado_boton1);
estado_boton1 = 0;
} else {
tiempo_max_rellenar = 0;
chequeo_rellenar[2] = 0;
}
} else p5Mili = tiempo_actual;
if ((data > 90) & (data < 100)) {
if (chequeo_boton == 0) { // Verifica si se presionó el botón
if (chequeo_rellenar[2] == 1) { // Verifica si se inició el relleno
if (tiempo_actual - p3Mili < 300) { // Tiempo de demora del zumbador
tone(buzzer, frecuencia_buzzer);
} else if (tiempo_actual - p3Mili > (map(data, 90, 100, 700, 300))) { // Efecto de
disminución
p3Mili = tiempo_actual;
} else noTone(buzzer);
}
} else noTone(buzzer);
} else noTone(buzzer);
return chequeo_rellenar;
}
int chequeo_boton2(int data) {
// Primera alarma comienza cuando el nivel está por debajo del 16%
if ((data < 16) || (data > 200)) { // Para alarma de nivel bajo
if (estado_boton2 == 0) {
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
estado_boton2 = digitalRead(boton2);
if (estado_boton2_array[0] == 0) { // Enciende la luz de fondo cada vez que se
presiona el botón.
estado_boton2_array[0] = 1; // Solo se ejecuta una vez cuando el límite está
por debajo del 15
boolean estado_boton1 = 1;
encender_luz_fondo(estado_boton1);
estado_boton1 = 0;
}
}
// Segunda alarma comienza cuando el nivel está por debajo del 10%
else if ((estado_boton2_array[1] == 0) & (data < 10)) {
estado_boton2_array[1] = 1; // Se ejecuta una vez cuando el límite está por
debajo del 10
boolean estado_boton1 = 1; // Enciende la luz de fondo
encender_luz_fondo(estado_boton1);
estado_boton1 = 0;
estado_boton2 = 0;
}
// Tercera alarma comienza cuando el nivel está por debajo del 5%
else if ((estado_boton2_array[2] == 0) & (data < 5)) {
estado_boton2_array[2] = 1; // Se ejecuta una vez cuando el límite está por
debajo del 5
boolean estado_boton1 = 1; // Enciende la luz de fondo
encender_luz_fondo(estado_boton1);
estado_boton1 = 0;
estado_boton2 = 0;
}
} else {
estado_boton2_array[0] = 0;
estado_boton2_array[2] = 0;
estado_boton2_array[1] = 0;
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
estado_boton2 = 0;
}
return estado_boton2;
}
// Esta función muestra mensajes
void miniNota(int data) {
if ((data < 8) || (data > 200)) {
[Link](0, 1);
[Link]("Casi Vacio "); // Mantener 16 caracteres entre ""
} else if ((data > 7) & (data < 15)) {
[Link](0, 1);
[Link]("Rellenar ");
} else if ((data > 14) & (data < 95)) {
[Link](0, 1);
[Link]("Normal ");
} else if ((data > 94) & (data < 101)) {
[Link](0, 1);
[Link]("Tanque Lleno ");
} else if ((data > 100) & (data < 110)) {
[Link](0, 1);
[Link]("Desbordando ");
}
}
// Para los LEDs
int nivel_1(int data) {
unsigned long tiempo_actual = millis();
// Enciende el LED rojo y el zumbador cuando el nivel está por debajo del 15
if ((data < 16) || (data > 200)) {
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
digitalWrite(led_rojo, 1);
digitalWrite(led_verde, 0);
digitalWrite(led_amarillo, 0);
// Para el zumbador
if (estado_boton2 == 0) {
if (tiempo_actual - p3Mili < 300) {
tone(buzzer, frecuencia_buzzer);
} else if (tiempo_actual - p3Mili > 600) {
p3Mili = tiempo_actual;
} else {
noTone(buzzer);
}
} else noTone(buzzer);
}
// Enciende el LED amarillo cuando el nivel está entre 15 y 30
else if ((data > 15) & (data < 31)) {
digitalWrite(led_amarillo, 1); // Enciende el LED amarillo
digitalWrite(led_verde, 0);
digitalWrite(led_rojo, 0);
noTone(buzzer);
}
// Enciende el LED verde cuando el nivel está entre 30 y 100
else if ((data > 30) & (data < 110)) {
digitalWrite(led_verde, 1); // Enciende el LED verde
digitalWrite(led_amarillo, 0);
digitalWrite(led_rojo, 0);
} else {
digitalWrite(led_rojo, 0);
digitalWrite(led_amarillo, 0);
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
digitalWrite(led_verde, 0);
noTone(buzzer);
}
if ((data > 16) & (data < 90)) {
noTone(buzzer);
}
}
// Enciende la luz de fondo
int encender_luz_fondo(int estado_boton1) { // Para luz de fondo del LCD
unsigned long tiempo_actual = millis();
if (estado_boton1 == 1) {
p2Mili = tiempo_actual;
}
if (tiempo_actual - p2Mili < tiempo_luz_fondo) {
digitalWrite(luz_fondo, 1);
} else digitalWrite(luz_fondo, 0);
}
// Muestra el porcentaje
void mostrar_porcentaje(int data) {
if (data < 10) {
[Link](14, 1); // Para valores de un dígito
}
if ((data < 100) & (data > 9)) {
[Link](13, 1); // Para valores de dos dígitos
}
if ((data < 1000) & (data > 99)) {
[Link](12, 1); // Para valores de tres dígitos
}
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
[Link](data);
[Link]("%");
}
// Muestra el nivel de agua como una barra
void mostrar_barra(int data) {
if ((data >= 0) & (data < 110)) {
int dplay = map(data, 0, 100, 0, 80);
if (dplay > 80) {
dplay = 80;
}
int cociente = dplay / 5; // Para bloques completos
int resto = dplay % 5; // Para bloques parciales
for (int x = 0; x < cociente; x++) {
[Link](x, 0);
[Link](5);
}
[Link](cociente, 0);
[Link](int(resto));
}
}
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
12. SIMULACION EN TINKER CAD
CIRCUITO DEL TRANSMISOR
CIRCUITO DEL RECEPTOR
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
13. CONCLUSIONES Y RECOMENDACIONES
El proyecto "Medidor de Nivel de Tanque de Agua Inalámbrico con Alarma" se ha
completado con éxito, cumpliendo con los objetivos propuestos. Después de un
arduo trabajo en el diseño, ensamblaje y programación de los componentes
electrónicos, se ha logrado implementar un sistema funcional y eficiente para el
monitoreo inalámbrico del nivel de agua en un tanque.
Durante el proceso de desarrollo, se superaron varios desafíos técnicos, como la
calibración precisa del sensor ultrasónico, el establecimiento de una comunicación
inalámbrica estable entre los módulos HC-12 y la programación de las diferentes
funcionalidades en el microcontrolador Arduino. Sin embargo, gracias a una
investigación exhaustiva, la aplicación de conocimientos adquiridos y una actitud
perseverante, se lograron sortear estos obstáculos de manera satisfactoria.
El prototipo final cumple con los requisitos establecidos, permitiendo medir y
visualizar el nivel de agua en un tanque a través de una pantalla LCD en la unidad
receptora. Además, se implementaron alertas visuales y sonoras para indicar niveles
críticos de agua, tanto para niveles bajos como altos, lo que brinda una mayor
seguridad y control sobre el sistema.
Una de las características destacadas del proyecto es su naturaleza inalámbrica, lo
que elimina la necesidad de cableado extenso y facilita la instalación y el
mantenimiento del sistema. Gracias a los módulos HC-12, la transmisión de datos se
Código
PROGRAMACIÓN Carrera T:S: Sistemas
Eléctronicos
Segundo Semestre
realiza de manera eficiente y confiable, permitiendo un monitoreo remoto del nivel de
agua.
Durante las pruebas realizadas, el sistema demostró un funcionamiento estable y
preciso, respondiendo adecuadamente a los cambios de nivel de agua en el tanque.
Las alertas visuales y sonoras se activaron correctamente en los niveles críticos
establecidos, brindando una indicación clara al usuario.
En general, el proyecto ha sido un éxito, demostrando la capacidad de integrar
diferentes componentes electrónicos y tecnologías para crear una solución práctica y
útil. Este sistema de medición de nivel de agua inalámbrico puede ser aplicado en
diversos ámbitos, como sistemas de riego, edificios residenciales y comerciales, e
incluso en entornos industriales, contribuyendo a la optimización del uso del agua y
evitando desbordamientos o falta de suministro.
RECOMENDACIONES
Explorar la posibilidad de integrar el sistema con una aplicación móvil o una
interfaz web, lo que permitiría un monitoreo remoto más conveniente y accesible.
Investigar opciones para mejorar la eficiencia energética del sistema, como la
implementación de modos de bajo consumo o el uso de fuentes de energía
renovables.
Considerar la implementación de medidas de seguridad adicionales, como
encriptación de datos y autenticación, para proteger la comunicación inalámbrica y
evitar accesos no autorizados.
Evaluar la escalabilidad del sistema para su implementación en múltiples tanques
de agua, lo que podría requerir ajustes en la configuración de los módulos
inalámbricos y la gestión de datos.
Realizar pruebas exhaustivas en diferentes entornos y condiciones para garantizar
un funcionamiento confiable y robusto del sistema.
14. BIBLIOGRAFIA
15. ANEXOS