from machine import I2C, Pin, ADC, PWM # Permite usar I2C, pines digitales, ADC y PWM
from pico_i2c_lcd import I2cLcd # Libreria para manejar la pantalla LCD I2C
from time import sleep # Pausa de tiempo entre mediciones
# ------------------ FUNCION PARA RELLENAR TEXTO A 16 CARACTERES ------------------
def rellenar_16(texto): # Ajusta el texto para que ocupe exactamente 16 caracteres
s = str(texto) # Se asegura de que sea una cadena
if len(s) < 16: # Si es mas corta que 16
s = s + " " * (16 - len(s)) # Agrega espacios al final
return s[:16] # Devuelve solo los primeros 16 caracteres
# ------------------ CONFIGURACION I2C Y LCD ------------------
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000) # Crea el bus I2C0 en GP0 (SDA) y GP1 (SCL)
i2c_addr = i2c.scan()[0] # Escanea el bus y toma la direccion del LCD
lcd = I2cLcd(i2c, i2c_addr, 2, 16) # Inicializa la LCD de 2 filas x 16 columnas
lcd.clear() # Limpia la pantalla al inicio
lcd.putstr("Sistema de gases") # Muestra un mensaje de bienvenida
sleep(2) # Mantiene el mensaje 2 segundos
lcd.clear() # Limpia la pantalla para comenzar a usarla
# ------------------ SENSORES MQ (ENTRADAS ADC) ------------------
mq2 = ADC(27) # MQ-2 real en GP27 (ADC1)
mq135 = ADC(26) # Segundo MQ-2 simulando MQ-135 en GP26 (ADC0)
# ------------------ LEDS DE ESTADO ------------------
led_verde = Pin(20, Pin.OUT) # LED verde (estado SEGURO) en GP20
led_amarillo = Pin(21, Pin.OUT) # LED amarillo (estado ALERTA) en GP21
led_rojo = Pin(22, Pin.OUT) # LED rojo (estado PELIGRO) en GP22
# ------------------ BUZZER ------------------
buzzer = PWM(Pin(16)) # Buzzer en GP16 controlado por PWM
buzzer.duty_u16(0) # Deja el buzzer apagado al inicio
# ------------------ FUNCIONES AUXILIARES ------------------
def leer_sensor(adc_obj): # Funcion para leer y escalar un sensor MQ
valor_16bits = adc_obj.read_u16() # Lee el ADC en rango 0–65535
valor_10bits = valor_16bits // 64 # Escala a un rango aproximado 0–1023
return valor_10bits # Retorna el valor escalado
def encender_buzzer(): # Enciende el buzzer en modo alarma
buzzer.freq(250) # Fija la frecuencia del tono en 250 Hz
buzzer.duty_u16(32768) # Duty ~50% para que suene
def apagar_buzzer(): # Apaga el buzzer
buzzer.duty_u16(0) # Duty en 0 = sin sonido
# ------------------ BUCLE PRINCIPAL ------------------
while True: # Bucle infinito de monitoreo
valor_mq2 = leer_sensor(mq2) # Lee el valor del MQ-2 real
valor_mq135 = leer_sensor(mq135) # Lee el valor del MQ-135 simulado
# --- Determinar estado del ambiente segun umbrales ---
if valor_mq2 >= 600 or valor_mq135 >= 600: # Si alguno de los sensores es >= 600
estado = "PELIGRO" # Estado de peligro
elif valor_mq2 > 300 or valor_mq135 > 300: # Si alguno supera 300
estado = "ALERTA" # Estado de alerta
else: # En cualquier otro caso
estado = "SEGURO" # Estado seguro
# Variable para registrar si el buzzer esta encendido o apagado
buzzer_estado = "OFF" # Por defecto se considera apagado
# --- Actualizar LEDs y buzzer ---
if estado == "PELIGRO": # Si el estado es peligro
led_verde.value(0) # Apaga LED verde
led_amarillo.value(0) # Apaga LED amarillo
led_rojo.value(1) # Enciende LED rojo
encender_buzzer() # Activa buzzer
buzzer_estado = "ON" # Registra que el buzzer esta encendido
elif estado == "ALERTA": # Si el estado es alerta
led_verde.value(0) # Apaga LED verde
led_amarillo.value(1) # Enciende LED amarillo
led_rojo.value(0) # Apaga LED rojo
encender_buzzer() # Buzzer tambien encendido en alerta
buzzer_estado = "ON" # Registra buzzer encendido
else: # Si el estado es seguro
led_verde.value(1) # Enciende LED verde
led_amarillo.value(0) # Apaga LED amarillo
led_rojo.value(0) # Apaga LED rojo
apagar_buzzer() # Buzzer apagado en seguro
buzzer_estado = "OFF" # Registra buzzer apagado
# --- Actualizar texto en la LCD ---
linea1 = "M2:{:3d} M135:{:3d}".format(valor_mq2, valor_mq135) # Lecturas sensores
lcd.move_to(0, 0) # Cursor a fila 0, columna 0
lcd.putstr(rellenar_16(linea1)) # Escribe la linea ajustada a 16 caracteres
linea2 = "Est:" + estado + " BZ:" + buzzer_estado # Muestra estado y buzzer ON/OFF
lcd.move_to(0, 1) # Cursor a fila 1, columna 0
lcd.putstr(rellenar_16(linea2)) # Escribe la linea ajustada a 16 caracteres
# --- Enviar datos al monitor serial ---
print("MQ2:", valor_mq2, # Imprime lectura del MQ-2
"| MQ135(sim):", valor_mq135, # Imprime lectura del MQ-135 simulado
"| Estado:", estado, # Imprime estado calculado
"| Buzzer:", buzzer_estado) # Indica si el buzzer esta ON u OFF
sleep(1) # Espera 1 segundo antes de repetir