import network
import time
import machine
import dht
import urequests
from machine import Pin, ADC, I2C
from umqtt.simple import MQTTClient
# ─────────────────────────────────────────────────────────────
# WIFI
# ─────────────────────────────────────────────────────────────
WIFI_SSID = "SEU_WIFI"
WIFI_PASS = "SENHA_WIFI"
# ─────────────────────────────────────────────────────────────
# MQTT PRIVADO
# ─────────────────────────────────────────────────────────────
MQTT_BROKER = "192.168.0.10" # IP DO PC COM NODE-RED/MQTT
MQTT_PORT = 1883
MQTT_USER = "gustavo"
MQTT_PASS = "123456"
MQTT_CLIENT_ID = b"esp32_estacao_gustavo"
MQTT_TOPIC = b"gustavo/estacao_meteo/dados"
# ─────────────────────────────────────────────────────────────
# OPEN WEATHER
# ─────────────────────────────────────────────────────────────
OWM_API_KEY = "SUA_API_KEY"
OWM_CIDADE = "Sao Paulo,BR"
OWM_URL = (
"http://api.openweathermap.org/data/2.5/weather?q={}"
"&appid={}&units=metric"
).format(
OWM_CIDADE.replace(" ", "%20"),
OWM_API_KEY
)
# ─────────────────────────────────────────────────────────────
# I2C / OLED
# ─────────────────────────────────────────────────────────────
i2c = I2C(
0,
scl=Pin(22),
sda=Pin(21),
freq=400000
)
print("Escaneando I2C...")
devs = i2c.scan()
print("I2C:", [hex(d) for d in devs])
oled = None
oled_ok = False
if devs:
try:
from ssd1306 import SSD1306_I2C
oled = SSD1306_I2C(
128,
64,
i2c,
addr=devs[0]
)
oled_ok = True
print("OLED OK")
except Exception as e:
print("OLED ERRO:", e)
# ─────────────────────────────────────────────────────────────
# SENSORES
# ─────────────────────────────────────────────────────────────
sensor_dht = dht.DHT22(Pin(15))
sensor_ldr = ADC(Pin(34))
sensor_ldr.atten(ADC.ATTN_11DB)
sensor_gas = ADC(Pin(35))
sensor_gas.atten(ADC.ATTN_11DB)
botao = Pin(13, Pin.IN, Pin.PULL_UP)
led = Pin(26, Pin.OUT)
led.value(0)
# ─────────────────────────────────────────────────────────────
# VARIAVEIS
# ─────────────────────────────────────────────────────────────
tela_atual = 0
TOTAL_TELAS = 4
ultimo_clique = 0
ultimo_mqtt = 0
ultimo_dht = 0
ultimo_owm = 0
ultimo_pisca = 0
pisca_estado = 0
client = None
wifi_ok = False
mqtt_ok = False
temp = 25.0
umid = 60.0
luz = 0
gas = 0
hi = 25.0
conforto = "Regular"
pressao = 0
previsao = "Aguardando"
# ─────────────────────────────────────────────────────────────
# OLED
# ─────────────────────────────────────────────────────────────
def oled_msg(l1, l2="", l3=""):
if not oled_ok:
return
oled.fill(0)
oled.text(l1[:16], 0, 10)
if l2:
oled.text(l2[:16], 0, 26)
if l3:
oled.text(l3[:16], 0, 42)
oled.show()
# ─────────────────────────────────────────────────────────────
# WIFI
# ─────────────────────────────────────────────────────────────
def conectar_wifi():
global wifi_ok
print("Conectando WiFi...")
oled_msg("Conectando", "WiFi...")
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(
WIFI_SSID,
WIFI_PASS
)
for _ in range(20):
if wlan.isconnected():
wifi_ok = True
ip = wlan.ifconfig()[0]
print("WiFi OK:", ip)
oled_msg("WiFi OK", ip)
time.sleep(1)
return
time.sleep(0.5)
print("WiFi ERRO")
oled_msg("WiFi ERRO")
time.sleep(1)
# ─────────────────────────────────────────────────────────────
# MQTT
# ─────────────────────────────────────────────────────────────
def conectar_mqtt():
global client
global mqtt_ok
try:
print("Conectando MQTT...")
client = MQTTClient(
MQTT_CLIENT_ID,
MQTT_BROKER,
port=MQTT_PORT,
user=MQTT_USER,
password=MQTT_PASS,
keepalive=60
)
client.connect()
mqtt_ok = True
print("MQTT OK")
except Exception as e:
mqtt_ok = False
print("MQTT ERRO:", e)
# ─────────────────────────────────────────────────────────────
# CALCULOS
# ─────────────────────────────────────────────────────────────
def calcular_conforto(t, h):
if t < 20:
return "Frio"
elif 20 <= t <= 27 and 40 <= h <= 60:
return "Ideal"
elif t > 35:
return "Perigo"
elif t > 30:
return "Quente"
return "Regular"
def calcular_hi(t, h):
if t < 27:
return round(t, 1)
v = (
-8.784695
+ 1.61139411 * t
+ 2.3385549 * h
- 0.14611605 * t * h
- 0.012308094 * t * t
- 0.016424828 * h * h
+ 0.002211732 * t * t * h
+ 0.00072546 * t * h * h
- 0.000003582 * t * t * h * h
)
return round(v, 1)
def calcular_previsao(p):
if p == 0:
return "Sem dados"
if p >= 1022:
return "Sol"
elif p >= 1013:
return "Nublado"
elif p >= 1003:
return "Chuva"
return "Tempestade"
# ─────────────────────────────────────────────────────────────
# OPEN WEATHER
# ─────────────────────────────────────────────────────────────
def consultar_owm():
global pressao
global previsao
try:
print("Consultando clima...")
r = urequests.get(OWM_URL)
if r.status_code == 200:
d = r.json()
pressao = d["main"]["pressure"]
previsao = calcular_previsao(
pressao
)
print("OWM:", pressao)
r.close()
except Exception as e:
print("OWM ERRO:", e)
previsao = "Sem dados"
# ─────────────────────────────────────────────────────────────
# LED
# ─────────────────────────────────────────────────────────────
def controlar_led(alerta, agora):
global ultimo_pisca
global pisca_estado
if alerta:
if time.ticks_diff(
agora,
ultimo_pisca
) > 300:
pisca_estado = 1 - pisca_estado
led.value(pisca_estado)
ultimo_pisca = agora
else:
led.value(0)
pisca_estado = 0
# ─────────────────────────────────────────────────────────────
# OLED TELAS
# ─────────────────────────────────────────────────────────────
def exibir_oled(alerta):
if not oled_ok:
return
oled.fill(0)
if alerta:
oled.fill_rect(0, 0, 128, 12, 1)
oled.text(alerta[:16], 0, 2, 0)
else:
oled.text("ESTACAO", 20, 2)
oled.hline(0, 14, 128, 1)
if tela_atual == 0:
oled.text(
"Temp:{:.1f}C".format(temp),
0,
20
)
oled.text(
"Umid:{:.1f}%".format(umid),
0,
34
)
oled.text(
conforto,
0,
48
)
elif tela_atual == 1:
pct_luz = int(
luz / 4095 * 100
)
oled.text("Luz:", 0, 20)
oled.text(
str(pct_luz) + "%",
0,
34
)
elif tela_atual == 2:
oled.text("Gas:", 0, 20)
oled.text(
str(gas),
0,
34
)
elif tela_atual == 3:
oled.text("Pressao:", 0, 20)
oled.text(
str(pressao) + "hPa",
0,
34
)
oled.text(
previsao[:16],
0,
48
)
oled.show()
# ─────────────────────────────────────────────────────────────
# INICIO
# ─────────────────────────────────────────────────────────────
print("ESTACAO INICIANDO")
oled_msg(
"ESTACAO",
"INICIANDO"
)
time.sleep(2)
conectar_wifi()
if wifi_ok:
conectar_mqtt()
consultar_owm()
ultimo_dht = time.ticks_ms()
ultimo_owm = time.ticks_ms()
# ─────────────────────────────────────────────────────────────
# LOOP
# ─────────────────────────────────────────────────────────────
while True:
agora = time.ticks_ms()
# BOTAO
if not botao.value():
if time.ticks_diff(
agora,
ultimo_clique
) > 300:
tela_atual = (
tela_atual + 1
) % TOTAL_TELAS
ultimo_clique = agora
# DHT22
if time.ticks_diff(
agora,
ultimo_dht
) >= 3000:
try:
sensor_dht.measure()
temp = sensor_dht.temperature()
umid = sensor_dht.humidity()
hi = calcular_hi(
temp,
umid
)
conforto = calcular_conforto(
temp,
umid
)
print("Temp:", temp)
except Exception as e:
print("DHT ERRO:", e)
ultimo_dht = agora
# OPEN WEATHER
if wifi_ok and time.ticks_diff(
agora,
ultimo_owm
) >= 600000:
consultar_owm()
ultimo_owm = agora
# SENSORES
luz = sensor_ldr.read()
gas = sensor_gas.read()
# ALERTA
alerta = ""
if temp > 35:
alerta = "TEMP ALTA"
if gas > 2500:
alerta = "GAS!"
controlar_led(alerta, agora)
exibir_oled(alerta)
# MQTT
if mqtt_ok and time.ticks_diff(
agora,
ultimo_mqtt
) > 5000:
try:
payload = "{};{};{};{};{};{};{};{};{};{}".format(
round(temp, 1),
round(umid, 1),
hi,
conforto,
int(luz / 4095 * 100),
gas,
"Limpo" if gas <= 1000 else "Ruim",
alerta if alerta else "normal",
pressao,
previsao
)
client.publish(
MQTT_TOPIC,
payload
)
print("MQTT:", payload)
ultimo_mqtt = agora
except Exception as e:
print("MQTT ERRO:", e)
mqtt_ok = False
conectar_mqtt()
time.sleep(0.5)