from machine import Pin, ADC, PWM
import time
class RainDetectionSystem:
def __init__(self):
# Configuración del sensor de lluvia (ADC)
self.rain_sensor = ADC(Pin(4)) # Pin analógico para sensor de lluvia
self.rain_sensor.atten(ADC.ATTN_11DB) # Para leer voltajes de 0-3.3V
# Configuración de los 8 LEDs
self.leds = []
led_pins = [12, 13, 14, 15, 16, 17, 18, 19] # Pines digitales para LEDs
for pin_num in led_pins:
led = Pin(pin_num, Pin.OUT)
led.off() # Inicializar apagados
self.leds.append(led)
# Configuración del zumbador (PWM para frecuencia variable)
self.buzzer = PWM(Pin(21)) # Pin PWM para el zumbador
self.buzzer.duty(0) # Inicializar silenciado
# Parámetros del sistema - ESTOS NECESITAN CALIBRACIÓN
self.min_rain_value = 0 # Valor mínimo del sensor (seco) - AJUSTAR
self.max_rain_value = 4095 # Valor máximo del sensor (muy mojado) - AJUSTAR
self.min_frequency = 200 # Frecuencia mínima del zumbador (Hz)
self.max_frequency = 2000 # Frecuencia máxima del zumbador (Hz)
self.buzzer_duty = 512 # Intensidad del zumbador (0-1023)
print("Sistema de detección de lluvia inicializado")
print("¡IMPORTANTE! Ejecuta calibrate_sensor() primero para ajustar valores")
print("Pines LEDs:", led_pins)
print("Pin sensor lluvia: 4")
print("Pin zumbador: 21")
def read_rain_intensity(self):
"""
Lee el valor del sensor de lluvia y lo convierte a porcentaje
Returns: intensidad de lluvia (0-100%)
"""
raw_value = self.rain_sensor.read()
# CALIBRACIÓN AUTOMÁTICA: descomentar la siguiente línea para ver valores reales
# print(f"Valor crudo del sensor: {raw_value}")
# Lógica normal: mayor valor ADC = más agua = mayor intensidad
# Si tu sensor funciona al revés, cambia esta fórmula
intensity = (raw_value / self.max_rain_value) * 100
intensity = max(0, min(100, intensity)) # Limitar entre 0-100
return intensity, raw_value
def control_leds(self, intensity):
"""
Controla la secuencia de LEDs basada en la intensidad de lluvia
intensity: 0-100%
"""
# Calcular cuántos LEDs deben estar encendidos
num_leds_on = int((intensity / 100) * len(self.leds))
# Encender/apagar LEDs según la intensidad
for i, led in enumerate(self.leds):
if i < num_leds_on:
led.on()
else:
led.off()
return num_leds_on
def control_buzzer(self, intensity):
"""
Controla la frecuencia del zumbador basada en la intensidad de lluvia
intensity: 0-100%
"""
if intensity > 5: # Solo sonar si hay algo de lluvia
# Calcular frecuencia proporcional a la intensidad
frequency = int(self.min_frequency +
(intensity / 100) * (self.max_frequency - self.min_frequency))
self.buzzer.freq(frequency)
self.buzzer.duty(self.buzzer_duty)
else:
# Silenciar si no hay lluvia significativa
self.buzzer.duty(0)
return frequency if intensity > 5 else 0
def display_status(self, intensity, raw_value, num_leds, frequency):
"""
Muestra el estado actual del sistema
"""
print(f"Lluvia: {intensity:.1f}% | Sensor: {raw_value} | LEDs: {num_leds}/8 | Buzzer: {frequency}Hz")
def run(self):
"""
Bucle principal del sistema
"""
print("\n--- Iniciando monitoreo de lluvia ---")
print("Presiona Ctrl+C para detener\n")
try:
while True:
# Leer intensidad de lluvia
intensity, raw_value = self.read_rain_intensity()
# Controlar LEDs y zumbador
num_leds = self.control_leds(intensity)
frequency = self.control_buzzer(intensity)
# Mostrar estado
self.display_status(intensity, raw_value, num_leds, frequency)
# Pequeña pausa para estabilidad
time.sleep(0.5)
except KeyboardInterrupt:
print("\n--- Deteniendo sistema ---")
self.shutdown()
def shutdown(self):
"""
Apaga todos los componentes del sistema
"""
# Apagar todos los LEDs
for led in self.leds:
led.off()
# Silenciar zumbador
self.buzzer.duty(0)
self.buzzer.deinit()
print("Sistema apagado correctamente")
def test_components(self):
"""
Función de prueba para verificar que todos los componentes funcionan
"""
print("\n--- Modo de prueba ---")
# Probar LEDs secuencialmente
print("Probando LEDs...")
for i, led in enumerate(self.leds):
print(f"LED {i+1} encendido")
led.on()
time.sleep(0.3)
led.off()
# Probar zumbador con diferentes frecuencias
print("Probando zumbador...")
test_frequencies = [400, 800, 1200, 1600, 2000]
for freq in test_frequencies:
print(f"Frecuencia: {freq}Hz")
self.buzzer.freq(freq)
self.buzzer.duty(512)
time.sleep(0.5)
self.buzzer.duty(0)
print("Prueba completada")
def calibrate_sensor(self):
"""
Función para calibrar el sensor de lluvia
Ejecuta esto primero para encontrar los valores correctos
"""
print("\n=== CALIBRACIÓN DEL SENSOR DE LLUVIA ===")
print("Esta función te ayudará a encontrar los valores correctos")
print("Presiona Ctrl+C cuando tengas suficientes datos\n")
values = []
try:
print("Leyendo valores del sensor...")
print("Valor Crudo | Voltaje | Notas")
print("-" * 40)
while True:
raw_value = self.rain_sensor.read()
voltage = (raw_value / 4095) * 3.3 # Convertir a voltaje
values.append(raw_value)
print(f"{raw_value:4d} | {voltage:.2f}V | ", end="")
# Sugerencias basadas en el valor
if raw_value < 500:
print("MUY SECO")
elif raw_value < 1500:
print("Seco")
elif raw_value < 2500:
print("Poco húmedo")
elif raw_value < 3500:
print("Húmedo")
else:
print("MUY HÚMEDO")
time.sleep(1)
except KeyboardInterrupt:
if values:
min_val = min(values)
max_val = max(values)
avg_val = sum(values) / len(values)
print(f"\n=== RESULTADOS DE CALIBRACIÓN ===")
print(f"Valores observados:")
print(f" Mínimo: {min_val}")
print(f" Máximo: {max_val}")
print(f" Promedio: {avg_val:.1f}")
print(f"\n=== RECOMENDACIONES ===")
print("Basado en tus lecturas, actualiza estos valores en el código:")
print(f"self.min_rain_value = {min_val} # Sensor seco")
print(f"self.max_rain_value = {max_val} # Sensor mojado")
if min_val > max_val * 0.8:
print("\n⚠️ ADVERTENCIA: Los valores son muy similares")
print(" Verifica las conexiones del sensor")
if avg_val > 3000:
print("\n💡 SUGERENCIA: Tu sensor parece funcionar con lógica invertida")
print(" Usa la fórmula invertida en read_rain_intensity()")
print("\nCalibración terminada")
# Código principal
def main():
# Crear instancia del sistema
rain_system = RainDetectionSystem()
print("\n=== MENÚ DE OPCIONES ===")
print("1. Calibrar sensor (RECOMENDADO PRIMERO)")
print("2. Probar componentes")
print("3. Ejecutar sistema normal")
print("\nEscribe el número de opción y presiona Enter:")
try:
# En MicroPython, input() puede no estar disponible
# Por defecto, ejecutaremos la calibración
print("Ejecutando calibración automáticamente...")
rain_system.calibrate_sensor()
print("\n¿Continuar con el sistema normal? (descomenta la siguiente línea)")
# rain_system.run()
except:
# Si hay algún error, ejecutar el sistema normal
print("Ejecutando sistema con valores por defecto...")
rain_system.run()
# Ejecutar el programa
if __name__ == "__main__":
main()