##*****************************************************************************************************
# DESCRIPCIÓN: Realiza lo siguiente:
# - Se imprime un menú principal en una pantalla OLED en el cual podemos elegir entre dos opciones
# LEDs y Entradas.
# - Al seleccionar LEDs se imprime un submenú en el cual podemos cambiar el estado de tres leds
# y una opción de salida para regresar al menú principal.
# - Al seleecionar Entradas se imprime un submenú en el cual podemos ver el estado de dos
# potenciometros que simulan ser un sensor de humedad y temperatura. Al igual que el submenú de LEDs
# hay una opción de salida para regresar al menú principal.
# - Para la selección se usa un encodificador rotativo y un buzzer que produce un sonido corto cada
# vez que se presiona el push button del encodificador.
# ENTRADAS:
# Encodificador Rotativo: Con este componente controlamos la selección de opciones en los menus.
# Potenciometro 1: Simula ser un sensor de temperatura.
# Potenciometro 2: Simula ser un sensor de humedad.
# SALIDAS:
# Pantalla OLED: Aquí podemos visualizar los menus así como los cambios que haya en las entradas
# y salidas.
# LED1: LED cuyo estado podemos controlar desde el submenu "LEDs".
# LED2: LED cuyo estado podemos controlar desde el submenu "LEDs".
# LED3: LED cuyo estado podemos controlar desde el submenu "LEDs".
# Buzzer: Este componente nos indicará cuando presionemos el push button del encodificador para saber
# cuando estamos haciendo una selección.
#
#******************************************************************************************************
#--------------------------------------------------
# Importación de Librerías |
#--------------------------------------------------
from machine import Pin, I2C, ADC, disable_irq, enable_irq
from ssd1306 import SSD1306_I2C
import time
#--------------------------------------------------
# Datos y Variables |
#--------------------------------------------------
i2c = I2C(0, scl=Pin(36), sda=Pin(37))
oled_width = 128
oled_height = 64
oled = SSD1306_I2C(oled_width, oled_height, i2c)
buzzer = Pin(4, Pin.OUT)
led1 = Pin(10, Pin.OUT)
led2 = Pin(9, Pin.OUT)
led3 = Pin(3, Pin.OUT)
leds = [led1, led2, led3]
estados_leds = [False, False, False]
pot1 = ADC(Pin(8))
pot2 = ADC(Pin(18))
contador = 1
seleccion_actual = 1
sw_presionado = False
ultimo_tiempo_presion = 0
estado_menu = "principal" # "principal", "leds", "entradas"
#--------------------------------------------------
# Funciones |
#--------------------------------------------------
def encodificador_handler(pin):
# Manejador de interrupción para el giro del encodificador
global contador
time.sleep_us(100)
dt_val = Pin(13).value()
clk_val = Pin(12).value()
if clk_val == 0:
if dt_val == 0:
# Giro en sentido anti-horario
contador -= 1
else:
# Giro en sentido horario
contador += 1
def sw_handler(pin):
# Manejador de interrupción para el pulsador del encodificador
global sw_presionado, ultimo_tiempo_presion
tiempo_actual = time.ticks_ms()
if time.ticks_diff(tiempo_actual, ultimo_tiempo_presion) > 200: # 200ms de debounce
sw_presionado = True
ultimo_tiempo_presion = tiempo_actual
buzzer.on()
time.sleep_ms(100)
buzzer.off()
def setup():
# Encodificador Rotativo
pin_DT = Pin(13, Pin.IN)
pin_CLK = Pin(12, Pin.IN)
pin_SW = Pin(11, Pin.IN, Pin.PULL_UP)
# Configurar interrupciones
pin_CLK.irq(trigger=Pin.IRQ_FALLING, handler=encodificador_handler)
pin_SW.irq(trigger=Pin.IRQ_FALLING, handler=sw_handler)
# Apagar LEDs y buzzer al inicio
for led in leds:
led.value(0)
buzzer.value(0)
def dibujar_menu_principal():
oled.fill(0)
oled.text("Menu Principal", 0, 0)
oled.text("1.- LEDs", 0, 20)
oled.text("2.- Entradas", 0, 40)
if seleccion_actual == 1:
oled.text(" <", 90, 20)
elif seleccion_actual == 2:
oled.text(" <", 90, 40)
oled.show()
def dibujar_menu_leds():
oled.fill(0)
oled.text("Menu LEDs", 0, 0)
for i, state in enumerate(estados_leds):
status_text = "ON" if state else "OFF"
oled.text(f"LED{i+1}: {status_text}", 0, 15 + (i * 12))
oled.text("SALIR", 0, 15 + (len(leds) * 12))
if seleccion_actual <= len(leds):
oled.text(" <", 100, 15 + ((seleccion_actual - 1) * 12))
else:
oled.text(" <", 100, 15 + (len(leds) * 12))
oled.show()
def dibujar_menu_entradas():
oled.fill(0)
oled.text("Menu Entradas", 0, 0)
temp_val = pot1.read()
hum_val = pot2.read()
temperatura = (temp_val / 4095) * 100
humedad = (hum_val / 4095) * 100
oled.text(f"Temp: {temperatura:.1f}C", 0, 20)
oled.text(f"Humedad: {humedad:.1f}%", 0, 40)
oled.text("Salir", 0, 55)
oled.text(" <", 90, 55)
oled.show()
def actualizar_leds():
# Actualiza el estado físico de los LEDs según la lista estados:_leds
for i, state in enumerate(estados_leds):
leds[i].value(state)
#--------------------------------------------------
# Cuerpo Principal |
#--------------------------------------------------
setup()
dibujar_menu_principal()
while True:
if estado_menu == "principal":
# Limitar el contador al rango de opciones (1 y 2)
if contador < 1: contador = 2
if contador > 2: contador = 1
if seleccion_actual != contador:
seleccion_actual = contador
dibujar_menu_principal()
if sw_presionado:
sw_presionado = False
if seleccion_actual == 1:
estado_menu = "leds"
contador = 0 # Reiniciar contador para el nuevo menú
elif seleccion_actual == 2:
estado_menu = "entradas"
contador = 0
seleccion_actual = 1
elif estado_menu == "leds":
# Limitar contador a 4 opciones (3 LEDs + Salir)
if contador < 1: contador = 4
if contador > 4: contador = 1
if seleccion_actual != contador:
seleccion_actual = contador
dibujar_menu_leds()
if sw_presionado:
sw_presionado = False
if seleccion_actual <= len(leds):
# Cambiar estado del LED
led_index = seleccion_actual - 1
estados_leds[led_index] = not estados_leds[led_index]
actualizar_leds()
dibujar_menu_leds() # Redibujar para mostrar el nuevo estado
else: # Opción "SALIR"
estado_menu = "principal"
contador = 1
seleccion_actual = 1
elif estado_menu == "entradas":
dibujar_menu_entradas()
if sw_presionado:
sw_presionado = False
estado_menu = "principal"
contador = 1
seleccion_actual = 1
time.sleep_ms(50)