from machine import Pin, PWM, ADC
import utime
import math
# --- CONFIGURACIÓN DE PINES ---
trigger = Pin(3, Pin.OUT)
echo = Pin(2, Pin.IN)
sensor_pir = Pin(15, Pin.IN) # Mantenemos el pin configurado por si tu profesor lo pide
led_rojo = Pin(14, Pin.OUT)
led_verde = Pin(13, Pin.OUT)
# Sensores Analógicos (LDR en GP26 y NTC en GP27)
ldr = ADC(26)
ntc = ADC(27)
# Configuración de Servomotores (50Hz)
servo_cortina = PWM(Pin(16))
servo_cortina.freq(50)
servo_puerta = PWM(Pin(17))
servo_puerta.freq(50)
# --- CONFIGURACIÓN DE PARÁMETROS ---
DISTANCIA_ALERTA = 300.0 # Perímetro de seguridad estricto a 300 cm
DISTANCIA_PUERTA = 50.0
LUZ_UMBRAL = 30000
# Parámetros de Climatización
TEMP_MINIMA = 15.0
TEMP_MAXIMA = 30.0
RESISTENCIA_FIJA = 10000.0
BETA = 3950.0
TEMP_REFERENCIA = 298.15
R_REFERENCIA = 10000.0
# Variable auxiliar para el parpadeo del LED Rojo
estado_led_rojo = 0
def mover_servo(servo, angulo):
duty = int(1638 + (angulo * 6554 / 180))
servo.duty_u16(duty)
def medir_distancia():
trigger.low()
utime.sleep_us(2)
trigger.high()
utime.sleep_us(10)
trigger.low()
signaloff = utime.ticks_us()
signalon = utime.ticks_us()
max_espera = utime.ticks_us() + 50000
while echo.value() == 0:
signaloff = utime.ticks_us()
if utime.ticks_us() > max_espera: return -1
while echo.value() == 1:
signalon = utime.ticks_us()
if utime.ticks_us() > max_espera: return -1
timepassed = signalon - signaloff
return round((timepassed * 0.0343) / 2, 1)
def calcular_temperatura():
valor_adc = ntc.read_u16()
if valor_adc == 0 or valor_adc == 65535: return 25.0
voltaje = (valor_adc * 3.3) / 65535.0
resistencia_ntc = RESISTENCIA_FIJA * (3.3 - voltaje) / voltaje
logaritmo = math.log(resistencia_ntc / R_REFERENCIA)
temp_k = 1.0 / (1.0 / TEMP_REFERENCIA + logaritmo / BETA)
return round(temp_k - 273.15, 1)
# Inicializar actuadores
mover_servo(servo_cortina, 0)
mover_servo(servo_puerta, 0)
# --- CICLO PRINCIPAL DE DOMÓTICA ---
while True:
distancia_actual = medir_distancia()
valor_luz = ldr.read_u16()
temperatura_actual = calcular_temperatura()
print(f"Distancia: {distancia_actual} cm | Luz LDR: {valor_luz} | Temp: {temperatura_actual}°C")
# 1. CONTROL DE CORTINAS AUTOMÁTICAS
if valor_luz < LUZ_UMBRAL:
print("☀️ Luz exterior suficiente. Cortinas abiertas (180°).")
mover_servo(servo_cortina, 180)
else:
print("🌙 Oscuridad exterior. Cortinas cerradas (0°).")
mover_servo(servo_cortina, 0)
# 2. CONTROL INTELIGENTE DE PUERTAS
if 0 < distancia_actual <= DISTANCIA_PUERTA:
print("🚪 ¡Persona detectada cerca! Abriendo puerta por acceso (90°)...")
mover_servo(servo_puerta, 90)
elif temperatura_actual >= TEMP_MAXIMA:
print(f"🥵 Temp Alta ({temperatura_actual}°C). Puerta abierta para ventilar (90°).")
mover_servo(servo_puerta, 90)
elif temperatura_actual <= TEMP_MINIMA:
print(f"🥶 Temp Baja ({temperatura_actual}°C). Puerta cerrada para aislar frío (0°).")
mover_servo(servo_puerta, 0)
else:
print(f"🏠 Temp agradable ({temperatura_actual}°C). Puerta cerrada (0°).")
mover_servo(servo_puerta, 0)
# 3. CONTROL DE SEGURIDAD CORREGIDO (Basado estrictamente en la distancia)
if 0 < distancia_actual <= DISTANCIA_ALERTA:
print(f"⚠️ ¡ALERTA CONTINUA! Presencia detectada a {distancia_actual} cm (Límite: {DISTANCIA_ALERTA} cm) ⚠️")
# El LED Verde se apaga INMEDIATAMENTE si hay alguien en el rango
led_verde.low()
# Parpadeo infinito: Cambia de estado en cada ciclo sin importar el PIR
estado_led_rojo = not estado_led_rojo
led_rojo.value(estado_led_rojo)
else:
# Si la distancia es mayor a 300 cm o hay error (-1), significa que NO detecta a nadie
print("✅ Zona segura. No se detecta presencia en el perímetro.")
# El LED Verde se enciende estrictamente al no detectar a nadie
led_verde.high()
led_rojo.low() # Apaga el LED Rojo al instante
print("------------------------------------------------------------")
utime.sleep(0.4) # Velocidad del parpadeo fluida