from machine import Pin, ADC, I2C
import dht
import time
from ssd1306 import SSD1306_I2C
import math
import random
import sys
import select
# Configuración de la pantalla OLED
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
oled = SSD1306_I2C(128, 64, i2c)
# Configurar sensores
ldr = ADC(Pin(34))
ldr.atten(ADC.ATTN_11DB)
# DHT22 en GPIO 4
try:
dht_sensor = dht.DHT22(Pin(4))
sensor_disponible = True
print("✓ Sensor DHT22 detectado")
except:
sensor_disponible = False
print("✗ Sensor DHT22 no disponible - usando datos simulados")
# LED integrado
led = Pin(2, Pin.OUT)
# Variables para temporización
ultima_lectura_dht = 0
INTERVALO_DHT = 2000 # 2 segundos
# Variables para gráfica de temperatura
historial_temp = [20] * 80 # Iniciar con 20°C en lugar de ceros
pos_actual = 79
ultimas_temperaturas = []
# Variables de estado
pantalla_actual = 0
NOMBRES_PANTALLAS = ["LUZ", "TEMP", "HUMEDAD", "IDENTIDAD"]
# Variables de sensores
valor_luz = 0
temperatura = 25
humedad = 50
# Contador de fallos del sensor
fallos_consecutivos = 0
MODO_SIMULACION = False
# ============================================
# FUNCIONES DE UTILERÍA
# ============================================
def calcular_porcentaje_luz(valor_adc):
porcentaje = (valor_adc / 4095) * 100
return max(0, min(100, porcentaje))
def generar_temperatura_simulada():
global ultimas_temperaturas
tiempo = time.ticks_ms() / 10000
temp_base = 25 + 5 * math.sin(tiempo)
ruido = random.uniform(-0.5, 0.5)
temp = temp_base + ruido
ultimas_temperaturas.append(temp)
if len(ultimas_temperaturas) > 5:
ultimas_temperaturas.pop(0)
return sum(ultimas_temperaturas) / len(ultimas_temperaturas)
def generar_humedad_simulada():
tiempo = time.ticks_ms() / 15000
return 55 + 15 * math.sin(tiempo + 2)
def leer_dht22():
global temperatura, humedad, fallos_consecutivos, MODO_SIMULACION
if MODO_SIMULACION or not sensor_disponible:
temperatura = generar_temperatura_simulada()
humedad = generar_humedad_simulada()
return True
try:
dht_sensor.measure()
temp = dht_sensor.temperature()
hum = dht_sensor.humidity()
if temp is not None and hum is not None:
temperatura = temp
humedad = hum
fallos_consecutivos = 0
return True
else:
fallos_consecutivos += 1
return False
except Exception as e:
fallos_consecutivos += 1
if fallos_consecutivos > 5:
MODO_SIMULACION = True
print("⚠ Cambiando a MODO SIMULACIÓN")
return False
# ============================================
# FUNCIONES DE DIBUJADO
# ============================================
def dibujar_temperatura():
global historial_temp
oled.fill(0)
oled.text("TEMPERATURA", 0, 0)
oled.text("{:.1f}C".format(temperatura), 80, 0)
ancho_grafica = 120
alto_grafica = 40
x_inicio = 4
y_base = 50
oled.hline(x_inicio, y_base, ancho_grafica, 1)
oled.hline(x_inicio, y_base - alto_grafica, ancho_grafica, 1)
for i in range(1, 4):
y_ref = y_base - int((alto_grafica / 4) * i)
oled.hline(x_inicio, y_ref, ancho_grafica, 0)
historial_temp.pop(0)
historial_temp.append(temperatura)
min_temp = 15
max_temp = 35
rango_temp = max_temp - min_temp
puntos_dibujados = []
for i in range(len(historial_temp)):
temp_val = historial_temp[i]
proporcion = (temp_val - min_temp) / rango_temp
proporcion = max(0, min(1, proporcion))
y = int(y_base - (proporcion * alto_grafica))
x = x_inicio + int((i / len(historial_temp)) * ancho_grafica)
puntos_dibujados.append((x, y))
oled.pixel(x, y, 1)
oled.pixel(x+1, y, 1)
oled.pixel(x, y+1, 1)
for i in range(len(puntos_dibujados) - 1):
x1, y1 = puntos_dibujados[i]
x2, y2 = puntos_dibujados[i+1]
oled.line(x1, y1, x2, y2, 1)
if MODO_SIMULACION or not sensor_disponible:
oled.text("SIM", 110, 55)
oled.show()
def dibujar_luz(porcentaje):
oled.fill(0)
oled.text("LUZ", 0, 0)
oled.text("{:.0f}%".format(porcentaje), 90, 0)
ancho_maximo = 100
alto_barra = 30
x_inicio = 14
y_inicio = 20
oled.rect(x_inicio, y_inicio, ancho_maximo, alto_barra, 1)
relleno = int((porcentaje / 100) * ancho_maximo)
oled.fill_rect(x_inicio, y_inicio, relleno, alto_barra, 1)
if porcentaje > 50:
oled.rect(110, 45, 8, 8, 1)
oled.line(114, 40, 114, 43, 1)
oled.line(114, 55, 114, 58, 1)
oled.line(107, 49, 110, 49, 1)
oled.line(117, 49, 120, 49, 1)
else:
oled.ellipse(114, 49, 4, 4, 1)
oled.fill_rect(112, 47, 4, 4, 0)
oled.show()
def dibujar_humedad():
oled.fill(0)
oled.text("HUMEDAD", 0, 0)
oled.text("{:.0f}%".format(humedad), 90, 0)
centro_x = 64
centro_y = 35
radio = 25
for angulo in range(0, 181, 2):
rad = math.radians(angulo)
x = int(centro_x + radio * math.cos(rad))
y = int(centro_y - radio * math.sin(rad))
oled.pixel(x, y, 1)
for ang, texto in [(0, "0"), (90, "50"), (180, "100")]:
rad = math.radians(ang)
x = int(centro_x + (radio + 5) * math.cos(rad))
y = int(centro_y - (radio + 5) * math.sin(rad))
oled.text(texto, x-5, y-3)
angulo_aguja = int((humedad / 100) * 180)
rad_aguja = math.radians(angulo_aguja)
x_aguja = int(centro_x + (radio - 5) * math.cos(rad_aguja))
y_aguja = int(centro_y - (radio - 5) * math.sin(rad_aguja))
oled.line(centro_x, centro_y, x_aguja, y_aguja, 1)
ancho_barra = 100
alto_barra = 8
x_barra = 14
y_barra = 55
oled.rect(x_barra, y_barra, ancho_barra, alto_barra, 1)
relleno = int((humedad / 100) * ancho_barra)
oled.fill_rect(x_barra, y_barra, relleno, alto_barra, 1)
oled.show()
def dibujar_identidad():
oled.fill(0)
oled.rect(0, 0, 127, 63, 1)
oled.rect(2, 2, 123, 59, 1)
oled.text("TECNOLOGICO", 20, 10)
oled.text("NACIONAL", 30, 20)
oled.text("DE MEXICO", 25, 30)
oled.hline(20, 40, 88, 1)
# Datos actualizadoS
oled.text("Alfredo Mata", 14, 45)
oled.text("Isrel sotelo", 14, 55)
oled.show()
# ============================================
# PROGRAMA PRINCIPAL
# ============================================
def main():
global ultima_lectura_dht, pantalla_actual
global valor_luz, temperatura, humedad
print("\n" + "="*40)
print("SISTEMA DE MONITOREO AMBIENTAL")
print("="*40)
print("MENU DE CONTROL:")
print("Escribe un numero en la consola y presiona Enter:")
print("[1] -> Gráfica de Luz")
print("[2] -> Gráfica de Temperatura")
print("[3] -> Medidor de Humedad")
print("[4] -> Pantalla de Identidad")
print("="*40 + "\n")
while True:
tiempo_actual = time.ticks_ms()
# Leer LDR
valor_luz = ldr.read()
# Leer DHT cada 2 segundos sin bloquear
if time.ticks_diff(tiempo_actual, ultima_lectura_dht) >= INTERVALO_DHT:
leer_dht22()
ultima_lectura_dht = tiempo_actual
# Revisar si se escribió algo en la consola (menú no bloqueante)
if select.select([sys.stdin], [], [], 0)[0]:
tecla = sys.stdin.read(1)
if tecla == '1':
pantalla_actual = 0
print(">> Cambiando a: LUZ")
elif tecla == '2':
pantalla_actual = 1
print(">> Cambiando a: TEMPERATURA")
elif tecla == '3':
pantalla_actual = 2
print(">> Cambiando a: HUMEDAD")
elif tecla == '4':
pantalla_actual = 3
print(">> Cambiando a: IDENTIDAD")
# Mostrar la pantalla seleccionada
try:
if pantalla_actual == 0:
porcentaje_luz = calcular_porcentaje_luz(valor_luz)
dibujar_luz(porcentaje_luz)
elif pantalla_actual == 1:
dibujar_temperatura()
elif pantalla_actual == 2:
dibujar_humedad()
elif pantalla_actual == 3:
dibujar_identidad()
except Exception as e:
oled.fill(0)
oled.text("ERROR", 40, 30)
oled.show()
time.sleep_ms(50)
if __name__ == "__main__":
main()