Caso práctico: monitor de bomba de achique con Raspberry Pi

Raspberry Pi connected to a microcontroller board with jumpers and terminal blocks on a lab board labeled 'Sump-Pump-Runtime-Monitor', monitoring bilge pump runtime.

Objetivo y caso de uso

Qué construirás: Un sistema de monitoreo de corriente no invasivo que rastrea los ciclos de activación y la duración del tiempo de ejecución de una bomba de sumidero utilizando una Raspberry Pi 4 Modelo B.

Por qué es importante / Casos de uso

  • Mantenimiento predictivo: Detectar tiempos de funcionamiento de la bomba inusualmente largos que indican tomas obstruidas, cojinetes desgastados o impulsores defectuosos antes de una falla completa.
  • Prevención de inundaciones: Activar alertas si se registran cero ciclos durante lluvias intensas, lo que indica una posible pérdida de energía, un disyuntor disparado o una falla en el interruptor de flotador.
  • Análisis de capacidad: Registrar la frecuencia de los ciclos durante tormentas fuertes para determinar si la bomba es de tamaño insuficiente o si se requiere una bomba de respaldo secundaria.
  • Auditoría energética: Correlacionar la duración del tiempo de ejecución con el consumo de energía para calcular con precisión los costos de gestión del agua del sótano.

Resultado esperado

  • Muestreo analógico continuo y de baja latencia del sensor de corriente a través del ADC MCP3008.
  • Lógica de máquina de estados que detecta de manera confiable transiciones de ENCENDIDO/APAGADO basadas en un umbral de corriente ajustable con una latencia de respuesta de <50ms.
  • Registro preciso y con marca de tiempo de los recuentos totales de ciclos y duraciones precisas del tiempo de ejecución.

Audiencia: Desarrolladores de IoT, Entusiastas de la domótica; Nivel: Intermedio

Arquitectura/flujo: Sensor de corriente no invasivo → ADC MCP3008 (vía SPI) → Raspberry Pi 4 → Procesamiento de máquina de estados → Registro de datos y alertas

Nota educativa de validación

Antes de publicar este caso, el contenido pasó la puerta automática de validación de Prometeo con estado PASS. El validador comprobó los bloques de código, la estructura del artículo, los comandos copiables y la coherencia con el catálogo de dispositivos soportados.

Evidencia de validación publicada

  • Resultado automático: PASS.
  • Estructura parseada: 3 apartados, 3 tablas y 2 bloques de código detectados antes de publicar.
  • Código comprobado: 2 Python/py_compile.
  • Catálogo soportado: el texto se contrastó contra los perfiles de dispositivo validables de Prometeo y los stacks no soportados bloquean la publicación.
  • Hallazgos del informe: sin hallazgos bloqueantes.

Esta validación confirma compatibilidad sintáctica y de herramientas para el material publicado, pero no sustituye la prueba física sobre tu hardware, cableado y entorno exactos.

Nota educativa de seguridad

Este proyecto es un prototipo educativo de bajo voltaje, no un producto certificado. Antes de encender la configuración, verifica la disposición de pines de tu Raspberry Pi exacta, nunca conectes 5 V a pines GPIO de 3.3 V, desconecta la alimentación antes de cambiar el cableado y utiliza interfaces o fuentes externas adecuadas para sensores, relés, motores o cargas.

Diagrama de bloques conceptual

Vista de alto nivel: qué entra, qué procesa cada bloque y qué sale del sistema.

Arquitectura funcional

Sensor de corriente no invasivo

ADC MCP3008 (vía SPI)

Raspberry Pi 4

Procesamiento de máquina de estados

Registro de datos y alertas

Flujo conceptual de señales y responsabilidades entre bloques del dispositivo.

Requisitos previos

  • Hardware: Una Raspberry Pi 4 Modelo B con una fuente de alimentación USB-C de 5V/3A.
  • Sistema operativo: Raspberry Pi OS Bookworm de 64 bits.
  • Software: Python 3.11 instalado (por defecto en Bookworm).
  • Configuración: La interfaz SPI debe estar habilitada en Raspberry Pi OS.
  • Conocimientos: Familiaridad básica con la línea de comandos de Linux y la ejecución de scripts en Python.

