Saltar al contenido
Nivel intermedio

Un segundo tanque con bomba sumergible

Preparar la instalación del segundo tanque

Para simular el sistema de tanque cisterna y elevado, tomaremos la maqueta realizada en la etapa anterior y agregaremos un tanque extra con otro sensor de distancia y una bomba sumergible. Los roles quedan así:

  • El tanque del nivel inicial pasa a ser la cisterna: conserva su sensor y su electroválvula (el agua de la red sigue entrando por ahí) y recibe adentro la bomba sumergible.
  • El tanque nuevo es el tanque elevado: lleva el segundo sensor bajo su tapa, montado igual que en el nivel inicial (perpendicular al fondo y protegido del agua), y recibe por su entrada la manguera que sube desde la bomba.

Las bombas sumergibles no pueden funcionar si no están por debajo del nivel del agua; por lo tanto, es muy importante asegurarnos de que el tanque cisterna sea lo suficientemente grande como para que el agua tape la bomba.

Además, programaremos la placa de modo que, cuando el nivel del agua sea inferior al de la bomba, no envíe agua al tanque elevado y espere hasta que se haya llenado lo suficiente para enviar el agua.

Esquema de los dos tanques: a la derecha, la cisterna con su sensor ultrasónico bajo la tapa, la bomba sumergible en su interior y la electroválvula en la entrada; a la izquierda, el tanque elevado con su propio sensor y la manguera de salida. Una manguera une la bomba con el tanque elevado.
El sistema completo del nivel intermedio: la cisterna (con electroválvula y bomba sumergible) alimenta al tanque elevado, y cada tanque tiene su sensor (figura original del proyecto).

Realizar las conexiones a la placa

¡Atención! Agua y electricidad no se llevan bien. En este paso la regla del nivel inicial vale doble, porque ahora hay un cable que sí entra al agua: el de la bomba sumergible. Ese cable debe entrar al tanque por arriba, con su aislación sana en todo el recorrido; el resto de las conexiones queda fuera de los tanques y por encima del nivel del agua, y el circuito se manipula siempre con las manos secas y con la maqueta desenchufada. El original trabajaba con válvula y bomba de 220 V; en esta reedición ambas son de baja tensión (el desvío está documentado en la ficha), pero los hábitos se practican como si fueran de red.

Esquema de conexión: Arduino UNO con dos sensores ultrasónicos HC-SR04 rotulados Nivel Tanque 1 y Nivel Tanque 2 (Trig y Echo a los pines 8-9 y 10-11) y dos módulos relé con señal a los pines 4 y 5; en los bornes de los relés, la electroválvula 1, la bomba de agua 1 y un enchufe de 220 V.
Esquema de conexión del nivel intermedio: se suman el segundo sensor y el relé de la bomba (figura original del proyecto). Atención: el enchufe de 220 V del original se reemplaza en esta reedición por la fuente de baja tensión.

Conectamos los componentes como indica la figura, agregando el sensor ultrasónico del segundo tanque y la bomba de agua con su relé:

  • Sensor del tanque elevado: cuatro cables dupont macho-hembra, de los pines Vcc, GND, Trig y Echo del sensor a la alimentación y a las dos entradas nuevas de la placa.
  • Bomba con su relé: un cable de la fuente de baja tensión a la bornera COM del segundo relé, de la bornera NO a un cable de la bomba, y el otro cable de la bomba de vuelta al otro polo de la fuente (el mismo lazo que armaste para la válvula).
  • Control del segundo relé: el pin + a 5V, el pin - a GND y el pin S a la salida digital nueva de la placa.

En el Arduino UNO seguimos el esquema original: los pines Trig y Echo del segundo sensor van a los pines 10 y 11 (las constantes PIN_TRIG2 y PIN_ECHO2 del código), y el pin S del relé de la bomba, al pin digital 5 (la constante PIN_RELE_BOMBA). El sensor y el relé del nivel inicial no se tocan: siguen en 8, 9 y 4.

En el ESP32, el segundo sensor y el relé de la bomba van a GPIO de propósito general seguros. Los números exactos están en las constantes PIN_TRIG2, PIN_ECHO2 y PIN_RELE_BOMBA al comienzo del código del paso siguiente: conectá cada cable al GPIO que indica su constante. Igual que en el nivel inicial, el pin Echo de este segundo sensor también necesita su divisor de dos resistencias hacia el GPIO.

El armado de este circuito tiene como función conseguir que el sensor del tanque elevado envíe una señal a la placa para activar la bomba sumergible del tanque cisterna cuando el nivel de llenado sea inferior al máximo. Si en el tanque cisterna hay agua suficiente, se activará la bomba para enviar agua al tanque elevado. La activación se mantendrá hasta que se llene el tanque elevado o hasta que el nivel de agua del tanque cisterna sea inferior al mínimo.

