from machine import Pin, ADC, PWM
import dht
import time
import math
import network
from umqtt.simple import MQTTClient
import ujson
#Participantes:
#Bianca Duarte Bernardo
#Ellen Alves Inacio
#Guilherme Marins Rodrigues
#João Vitor Fernandes D Araujo
#config wifi e mqtt
WIFI_SSID = "Wokwi-GUEST"
WIFI_SENHA = ""
MQTT_CLIENT_ID = "esp32-estufa-alface-grupo"
MQTT_BROKER = "broker.hivemq.com"
MQTT_TOPIC_PUB = b"estufa/alface/sensores"
MQTT_TOPIC_SUB = b"estufa/alface/comandos"
dht1 = dht.DHT22(Pin(16))
dht2 = dht.DHT22(Pin(4))
ldr1 = ADC(Pin(32))
ldr2 = ADC(Pin(33))
#atenuacao pra ler a tensao completa do esp32 (ate 3.3v)
ldr1.atten(ADC.ATTN_11DB)
ldr2.atten(ADC.ATTN_11DB)
GAMMA = 0.7
RL10 = 50
#configurando o pino do servo da escotilha com freq de 50hz
servo_escotilha = PWM(Pin(18), freq=50)
#funcao para converter o angulo (0 a 180) pro duty q o motor entende
def mover_servo(angulo):
min_duty = 40
max_duty = 115
duty = int(min_duty + (angulo / 180.0) * (max_duty - min_duty))
servo_escotilha.duty(duty)
#ja comeca com a escotilha fechada
mover_servo(0)
botao = Pin(17, Pin.IN, Pin.PULL_UP)
escotilha_aberta = False
ultimo_clique = 0
ventilador1 = Pin(19, Pin.OUT)
ventilador2 = Pin(21, Pin.OUT)
borrifador1 = Pin(25, Pin.OUT)
borrifador2 = Pin(26, Pin.OUT)
#garante q eles comecam desligados
ventilador1.value(0)
ventilador2.value(0)
borrifador1.value(0)
borrifador2.value(0)
def alternar_escotilha(pin):
global escotilha_aberta, ultimo_clique
#debounce maroto pra nao ler clique repetido rapido demais
if time.ticks_diff(time.ticks_ms(), ultimo_clique) > 300:
escotilha_aberta = not escotilha_aberta
if escotilha_aberta:
mover_servo(180)
print("\n Escotilha ABERTA\n")
else:
mover_servo(0)
print("\n Escotilha FECHADA\n")
ultimo_clique = time.ticks_ms()
#cria a interrupcao no botao
botao.irq(trigger=Pin.IRQ_FALLING, handler=alternar_escotilha)
def read_lux(ldr):
valor_lux = ldr.read()
voltage = (valor_lux / 4095.0) * 3.3
if voltage >= 3.29:
voltage = 3.29
if voltage <= 0:
voltage = 0.001
resistance = 10000 * voltage / (3.3 - voltage)
lux = math.trunc(math.pow(RL10 * 1e3 * math.pow(10, GAMMA) / resistance, (1 / GAMMA)))
return round(lux)
#conexao wifi
print("Iniciando tentativa de conexao com Wi-Fi...")
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect(WIFI_SSID, WIFI_SENHA)
while not sta_if.isconnected():
print("Conectando...")
time.sleep(1)
print("Wi-Fi Conectado com sucesso!")
#funcao que recebe os comandos do red
def mqtt_callback(topic, msg):
global escotilha_aberta
print(f"\n[MQTT] Comando recebido: {msg} no tópico {topic}")
if msg == b"ABRIR_ESCOTILHA" and not escotilha_aberta:
escotilha_aberta = True
mover_servo(180)
print("Escotilha ABERTA via Node-RED")
elif msg == b"FECHAR_ESCOTILHA" and escotilha_aberta:
escotilha_aberta = False
mover_servo(0)
print("Escotilha FECHADA via Node-RED")
#conexao mqtt
print("Conectando ao Broker MQTT...", end="")
try:
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER)
client.set_callback(mqtt_callback)
client.connect()
client.subscribe(MQTT_TOPIC_SUB)
print(" Conectado!")
except Exception as e:
print("Erro ao conectar no MQTT:", e)
while True:
#lendo os sensores com try/except pra nao crachar o codigo
try:
dht1.measure()
temp1 = dht1.temperature()
umi1 = dht1.humidity()
except:
temp1 = -1
umi1 = -1
try:
dht2.measure()
temp2 = dht2.temperature()
umi2 = dht2.humidity()
except:
temp2 = -1
umi2 = -1
lux1 = read_lux(ldr1)
lux2 = read_lux(ldr2)
#se a temp bater 26 graus ou mais ele liga o pino, senao ele desliga
if temp1 >= 26:
ventilador1.value(1)
elif temp1 != -1:
ventilador1.value(0)
if temp2 >= 26:
ventilador2.value(1)
elif temp2 != -1:
ventilador2.value(0)
#liga a agua se a umidade cair pra 69% ou menos
if umi1 <= 69 and umi1 != -1:
borrifador1.value(1)
elif umi1 != -1:
borrifador1.value(0)
if umi2 <= 69 and umi2 != -1:
borrifador2.value(1)
elif umi2 != -1:
borrifador2.value(0)
#se algum dos dois sensores bater 86%, força a abertura pra ventilar
if (umi1 >= 86 or umi2 >= 86) and not escotilha_aberta:
escotilha_aberta = True
mover_servo(180)
print("\n Umidade critica: Escotilha ABERTA automaticamente\n")
status_v1 = "Ligado" if ventilador1.value() == 1 else "Desligado"
status_v2 = "Ligado" if ventilador2.value() == 1 else "Desligado"
status_b1 = "Ligado" if borrifador1.value() == 1 else "Desligado"
status_b2 = "Ligado" if borrifador2.value() == 1 else "Desligado"
print(" Estufa de Alface Status:")
print(f" Area 1 | Temp: {temp1}C | Umi: {umi1}% | Lux: {lux2} | Vent: {status_v1} | Borrifador: {status_b1}")
print(f" Area 2 | Temp: {temp2}C | Umi: {umi2}% | Lux: {lux1} | Vent: {status_v2} | Borrifador: {status_b2}")
print("-" * 85)
#checa se tem novas mensg do node
try:
client.check_msg()
except:
pass
#preparando em json
dados_sensores = {
"temperatura1": temp1,
"umidade1": umi1,
"lux1": lux1,
"temperatura2": temp2,
"umidade2": umi2,
"lux2": lux2,
"status_escotilha": "Aberta" if escotilha_aberta else "Fechada",
"ventilador1": ventilador1.value(),
"borrifador1": borrifador1.value()
}
#puplica os dados do hivemq
try:
mensagem = ujson.dumps(dados_sensores)
client.publish(MQTT_TOPIC_PUB, mensagem.encode())
print(" Dados enviados para a Dashboard")
except Exception as e:
print(" Falha ao enviar dados:", e)
time.sleep(1)