Materiales

  • Microcontrolador: Raspberry Pi 4 Modelo B (cualquier configuración de RAM).
  • Módulo ADC: MCP3008 (Convertidor analógico a digital de 10 bits con interfaz SPI).
  • Sensor: Módulo sensor de corriente optoaislado. (Nota: Para este tutorial básico, asumimos un módulo que incluye un rectificador/detector de envolvente integrado, que emite un voltaje de CC constante de 0V a 3.3V proporcional a la corriente CA, en lugar de una onda sinusoidal de CA sin procesar).
  • Prototipado: Protoboard estándar y cables puente hembra-macho / macho-macho.

Configuración/Conexión

El MCP3008 utiliza la Interfaz Periférica Serial (SPI) para comunicarse con la Raspberry Pi. El sensor de corriente se conecta al primer canal (CH0) del MCP3008.

Importante: El MCP3008 será alimentado por el pin de 3.3V de la Raspberry Pi. Debido a que el voltaje de referencia del ADC (VREF) está vinculado a 3.3V, la entrada analógica del sensor nunca debe exceder los 3.3V. Asegúrate de que tu módulo sensor de corriente optoaislado esté configurado para lógica de 3.3V o tenga una salida máxima de 3.3V.

Tabla de cableado

Pin de Raspberry Pi 4BPin de MCP3008Pin del Módulo SensorFunción
Pin 1 (3.3V PWR)VDD y VREF (Pines 16, 15)VCC / 3.3VFuente de alimentación y referencia del ADC
Pin 6 (GND)AGND y DGND (Pines 14, 9)GNDTierra común
Pin 23 (SCLK)CLK (Pin 13)Reloj SPI
Pin 21 (MISO)DOUT (Pin 12)Salida de datos SPI (del ADC a la Pi)
Pin 19 (MOSI)DIN (Pin 11)Entrada de datos SPI (de la Pi al ADC)
Pin 24 (CE0)CS/SHDN (Pin 10)Selección de chip SPI
CH0 (Pin 1)OUT / AnalógicoSeñal analógica del sensor de corriente

Nota: La pinza del sensor de corriente optoaislado debe colocarse completamente alrededor de solo uno de los cables de CA aislados (ya sea el Fase o el Neutro, nunca ambos) que van a la bomba de sumidero.

Código validado

El software consta de dos archivos. El primero es una capa de abstracción de hardware (controlador) para el MCP3008, que permite que el código se ejecute en un modo de simulación (mock) sin hardware físico. El segundo es el script principal de monitoreo que contiene la máquina de estados y la lógica de registro.

Crea un directorio para tu proyecto y guarda estos archivos dentro de él.

Archivo 1: mcp3008_driver.py

"""
mcp3008_driver.py
Hardware adapter for the MCP3008 SPI ADC.
Includes a mock implementation for dry-run validation.
"""

try:
    import spidev
    SPI_AVAILABLE = True
except ImportError:
    SPI_AVAILABLE = False

class MCP3008:
    def __init__(self, bus=0, device=0, mock=False):
        """
        Initializes the MCP3008 ADC.
        :param bus: SPI bus (default 0)
        :param device: SPI device/chip select (default 0 for CE0)
        :param mock: If True, bypasses hardware and uses simulated values.
        """
        self.mock = mock
        self.mock_val = 0

        if not self.mock:
            if not SPI_AVAILABLE:
                raise RuntimeError("spidev module not found. Install it or use --mock.")
            self.spi = spidev.SpiDev()
            self.spi.open(bus, device)
            self.spi.max_speed_hz = 1350000

    def read_channel(self, channel):
        """
        Reads a 10-bit analog value from the specified channel (0-7).
        :param channel: Integer from 0 to 7.
        :return: Integer from 0 to 1023.
        """
        if channel < 0 or channel > 7:
            raise ValueError("Channel must be an integer between 0 and 7")

        if self.mock:
            return self.mock_val

        # MCP3008 SPI protocol:
        # Byte 1: Start bit (1)
        # Byte 2: Single-ended mode (1) + 3-bit channel number, shifted left by 4
        # Byte 3: Don't care (0)
        command = [1, (8 + channel) << 4, 0]
        adc_response = self.spi.xfer2(command)

        # Extract the 10-bit response from the last two bytes
        data = ((adc_response[1] & 3) << 8) + adc_response[2]
        return data

    def close(self):
        """Closes the SPI connection."""
        if not self.mock:
            self.spi.close()