Programar el funcionamiento del dispositivo

Editamos nuestro programa para que contemple este tanque extra, así como su llenado, siempre que el primer tanque esté en condiciones de activar la bomba. La lógica completa tiene ahora dos decisiones por vuelta de loop():

  1. La válvula (igual que en el nivel inicial, pero ahora cuida a la cisterna): si el agua de la cisterna llegó a su altura de corte, se cierra; si bajó más allá del margen de histéresis, se abre.
  2. La bomba (la decisión nueva, con doble condición): si el tanque elevado está lleno, la bomba se apaga. Si necesita agua, antes de encenderla el programa revisa la cisterna: cuando su nivel está demasiado bajo —la distancia medida supera la distancia máxima—, la bomba quedaría al descubierto y funcionar en seco la arruina, así que también se apaga. Solo si el elevado necesita agua y la cisterna tiene suficiente, la bomba se enciende.

La guía original usa como ejemplo 40 cm de altura de corte para ambos tanques y 140 cm de distancia máxima para la cisterna: igual que en el nivel inicial, esos valores no se copian, se miden en tu maqueta y se cargan en las constantes de distancia del comienzo del código.

Ver el código completo · dos-tanques.ino
dos-tanques.ino Arduino UNO
// Sistema de dos tanques: cisterna (tanque 1) + tanque elevado (tanque 2).
// La electroválvula carga la cisterna desde la red; una bomba sumergible,
// ubicada dentro de la cisterna, sube el agua al tanque elevado.
// Cada tanque tiene su sensor ultrasónico mirando el agua desde arriba
// (menor distancia = tanque más lleno).
//
// Reglas (las del original):
//   - Válvula: cierra cuando la cisterna está llena; abre cuando hay lugar.
//   - Bomba: se apaga si el tanque elevado está lleno, O si la cisterna
//     está tan vacía que la bomba quedaría fuera del agua (una bomba
//     sumergible que trabaja en seco se arruina). Solo bombea si hay
//     lugar arriba Y agua suficiente abajo.
//
// SEGURIDAD: agua y electricidad no se llevan bien. Todas las conexiones
// eléctricas van fuera y POR ENCIMA del nivel del agua, los sensores no
// se deben mojar y la bomba sumergible solo se enciende estando bajo el
// agua. La práctica se realiza con válvula y bomba de baja tensión (12 V);
// la conexión a 220 V de la guía original queda reservada al docente o a
// una instalación supervisada, y nunca sobre la protoboard (desvío
// pedagógico acordado).
//
// Plataforma: Arduino UNO.
// Conexión (la del esquema original): sensor cisterna TRIG 8 / ECHO 9,
// relé de la válvula → pin 4; sensor tanque elevado TRIG 10 / ECHO 11,
// relé de la bomba → pin 5.
//
// Basado en: Fragmento de código 2 — Sistema de Tanques,
// Saberes Digitales (INET/EDUCAR 2019)
// Modernización: (1) constantes nombradas y pinMode en setup() en lugar
// del C generado por mBlock3. (2) Histéresis de 5 cm en las tres
// comparaciones: el original conmutaba válvula y bomba en el valor exacto
// del umbral y el ruido del HC-SR04 haría traquetear los relés.

// Sensor del tanque 1 (cisterna) y relé de la electroválvula.
const int PIN_TRIG1        = 8;
const int PIN_ECHO1        = 9;
const int PIN_RELE_VALVULA = 4;

// Sensor del tanque 2 (elevado) y relé de la bomba sumergible.
const int PIN_TRIG2      = 10;
const int PIN_ECHO2      = 11;
const int PIN_RELE_BOMBA = 5;

// Módulos relé activo-alto, como en el original (HIGH = actuador andando).
// Si tu módulo es activo-bajo, invertí solo estas dos constantes.
const int RELE_ENCENDIDO = HIGH;
const int RELE_APAGADO   = LOW;

// Distancias del ejemplo original (se ajustan midiendo en TU maqueta):
// - MINIMA1: agua a menos de 40 cm del sensor 1 = cisterna llena.
// - MAXIMA1: agua a más de 140 cm del sensor 1 = cisterna casi vacía,
//   la bomba quedaría al aire.
// - MINIMA2: agua a menos de 40 cm del sensor 2 = tanque elevado lleno.
const float DISTANCIA_MINIMA1_CM = 40.0;
const float DISTANCIA_MAXIMA1_CM = 140.0;
const float DISTANCIA_MINIMA2_CM = 40.0;

