# INICIO DE CODIGO FUENTE
#..............................................................
#Proyecto integración de etapa II y etapa III
#A continuación se detalla un programa utilizando MicroPython...
#...cuyo objetivo es mover de manera intermitente el “servo” cuando se supera un umbral de temperatura ambiente,
#...y deja de moverse cuando la temperatura desciende
#..............................................................
#Se importan los siguientes módulos:
import network #Este comando importa la librería de MicroPython titulada "network" la cual está disponible en: https://docs.micropython.org/en/latest/library/network.html
import time #Este comando importa la librería de MicroPython titulada "time" la cual está disponible en: https://docs.micropython.org/en/latest/library/time.html
from machine import Pin, PWM #Este comando importa las clases "Pin" y "PWM" desde el módulo "machine"
#Un objeto "pin", asociado a un pin físico, permite controlar el envío de voltajes de salida y la lectura de voltajes de entrada
#Un objeto "PWM" permite generar señales PWM (Modulación por Ancho de Pulso) en las cuales se puede modificar el ciclo de trabajo (Duty Cycle)
import dht #Este comando importa la libreria de MicroPhyton titulada "DHT" (Digital Humidity & Temperature). Permite interactuar con el sensor DHT22 en la simulación
import ujson #Este comando importa la libreria de MicroPhyton titulada "ujson". Permite hacer conversiones entre objetos MicroPhyton y el formato de datos JSON
from umqtt.simple import MQTTClient #Este comando importa la clase "MQTTClient" desde la libreria "umqtt.simple". Permite usar y conectar un cliente con un servidor MQTT. MQTT es un protocolo de mensajeria ligero.
from utime import sleep, sleep_us #Este comando importa las clases "sleep" y "sleep_us" desde el módulo "utime".
#La funcion "sleep" permite suspender o detener un programa durante una cantidad determinada de segundos
#La funcion "sleep_us" permite suspender o detener un programa durante una cantidad determinada de microsegundos
# MQTT Server Parameters
#A continuación se establecen variables que servirán como parámetros de input de la clase MQTTClient
MQTT_CLIENT_ID = "micropython-weather-demo" #Este comando sirve como identificador de cliente MQTT
MQTT_BROKER = "broker.mqttdashboard.com" #Este comando sirve para indicar que el cliente se conectará al servidor en linea broker.mqttdashboard.com
MQTT_USER = "" #Este comando establece la variable asignada al nombre de usuario como vacía
MQTT_PASSWORD = "" #Este comando establece la variable asignada a la contraseña como vacía
MQTT_TOPIC = "wokwi-weather" #Este comando hace referencia al tema (topic) al cual el cliente MQTT se sucribirá, en este caso al referente al clima
#Configurando PIN 15 para el DHTT22
sensor = dht.DHT22(Pin(15)) #Este comando indica que el sensor DHT22 está conectado al pin 15 del ESP32
#Configurando PIN 18 para el Servomotor
servo = PWM(Pin(18), freq = 50) #La frecuencia 50 equivale a 20 ms. En este caso no ponemos la referencia a DUTY ya que ste valor cambiará en el tiempo
#Conectando DHTT22 a la red
print("Conectando WiFi", end="") #Este comando muestra la frase "Connecting to Wifi" al iniciarse el programa. La referencia end="" cambia el final de salto línea, por un vacío que resulta en que el siguiente comando print imprimirá en la misma linea
sta_if = network.WLAN(network.STA_IF) #Este comando crea un objeto llamado sta_if (interfaz de estación) el cual es configurado en modo cliente a través de la libreria network y la clase "WLAN"
sta_if.active(True) #Este comando activa la interfaz de estación
sta_if.connect('Wokwi-GUEST', '') #Este comando conecta la interfaz de estacion a una red WiFi llamda "Wokwi-GUEST". El espacio vacío en el segundo argumento indica que no se proporcionará contraseña para la red WiFi
while not sta_if.isconnected(): #Este comando inicia un bucle condicional que se ejecutará mientras el estado de la conexión sea "false", es decir, mientras la interface de estación esté desconectada de la red
print(".", end="") #Este comando muestra un punto mientras no se logre la conexión, lo que se verá como una línea continua de puntos
time.sleep(0.1) #Este comando establece una pausa de 0.1 segundos antes de terminar el bucle actual
print("Conectado a Wifi!") #Este comando se ejecutará cuando el condicional sea "true", es decir, cuando la interfaz de estación se conecte a la red y mostrará la frase entre comillas
print("Conectando a server MQTT ... ", end="") #Este comando mostrará el mensaje entre comillas, para indicar que se intenta conectar al servidor MQTT
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, user=MQTT_USER, password=MQTT_PASSWORD) #Este comando crea el objeto llamado "client" en base a la clase MQTTClient, ingresando los parametros identificador de cliente, dirección de broker, cuenta de usuario y contraseña, establecidos previamente
client.connect() #Este comando establece la conexión del cliente al servidor MQTT
print("Conectado a MQTT!") #Este comando mostrará la frase entre comillas
#La OMS indica que la temperatura ambiente óptima para el ser humano se encuentra entre 16 y 24 grados centigrados
umbral_temperatura_ambiente = 24.0 #Este comando asigna el valor de la temperatura ambiente normal a una variable para su uso y comparación
prev_weather = "" #Este comando establece una variable vacia. Será usada para almacenar el estado previo de las condiciones climatológicas y para poder realizar una comparación posterior
temperatura_actual = "" #Este comando establece una variable vacia. Será usada para almacenar el estado actual de la temperatura
temperatura_bajo_umbral=""
while True: #Este comando inicia un bucle infinito, dado que el estado TRUE no cambiará. Para concluir el bucle la aplicación debe ser interrumpida manualmente
print("Midiendo condiciones del clima... ", end="") #Este comando muestra el mensaje entre comillas, para indicar que se están midiendo las condiciones climatológicas
sensor.measure() #Este comando llama al método measure (medición) del objeto llamado sensor
temperatura_actual = sensor.temperature() #Este comando asigna el valor actual de temperatura actual a la variable para su uso
message = ujson.dumps({ #Este comando crea un diccionario "message" en una cadena de datos en formato JSON
"temp": sensor.temperature(), #Este comando incluye la palabra "temp" asignándole el valor medido de la temperatura
"humidity": sensor.humidity(), #Este comando incluye la palabra "humidity" asignándole el valor medido de la humedad
})
if message != prev_weather: #Este comando compara el mensaje actual con el estado previo. Si son diferentes se ejecutarán los siguientes comandos
print("Actualizado!") #Este comando muestra la palabra "Actualizado!", indicando que hubiero cambios
print("Reportando a MQTT topic {}: {}".format(MQTT_TOPIC, message)) #Este comando muestra los nuevos valores de temperatura y humedad
client.publish(MQTT_TOPIC, message) #Este comando publica el mensaje en el servidor MQTT en el tema especificado MQTT_TOPIC
prev_weather = message #Este comando actualiza la variable de estado previo con el estado actual
if temperatura_actual > umbral_temperatura_ambiente: #Este comando inicia un bucle infinito, dado que el estado TRUE no cambiará. Para concluir el bucle la aplicación debe ser interrumpida manualmente
print("Temperatura encima del umbral...moviendo el servomotor") #Este comando muestra la frase entre comillas, indicando que la temperatura ha rebasado el umbral
while sensor.temperature()>umbral_temperatura_ambiente: #Este comando inicia un bucle que durará mientras la temperatura siendo sensada este por encima del umbral
#duty_u16, permite asignar un entero de 16 bits sin signo (0 a 65536). Para ESP32 el rango hasta 180 grados correspondera a los valores 1800 a 8000
for i in range (1800, 8000): #Este comando permitirá que el servomotor gire completamente dentro de un rango de 180°, para este caso, en sentido horario
servo.duty_u16(i) #El comando hará que el brazo del servomotor de un "paso" dentro del rango, en sentido horario
sleep_us(1) #El comando permite detener el programa por 1 microsegundo
sleep(1) #El comando permite detener el programa por 1 segundo, con el fin de que se vea claramente el movimiento más bajo dentro del ángulo de 180°
for i in range (8000, 1800, -1): #Este comando permitirá que el servomotor gire completamente dentro de un rango de 180°, para este caso, en sentido antihorario
servo.duty_u16(i) #El comando hará que el brazo del servomotor de un "paso" dentro del rango, en sentido antihorario
sleep_us(1) #El comando permite detener el programa por 1 microsegundo
sleep(1) #El comando permite detener el programa por 1 segundo, con el fin de que se vea claramente el movimiento más alto dentro del ángulo de 180°
sensor.measure() #Este comando llama al método measure (medición) del objeto llamado sensor
temperatura_actual = sensor.temperature() #Este comando asigna el valor actual de temperatura actual a la variable para su uso
temperatura_bajo_umbral="si"
else:
if temperatura_bajo_umbral=="si":
print("Temperatura debajo del umbral...deteniendo el servomotor")
temperatura_bajo_umbral="no"
time.sleep(1) #Este comando pausa la aplicación por 1 segundo antes volver al inicio del bucle.
else: #Este comando se ejecuta cuando no se cumplió la condición de comparación, es decir, cuando no hubieron cambios en las condiciones climatológicas
print("No change") #Este comando muestra el mensaje "No change", indicando que no hubieron cambios
time.sleep(1) #Este comando pausa la aplicación por 1 segundo antes volver al inicio del bucle.
#manejo de excepciones
#except OSError as e:
# print("Error en la medición:", e)
# # Manejar el error ECONNRESET reconectando el cliente MQTT
# try:
# client.connect()
# print("Reconectado al servidor MQTT.")
# except OSError as reconnect_error:
# print("Error al reconectar al servidor MQTT:", reconnect_error)
# time.sleep(2) # Esperar antes de intentar nuevamente
# continue