Archivo 2: sump_monitor.py

Vista pública parcial del archivo validado. El código completo se muestra a miembros y en PDF/Print.

"""
sump_monitor.py
Main application for monitoring sump pump runtime.
Reads analog current data, applies threshold logic, and logs events to CSV.
"""

import argparse
import time
import datetime
import csv
import os
from mcp3008_driver import MCP3008

# Configuration
ADC_CHANNEL = 0
# Threshold out of 1023. Adjust based on your sensor's output when the pump is ON.
# 100 is roughly 0.32V on a 3.3V reference.
ON_THRESHOLD = 100 
LOG_FILE = "sump_pump_log.csv"

def initialize_csv(filepath):
    """Creates the CSV file and writes headers if it doesn't exist."""
    if not os.path.exists(filepath):
        with open(filepath, mode='w', newline='') as file:
            writer = csv.writer(file)
            writer.writerow(["Timestamp_Start", "Timestamp_End", "Duration_Seconds", "Peak_ADC_Value"])
        print(f"[*] Created new log file: {filepath}")

def log_event(filepath, start_time, end_time, peak_val):
    """Appends a completed pump cycle to the CSV log."""
    duration = round(end_time - start_time, 2)
    start_str = datetime.datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S')
    end_str = datetime.datetime.fromtimestamp(end_time).strftime('%Y-%m-%d %H:%M:%S')

    with open(filepath, mode='a', newline='') as file:
        writer = csv.writer(file)
        writer.writerow([start_str, end_str, duration, peak_val])

    print(f"[LOG] Cycle recorded: {duration} seconds (Peak ADC: {peak_val})")

def simulate_environment(mcp, script_start_time):
    """
    Simulates a pump cycling on and off for dry-run validation.
    Pump turns ON for 5 seconds every 20 seconds.
    """
    elapsed = time.time() - script_start_time
    cycle_time = elapsed % 20
    if 5 <= cycle_time <= 10:
        # Simulate pump running (high current)
        mcp.mock_val = 650 
    else:
        # Simulate pump off (noise floor)
        mcp.mock_val = 15
# ...

🔒 Este contenido es premium. Con la suscripción mensual (7 días gratis) podrás desbloquear el material didáctico completo y el pack PDF listo para imprimir.🔓 Desbloquéalo — 7 días gratis
"""
sump_monitor.py
Main application for monitoring sump pump runtime.
Reads analog current data, applies threshold logic, and logs events to CSV.
"""

import argparse
import time
import datetime
import csv
import os
from mcp3008_driver import MCP3008

# Configuration
ADC_CHANNEL = 0
# Threshold out of 1023. Adjust based on your sensor's output when the pump is ON.
# 100 is roughly 0.32V on a 3.3V reference.
ON_THRESHOLD = 100 
LOG_FILE = "sump_pump_log.csv"

def initialize_csv(filepath):
    """Creates the CSV file and writes headers if it doesn't exist."""
    if not os.path.exists(filepath):
        with open(filepath, mode='w', newline='') as file:
            writer = csv.writer(file)
            writer.writerow(["Timestamp_Start", "Timestamp_End", "Duration_Seconds", "Peak_ADC_Value"])
        print(f"[*] Created new log file: {filepath}")

def log_event(filepath, start_time, end_time, peak_val):
    """Appends a completed pump cycle to the CSV log."""
    duration = round(end_time - start_time, 2)
    start_str = datetime.datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S')
    end_str = datetime.datetime.fromtimestamp(end_time).strftime('%Y-%m-%d %H:%M:%S')

    with open(filepath, mode='a', newline='') as file:
        writer = csv.writer(file)
        writer.writerow([start_str, end_str, duration, peak_val])

    print(f"[LOG] Cycle recorded: {duration} seconds (Peak ADC: {peak_val})")