// Colchón anti-traqueteo (modernización, ver encabezado): cada umbral
// tiene una franja de 5 cm en la que no se toca el relé.
const float MARGEN_HISTERESIS_CM = 5.0;

// El original medía una vez por segundo (_delay(1)).
const unsigned long INTERVALO_MEDICION_MS = 1000;

// 58 microsegundos de eco por cada cm de distancia; el timeout evita
// esperar para siempre un eco que no llega.
const float MICROSEGUNDOS_POR_CM = 58.0;
const unsigned long TIMEOUT_ECO_US = 30000;

// Mide la distancia en cm entre un sensor y la superficie del agua.
// Si no llega eco, pulseIn devuelve 0 y la distancia da 0: se interpreta
// como "tanque lleno" y todo se apaga. Falla segura.
float medirDistanciaCm(int pinTrig, int pinEcho) {
  digitalWrite(pinTrig, LOW);
  delayMicroseconds(2);
  digitalWrite(pinTrig, HIGH); // pulso de disparo de 10 microsegundos
  delayMicroseconds(10);
  digitalWrite(pinTrig, LOW);
  return pulseIn(pinEcho, HIGH, TIMEOUT_ECO_US) / MICROSEGUNDOS_POR_CM;
}

void setup() {
  pinMode(PIN_TRIG1, OUTPUT);
  pinMode(PIN_ECHO1, INPUT);
  pinMode(PIN_TRIG2, OUTPUT);
  pinMode(PIN_ECHO2, INPUT);
  pinMode(PIN_RELE_VALVULA, OUTPUT);
  pinMode(PIN_RELE_BOMBA, OUTPUT);

  // Estado inicial seguro: válvula cerrada y bomba apagada hasta que
  // las primeras mediciones digan otra cosa.
  digitalWrite(PIN_RELE_VALVULA, RELE_APAGADO);
  digitalWrite(PIN_RELE_BOMBA, RELE_APAGADO);
}

void loop() {
  float distancia1 = medirDistanciaCm(PIN_TRIG1, PIN_ECHO1); // cisterna
  float distancia2 = medirDistanciaCm(PIN_TRIG2, PIN_ECHO2); // elevado

  // --- Válvula de la cisterna (misma lógica del nivel inicial) ---
  if (distancia1 < DISTANCIA_MINIMA1_CM) {
    // Cisterna llena: cerrar la válvula.
    digitalWrite(PIN_RELE_VALVULA, RELE_APAGADO);
  } else if (distancia1 > DISTANCIA_MINIMA1_CM + MARGEN_HISTERESIS_CM) {
    // Hay lugar: abrir la válvula.
    digitalWrite(PIN_RELE_VALVULA, RELE_ENCENDIDO);
  }
  // En la franja intermedia el relé conserva su último estado (histéresis).

  // --- Bomba sumergible (el razonamiento escalonado del original) ---
  if (distancia2 < DISTANCIA_MINIMA2_CM) {
    // El tanque elevado está lleno: no hay que bombear más.
    digitalWrite(PIN_RELE_BOMBA, RELE_APAGADO);
  } else if (distancia1 > DISTANCIA_MAXIMA1_CM) {
    // La cisterna está casi vacía: apagar la bomba ANTES de que quede
    // fuera del agua. Esta condición protege al hardware y por eso se
    // evalúa aunque arriba haga falta agua.
    digitalWrite(PIN_RELE_BOMBA, RELE_APAGADO);
  } else if (distancia2 > DISTANCIA_MINIMA2_CM + MARGEN_HISTERESIS_CM
             && distancia1 < DISTANCIA_MAXIMA1_CM - MARGEN_HISTERESIS_CM) {
    // Hay lugar arriba Y agua suficiente abajo: bombear.
    digitalWrite(PIN_RELE_BOMBA, RELE_ENCENDIDO);
  }
  // En las franjas intermedias la bomba conserva su estado (histéresis).

  delay(INTERVALO_MEDICION_MS);
}
dos-tanques.ino ESP32
// Sistema de dos tanques: cisterna (tanque 1) + tanque elevado (tanque 2).
// La electroválvula carga la cisterna desde la red; una bomba sumergible,
// ubicada dentro de la cisterna, sube el agua al tanque elevado.
// Cada tanque tiene su sensor ultrasónico mirando el agua desde arriba
// (menor distancia = tanque más lleno).
//
// Reglas (las del original):
//   - Válvula: cierra cuando la cisterna está llena; abre cuando hay lugar.
//   - Bomba: se apaga si el tanque elevado está lleno, O si la cisterna
//     está tan vacía que la bomba quedaría fuera del agua (una bomba
//     sumergible que trabaja en seco se arruina). Solo bombea si hay
//     lugar arriba Y agua suficiente abajo.
//
// SEGURIDAD: agua y electricidad no se llevan bien. Todas las conexiones
// eléctricas van fuera y POR ENCIMA del nivel del agua, los sensores no
// se deben mojar y la bomba sumergible solo se enciende estando bajo el
// agua. La práctica se realiza con válvula y bomba de baja tensión (12 V);
// la conexión a 220 V de la guía original queda reservada al docente o a
// una instalación supervisada, y nunca sobre la protoboard (desvío
// pedagógico acordado).
//
// Plataforma: ESP32 (DevKit v1).
// Conexión: sensor cisterna TRIG GPIO 5 / ECHO GPIO 18, relé de la
// válvula → GPIO 25; sensor elevado TRIG GPIO 19 / ECHO GPIO 21, relé de
// la bomba → GPIO 26.
// NOTA ELÉCTRICA (¡importante!): el ESP32 trabaja a 3,3 V. El HC-SR04
// clásico se alimenta con 5 V y su pin ECHO devuelve el eco a 5 V: eso
// dañaría el GPIO. Es OBLIGATORIO un divisor de tensión en CADA ECHO
// (ECHO —1 kΩ— GPIO —2 kΩ— GND), que baja los 5 V a ~3,3 V. TRIG no
// necesita nada: los 3,3 V del GPIO alcanzan para dispararlo.
// Alternativa sin divisores: el modelo HC-SR04P, que puede alimentarse
// directamente con 3,3 V.
//
// Basado en: Fragmento de código 2 — Sistema de Tanques,
// Saberes Digitales (INET/EDUCAR 2019)
// Modernización: (1) constantes nombradas y pinMode en setup() en lugar
// del C generado por mBlock3; portado a ESP32 (el original usaba los
// pines 8/9/4 y 10/11/5 del UNO). (2) Histéresis de 5 cm en las tres
// comparaciones: el original conmutaba válvula y bomba en el valor exacto
// del umbral y el ruido del HC-SR04 haría traquetear los relés.

