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
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 4B | Pin de MCP3008 | Pin del Módulo Sensor | Función |
|---|---|---|---|
| Pin 1 (3.3V PWR) | VDD y VREF (Pines 16, 15) | VCC / 3.3V | Fuente de alimentación y referencia del ADC |
| Pin 6 (GND) | AGND y DGND (Pines 14, 9) | GND | Tierra 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ógico | Señ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
# ..."""
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
| Tarea | Comando |
|---|---|
| Actualizar paquetes | sudo apt-get update |
| Habilitar interfaz SPI | sudo raspi-config nonint do_spi 0 |
| Instalar biblioteca SPI | sudo apt-get install python3-spidev |
| Ejecutar validación (Simulación) | python3 sump_monitor.py --mock |
| Ejecutar monitor de hardware | python3 sump_monitor.py |
| Ver registro CSV | cat sump_pump_log.csv |
Flujo de trabajo
- Abre un terminal SSH hacia tu Raspberry Pi 4 Modelo B.
- Ejecuta el comando para habilitar SPI e instala
python3-spidev. - Crea una carpeta para el proyecto (por ejemplo,
mkdir ~/sump_monitor && cd ~/sump_monitor). - Crea los dos archivos de Python usando un editor de texto (por ejemplo,
nano mcp3008_driver.pyynano sump_monitor.py) y pega el código. - 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. - 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.
- Verificación de habilitación de SPI
- Acción: Ejecuta
ls /dev/spi*. - Observación esperada: Deberías ver
/dev/spidev0.0y/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.
- Acción: Ejecuta
- 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 DETECTEDseguido 5 segundos después porPUMP OFF DETECTEDy 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.
- Acción: Ejecuta
- 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 unprint(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).
- Acción: Conecta el hardware. Mantén la bomba APAGADA (OFF). Ejecuta
- 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.
- Verificación del registro de datos
- Acción: Detén el script (
Ctrl+C). Ejecutacat 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.
- Acción: Detén el script (
Quiz rápido
Solución de problemas
| Síntoma | Causa probable | Solución |
|---|---|---|
ModuleNotFoundError: No module named 'spidev' | La biblioteca SPI no está instalada. | Ejecuta sudo apt-get install python3-spidev. |
PermissionError: [Errno 13] Permission denied | El usuario no está en el grupo spi o gpio. | Ejecuta sudo us |
Encuentra este producto y/o libros sobre este tema en 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.