def simulate_environment(mcp, script_start_time):
    """
    Simulates a pump cycling on and off for dry-run validation.
    Pump turns ON for 5 seconds every 20 seconds.
    """
    elapsed = time.time() - script_start_time
    cycle_time = elapsed % 20
    if 5 <= cycle_time <= 10:
        # Simulate pump running (high current)
        mcp.mock_val = 650 
    else:
        # Simulate pump off (noise floor)
        mcp.mock_val = 15 

def main():
    parser = argparse.ArgumentParser(description="Sump Pump Runtime Monitor")
    parser.add_argument("--mock", action="store_true", help="Run in mock mode without physical hardware")
    args = parser.parse_args()

    print("======================================")
    print("      Sump Pump Runtime Monitor       ")
    print("======================================")

    if args.mock:
        print("[!] Running in MOCK mode. Hardware bypassed.")
    else:
        print("[!] Running in HARDWARE mode.")

    initialize_csv(LOG_FILE)

    # Initialize ADC
    adc = MCP3008(bus=0, device=0, mock=args.mock)

    # State machine variables
    pump_is_running = False
    cycle_start_time = 0
    peak_adc_in_cycle = 0
    script_start_time = time.time()

    print(f"[*] Monitoring started. Press Ctrl+C to exit.")
    print(f"[*] Threshold set to ADC > {ON_THRESHOLD}")

    try:
        while True:
            # Inject simulated data if in mock mode
            if args.mock:
                simulate_environment(adc, script_start_time)

            # Read current sensor
            current_val = adc.read_channel(ADC_CHANNEL)

            # State Machine Logic
            if current_val > ON_THRESHOLD:
                if not pump_is_running:
                    # Transition: OFF -> ON
                    pump_is_running = True
                    cycle_start_time = time.time()
                    peak_adc_in_cycle = current_val
                    print(f"[{datetime.datetime.now().strftime('%H:%M:%S')}] PUMP ON DETECTED (ADC: {current_val})")
                else:
                    # Update peak value during the cycle
                    if current_val > peak_adc_in_cycle:
                        peak_adc_in_cycle = current_val
            else:
                if pump_is_running:
                    # Transition: ON -> OFF
                    pump_is_running = False
                    cycle_end_time = time.time()
                    print(f"[{datetime.datetime.now().strftime('%H:%M:%S')}] PUMP OFF DETECTED")
                    log_event(LOG_FILE, cycle_start_time, cycle_end_time, peak_adc_in_cycle)

            # Sample rate: ~10Hz is sufficient for this application
            time.sleep(0.1)

    except KeyboardInterrupt:
        print("\n[*] Shutting down monitor gracefully...")
    finally:
        adc.close()
        print("[*] Cleanup complete. Exiting.")

if __name__ == "__main__":
    main()

Comandos de Compilación/Flasheo/Ejecución

Para configurar tu Raspberry Pi y ejecutar el proyecto, sigue estos comandos.

Tabla de comandos

TareaComando
Actualizar paquetessudo apt-get update
Habilitar interfaz SPIsudo raspi-config nonint do_spi 0
Instalar biblioteca SPIsudo apt-get install python3-spidev
Ejecutar validación (Simulación)python3 sump_monitor.py --mock
Ejecutar monitor de hardwarepython3 sump_monitor.py
Ver registro CSVcat sump_pump_log.csv

Flujo de trabajo

  1. Abre un terminal SSH hacia tu Raspberry Pi 4 Modelo B.
  2. Ejecuta el comando para habilitar SPI e instala python3-spidev.
  3. Crea una carpeta para el proyecto (por ejemplo, mkdir ~/sump_monitor && cd ~/sump_monitor).
  4. Crea los dos archivos de Python usando un editor de texto (por ejemplo, nano mcp3008_driver.py y nano sump_monitor.py) y pega el código.
  5. Prueba la lógica ejecutando el comando de simulación: python3 sump_monitor.py --mock. Déjalo ejecutar durante al menos 30 segundos para observar los ciclos simulados de la bomba.
  6. Conecta tu hardware, asegúrate de que el sensor esté sujeto de manera segura alrededor del cable correcto e inicia el monitor en vivo: python3 sump_monitor.py.