// Sensor del tanque 1 (cisterna) y relé de la electroválvula.
const int PIN_TRIG1        = 5;
const int PIN_ECHO1        = 18; // con divisor 1 kΩ / 2 kΩ (ver nota)
const int PIN_RELE_VALVULA = 25;

// Sensor del tanque 2 (elevado) y relé de la bomba sumergible.
const int PIN_TRIG2      = 19;
const int PIN_ECHO2      = 21;   // con divisor 1 kΩ / 2 kΩ (ver nota)
const int PIN_RELE_BOMBA = 26;

// Módulos relé activo-alto, como en el original (HIGH = actuador andando).
// Si tu módulo es activo-bajo, invertí solo estas dos constantes.
const int RELE_ENCENDIDO = HIGH;
const int RELE_APAGADO   = LOW;

// Distancias del ejemplo original (se ajustan midiendo en TU maqueta):
// - MINIMA1: agua a menos de 40 cm del sensor 1 = cisterna llena.
// - MAXIMA1: agua a más de 140 cm del sensor 1 = cisterna casi vacía,
//   la bomba quedaría al aire.
// - MINIMA2: agua a menos de 40 cm del sensor 2 = tanque elevado lleno.
const float DISTANCIA_MINIMA1_CM = 40.0;
const float DISTANCIA_MAXIMA1_CM = 140.0;
const float DISTANCIA_MINIMA2_CM = 40.0;

// Colchón anti-traqueteo (modernización, ver encabezado): cada umbral
// tiene una franja de 5 cm en la que no se toca el relé.
const float MARGEN_HISTERESIS_CM = 5.0;

// El original medía una vez por segundo (_delay(1)).
const unsigned long INTERVALO_MEDICION_MS = 1000;

// 58 microsegundos de eco por cada cm de distancia; el timeout evita
// esperar para siempre un eco que no llega.
const float MICROSEGUNDOS_POR_CM = 58.0;
const unsigned long TIMEOUT_ECO_US = 30000;

// Mide la distancia en cm entre un sensor y la superficie del agua.
// Si no llega eco, pulseIn devuelve 0 y la distancia da 0: se interpreta
// como "tanque lleno" y todo se apaga. Falla segura.
float medirDistanciaCm(int pinTrig, int pinEcho) {
  digitalWrite(pinTrig, LOW);
  delayMicroseconds(2);
  digitalWrite(pinTrig, HIGH); // pulso de disparo de 10 microsegundos
  delayMicroseconds(10);
  digitalWrite(pinTrig, LOW);
  return pulseIn(pinEcho, HIGH, TIMEOUT_ECO_US) / MICROSEGUNDOS_POR_CM;
}

