from machine import Pin, ADC, PWM
import dht
import time
import ujson
from umqtt.simple import MQTTClient
import network
# =============================================================================
# CONFIGURAÇÕES DE REDE E BROKER MQTT
# =============================================================================
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASS = ""
MQTT_BROKER = "broker.hivemq.com"
MQTT_CLIENT_ID = "esp32_wokwi_estufa_davi_luiz_123"
TOPICO_PUB = "wokwi/dados/sensor"
TOPICO_SUB = "wokwi/comando/atuador"
# CONFIGURAÇÃO DOS PINOS
# Sensor DHT22 (Temperatura e Umidade)
pino_dht = Pin(4)
sensor_dht = dht.DHT22(pino_dht)
# Sensores de umidade do solo FC-28 (Potenciômetros em GPIO 34 e GPIO 35)
sensor_solo_1 = ADC(Pin(34))
sensor_solo_1.atten(ADC.ATTN_11DB)
sensor_solo_1.width(ADC.WIDTH_12BIT)
sensor_solo_2 = ADC(Pin(35))
sensor_solo_2.atten(ADC.ATTN_11DB)
sensor_solo_2.width(ADC.WIDTH_12BIT)
# Sensor de Luminosidade LDR (Entrada Analógica GPIO 32)
sensor_ldr = ADC(Pin(32))
sensor_ldr.atten(ADC.ATTN_11DB)
sensor_ldr.width(ADC.WIDTH_12BIT)
# Atuadores (Relés e PWMs)
rele_valvula_1 = Pin(18, Pin.OUT)
rele_valvula_2 = Pin(19, Pin.OUT)
rele_dispenser = Pin(26, Pin.OUT)
pwm_led_1 = PWM(Pin(25), freq=1000, duty=0)
pwm_led_2 = PWM(Pin(27), freq=1000, duty=0)
# LIMIARES DE OPERAÇÃO
UMIDADE_SOLO_MIN = 30
UMIDADE_SOLO_MAX = 70
TEMPERATURA_MAX = 30.0
UMIDADE_AR_MAX = 80.0
LUMINOSIDADE_MIN = 300
LUMINOSIDADE_MAX = 800
INTERVALO_LEITURA = 3
# CONEXÃO WI-FI E MQTT
def conectar_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print("Conectando ao Wi-Fi...", end="")
wlan.connect(WIFI_SSID, WIFI_PASS)
while not wlan.isconnected():
print(".", end="")
time.sleep(0.5)
print("\n[Wi-Fi] Conectado com sucesso!")
def callback_mqtt(topic, msg):
try:
comando = msg.decode('utf-8').strip().upper()
topico = topic.decode('utf-8')
print(f"\n[MQTT RECEBIDO] Tópico: {topico} | Comando: {comando}")
if comando == "VALVULA1_ON":
rele_valvula_1.value(1)
elif comando == "VALVULA1_OFF":
rele_valvula_1.value(0)
elif comando == "VALVULA2_ON":
rele_valvula_2.value(1)
elif comando == "VALVULA2_OFF":
rele_valvula_2.value(0)
elif comando == "DISPENSER_ON":
rele_dispenser.value(1)
elif comando == "DISPENSER_OFF":
rele_dispenser.value(0)
elif comando == "LUZ_ON":
pwm_led_1.duty(1023) # Ligas os LEDs com brilho máximo (100%)
pwm_led_2.duty(1023)
print(" [ILUMINAÇÃO] Forçada LIGADA via MQTT")
elif comando == "LUZ_OFF":
pwm_led_1.duty(0) # Desliga os LEDs (0%)
pwm_led_2.duty(0)
print(" [ILUMINAÇÃO] Forçada DESLIGADA via MQTT")
except Exception as e:
print("[ERRO Callback MQTT]:", e)
def conectar_mqtt():
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER)
client.set_callback(callback_mqtt)
client.connect()
client.subscribe(TOPICO_SUB)
print(f"[MQTT] Conectado ao Broker '{MQTT_BROKER}' e inscrito em '{TOPICO_SUB}'")
return client
# LEITURA DOS SENSORES
def ler_dht22():
try:
sensor_dht.measure()
return sensor_dht.temperature(), sensor_dht.humidity()
except OSError:
print("[ERRO] Falha na leitura do DHT22.")
return None, None
def ler_umidade_solo(sensor_adc, nome_canteiro):
valor_bruto = sensor_adc.read()
umidade_percentual = int(100 - ((valor_bruto / 4095.0) * 100))
return max(0, min(100, umidade_percentual))
def ler_luminosidade():
try:
valor_adc = sensor_ldr.read()
# Converte leitura do LDR (0 a 4095) para escala de 0 a 1000 Lux
lux = int((valor_adc / 4095.0) * 1000)
return lux
except Exception:
print("[ERRO] Falha na leitura do LDR.")
return -1
# CONTROLE DOS ATUADORES
def controlar_irrigacao(umidade_solo, rele_valvula, nome_canteiro):
if umidade_solo < UMIDADE_SOLO_MIN:
rele_valvula.value(1)
print(f" [IRRIGAÇÃO {nome_canteiro}] LIGADA - Solo seco ({umidade_solo}%)")
elif umidade_solo > UMIDADE_SOLO_MAX:
rele_valvula.value(0)
print(f" [IRRIGAÇÃO {nome_canteiro}] DESLIGADA - Solo úmido ({umidade_solo}%)")
def controlar_iluminacao(lux, pwm_led, nome_led):
if lux < 0:
pwm_led.duty(0)
return
if lux < LUMINOSIDADE_MIN:
duty = int(1023 - ((lux / LUMINOSIDADE_MIN) * 767))
duty = max(256, min(1023, duty))
pwm_led.duty(duty)
print(f" [LED {nome_led}] LIGADO - Duty: {duty} (Lux: {lux:.0f})")
elif lux > LUMINOSIDADE_MAX:
pwm_led.duty(0)
print(f" [LED {nome_led}] DESLIGADO - Lux suficiente ({lux:.0f})")
else:
duty = int(((LUMINOSIDADE_MAX - lux) / (LUMINOSIDADE_MAX - LUMINOSIDADE_MIN)) * 512)
pwm_led.duty(duty)
print(f" [LED {nome_led}] AJUSTADO - Duty: {duty} (Lux: {lux:.0f})")
def controlar_dispenser(temperatura, umidade_ar):
if temperatura is not None and umidade_ar is not None:
if temperatura > TEMPERATURA_MAX and umidade_ar > UMIDADE_AR_MAX:
rele_dispenser.value(1)
print(f" [DISPENSER] ACIONADO - Risco de pragas ({temperatura:.1f}°C, {umidade_ar:.1f}%)")
else:
rele_dispenser.value(0)
def exibir_status(temperatura, umidade_ar, solo_1, solo_2, lux):
print("\n" + "=" * 60)
print(" ESTUFA DO SR. JOÃO - MONITORAMENTO IoT")
print("=" * 60)
if temperatura is not None:
print(f" Temperatura do ar: {temperatura:.1f} °C")
print(f" Umidade do ar: {umidade_ar:.1f} %")
else:
print(" Temperatura / Umidade: ERRO na leitura")
print(f" Umidade solo cant. 1: {solo_1} %")
print(f" Umidade solo cant. 2: {solo_2} %")
print(f" Luminosidade LDR: {lux} lux" if lux >= 0 else " Luminosidade: ERRO")
print("-" * 60)
def inicializar():
rele_valvula_1.value(0)
rele_valvula_2.value(0)
pwm_led_1.duty(0)
pwm_led_2.duty(0)
rele_dispenser.value(0)
print("=" * 60)
print("SISTEMA DE AUTOMAÇÃO IoT - ESTUFAS DO SR. JOÃO")
print("Inicialização concluída.")
print("=" * 60)
# LOOP PRINCIPAL
def main():
conectar_wifi()
client = conectar_mqtt()
inicializar()
ultimo_envio = 0
while True:
try:
client.check_msg()
except OSError:
print("[MQTT] Conexão perdida. Reconectando...")
client = conectar_mqtt()
agora = time.time()
if agora - ultimo_envio >= INTERVALO_LEITURA:
temperatura, umidade_ar = ler_dht22()
solo_1 = ler_umidade_solo(sensor_solo_1, "Canteiro 1")
solo_2 = ler_umidade_solo(sensor_solo_2, "Canteiro 2")
lux = ler_luminosidade()
exibir_status(temperatura, umidade_ar, solo_1, solo_2, lux)
controlar_irrigacao(solo_1, rele_valvula_1, "Canteiro 1")
controlar_irrigacao(solo_2, rele_valvula_2, "Canteiro 2")
controlar_iluminacao(lux, pwm_led_1, "LED 1")
controlar_iluminacao(lux, pwm_led_2, "LED 2")
controlar_dispenser(temperatura, umidade_ar)
payload = ujson.dumps({
"temperatura": temperatura if temperatura is not None else 0,
"umidade_ar": umidade_ar if umidade_ar is not None else 0,
"umidade_solo_1": solo_1,
"umidade_solo_2": solo_2,
"luminosidade": lux if lux >= 0 else 0,
"valvula_1": rele_valvula_1.value(),
"valvula_2": rele_valvula_2.value(),
"dispenser": rele_dispenser.value()
})
client.publish(TOPICO_PUB, payload)
print(f"\n[MQTT PUBLICADO] Tópico: '{TOPICO_PUB}' | Payload: {payload}")
ultimo_envio = agora
time.sleep(0.1)
main()