Validación paso a paso

Utiliza estos puntos de control para asegurarte de que tu sistema funciona correctamente.

  1. Verificación de habilitación de SPI
    • Acción: Ejecuta ls /dev/spi*.
    • Observación esperada: Deberías ver /dev/spidev0.0 y /dev/spidev0.1.
    • Condición de aprobación: Los dispositivos aparecen en la lista, lo que confirma que el sistema operativo ha habilitado el bus SPI.
  2. Validación del modo de simulación
    • Acción: Ejecuta python3 sump_monitor.py --mock. Espera 25 segundos.
    • Observación esperada: La consola muestra PUMP ON DETECTED seguido 5 segundos después por PUMP OFF DETECTED y un mensaje [LOG] Cycle recorded.
    • Condición de aprobación: La máquina de estados detecta con éxito las transiciones y calcula una duración de ~5.0 segundos sin hardware conectado.
  3. Verificación de la línea base del hardware
    • Acción: Conecta el hardware. Mantén la bomba APAGADA (OFF). Ejecuta python3 sump_monitor.py. (Es posible que desees agregar un print(current_val) temporal dentro del bucle para ver los datos sin procesar).
    • Observación esperada: El valor del ADC se mantiene consistentemente bajo (por ejemplo, entre 0 y 20).
    • Condición de aprobación: El nivel de ruido base está muy por debajo del ON_THRESHOLD (100).
  4. Verificación del hardware activo
    • Acción: Activa manualmente la bomba de sumidero (por ejemplo, levanta ligeramente el interruptor de flotador o vierte agua en el foso).
    • Observación esperada: El script imprime inmediatamente PUMP ON DETECTED.
    • Condición de aprobación: El valor del ADC se dispara por encima de 100, activando la máquina de estados.
  5. Verificación del registro de datos
    • Acción: Detén el script (Ctrl+C). Ejecuta cat sump_pump_log.csv.
    • Observación esperada: El CSV contiene encabezados y al menos una fila de datos con marcas de tiempo válidas y duraciones distintas de cero.
    • Condición de aprobación: El formato del archivo es correcto y los datos se guardan correctamente en el disco.

Quiz rápido

Pregunta 1: ¿Qué función cumple el MCP3008 en este monitor de bomba?




Pregunta 2: ¿Por qué se usa aislamiento u optoacoplamiento al detectar actividad de una bomba?




Pregunta 3: ¿Qué tipo de información registra el sistema?




Pregunta 4: ¿Qué base de datos local es habitual en este caso práctico?




Pregunta 5: ¿Qué evita un umbral con filtrado o antirrebote?




Pregunta 6: ¿Cuál es una comprobación segura antes de conectarlo a una instalación real?




Pregunta 7: ¿Qué tensión lógica debe respetarse en las entradas de la Raspberry Pi?




Pregunta 8: ¿Para qué puede servir detectar ciclos muy frecuentes de la bomba?




Pregunta 9: ¿Qué no debe hacer este prototipo educativo?




Pregunta 10: ¿Qué confirma la validación automatizada del caso?




Solución de problemas

SíntomaCausa probableSolución
ModuleNotFoundError: No module named 'spidev'La biblioteca SPI no está instalada.Ejecuta sudo apt-get install python3-spidev.
PermissionError: [Errno 13] Permission deniedEl usuario no está en el grupo spi o gpio.Ejecuta sudo us

Encuentra este producto y/o libros sobre este tema en Amazon

Ir a Amazon

Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.

Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Ingeniero Superior en Electrónica de Telecomunicaciones e Ingeniero en Informática (titulaciones oficiales en España).

Sígueme:
Scroll al inicio