void setup() {
  pinMode(PIN_TRIG1, OUTPUT);
  pinMode(PIN_ECHO1, INPUT);
  pinMode(PIN_TRIG2, OUTPUT);
  pinMode(PIN_ECHO2, INPUT);
  pinMode(PIN_RELE_VALVULA, OUTPUT);
  pinMode(PIN_RELE_BOMBA, OUTPUT);

  // Estado inicial seguro: válvula cerrada y bomba apagada hasta que
  // las primeras mediciones digan otra cosa.
  digitalWrite(PIN_RELE_VALVULA, RELE_APAGADO);
  digitalWrite(PIN_RELE_BOMBA, RELE_APAGADO);
}

void loop() {
  float distancia1 = medirDistanciaCm(PIN_TRIG1, PIN_ECHO1); // cisterna
  float distancia2 = medirDistanciaCm(PIN_TRIG2, PIN_ECHO2); // elevado

  // --- Válvula de la cisterna (misma lógica del nivel inicial) ---
  if (distancia1 < DISTANCIA_MINIMA1_CM) {
    // Cisterna llena: cerrar la válvula.
    digitalWrite(PIN_RELE_VALVULA, RELE_APAGADO);
  } else if (distancia1 > DISTANCIA_MINIMA1_CM + MARGEN_HISTERESIS_CM) {
    // Hay lugar: abrir la válvula.
    digitalWrite(PIN_RELE_VALVULA, RELE_ENCENDIDO);
  }
  // En la franja intermedia el relé conserva su último estado (histéresis).

  // --- Bomba sumergible (el razonamiento escalonado del original) ---
  if (distancia2 < DISTANCIA_MINIMA2_CM) {
    // El tanque elevado está lleno: no hay que bombear más.
    digitalWrite(PIN_RELE_BOMBA, RELE_APAGADO);
  } else if (distancia1 > DISTANCIA_MAXIMA1_CM) {
    // La cisterna está casi vacía: apagar la bomba ANTES de que quede
    // fuera del agua. Esta condición protege al hardware y por eso se
    // evalúa aunque arriba haga falta agua.
    digitalWrite(PIN_RELE_BOMBA, RELE_APAGADO);
  } else if (distancia2 > DISTANCIA_MINIMA2_CM + MARGEN_HISTERESIS_CM
             && distancia1 < DISTANCIA_MAXIMA1_CM - MARGEN_HISTERESIS_CM) {
    // Hay lugar arriba Y agua suficiente abajo: bombear.
    digitalWrite(PIN_RELE_BOMBA, RELE_ENCENDIDO);
  }
  // En las franjas intermedias la bomba conserva su estado (histéresis).

  delay(INTERVALO_MEDICION_MS);
}
El sistema de dos tanques: la válvula cuida el llenado de la cisterna y la bomba solo trabaja si el elevado necesita agua y hay nivel suficiente para mantenerla sumergida.

Podés ver el sistema completo funcionando —la cisterna cargándose por la válvula, la bomba subiendo agua al tanque elevado y las protecciones actuando— en el simulador:

Simulación del comportamiento

La misma máquina de estados del firmware, portada a TypeScript, maneja el comportamiento del dispositivo. No se ejecuta el binario real: la ejecución del .hex con avr8js está en el roadmap.

Simulación lista. Presioná «Iniciar» para arrancar la secuencia.

Cierre del nivel

Al terminar este nivel, la maqueta reproduce el sistema de agua de un edificio real: la electroválvula carga la cisterna desde la red, la bomba sumergible sube el agua al tanque elevado cuando este lo necesita, y los dos sensores ultrasónicos vigilan los niveles. La regla de oro quedó escrita en el código: la bomba solo trabaja sumergida, gracias a la doble condición que podés señalar y explicar. En el nivel avanzado, los vecinos de Melina van a poder mirar todo esto desde el celular: vamos a publicar los niveles y los estados por Internet de las Cosas.

Evidencia de cierre

Al terminar este nivel, esto tiene que estar funcionando:

  • La maqueta tiene los dos tanques conectados: la cisterna (con la electroválvula en su entrada y la bomba sumergible adentro) y el tanque elevado, cada uno con su sensor ultrasónico.
  • La bomba solo se enciende cuando el tanque elevado necesita agua Y la cisterna tiene agua suficiente para mantenerla sumergida.
  • Podés explicar por qué la bomba nunca debe funcionar en seco y señalar en el código la condición que lo evita.