import network # Para conectar no Wi-Fi
import time # Para contar o tempo e fazer pausas
from machine import Pin, PWM # Para controlar os pinos e o motor da tampa (PWM)
from umqtt.simple import MQTTClient
import dht # Para ler a temperatura e umidade
# Informações para a lixeira se conectar na internet (MQTT)
ID_DA_LIXEIRA = "andreylindao123lixeira"
SERVIDOR_MQTT = "mqtt-dashboard.com" # Onde a lixeira se conecta para enviar/receber mensagens
USUARIO_MQTT = ""
SENHA_MQTT = ""
TOPICO_STATUS = "lixeira/status"
TOPICO_COMANDOS = "lixeira/comandos" # Onde a lixeira recebe comandos
# Onde cada parte da lixeira está conectada (pinos do ESP32)
PINO_SENSOR_DISTANCIA_ENVIA = 18 # Pino TRIG do sensor de distância ( envia um pulso de som )
PINO_SENSOR_DISTANCIA_RECEBE = 19 # Pino ECHO do sensor de distância ( recebe o som de volta )
PINO_SENSOR_TEMPERATURA = 22 # Pino do sensor de temperatura e umidade (DHT22)
PINO_MOTOR_TAMPA = 13 # Pino que controla o motor da tampa (servo)
PINO_LED = 23 # Pino que liga o LED
sensorDeTemperatura = dht.DHT22(Pin(PINO_SENSOR_TEMPERATURA)) # seta a leitura pro sensorDeTemperatura
led = Pin(PINO_LED, Pin.OUT) # Diz que o pino do LED é de saída
led.value(0) # Garante que o LED começa desligado
motorDaTampa = PWM(Pin(PINO_MOTOR_TAMPA)) # Prepara o controle do motor da tampa
# Como a lixeira sabe se está vazia ou cheia (ajuste se precisar)
DISTANCIA_LIXEIRA_VAZIA = 50 # Distância (em cm) do sensor até o fundo quando a lixeira está vazia
DISTANCIA_LIXEIRA_CHEIA = 5 # Distância (em cm) do sensor até o lixo quando a lixeira está cheia
# Como o motor da tampa se move (ajuste se a tampa não abrir/fechar direito)
POSICAO_TAMPA_ABERTA = 90 # Posição para abrir a tampa
POSICAO_TAMPA_FECHADA = 40 # Posição para fechar a tampa
estadoDaTampa = "fechada" # A tampa começa fechada
estadoDoLED = "desligado" # O LED começa desligado
# Função para ver a distância do lixo (em centímetros)
def verDistanciaDoLixo():
pinoEnvia = Pin(PINO_SENSOR_DISTANCIA_ENVIA, Pin.OUT) # Pino para enviar o som
pinoRecebe = Pin(PINO_SENSOR_DISTANCIA_RECEBE, Pin.IN) # Pino para receber o som
pinoEnvia.value(0) # Limpa o pino de envio
time.sleep_us(2) # Pequena pausa
pinoEnvia.value(1) # Envia um pulso
time.sleep_us(10) # Por 10 ms
pinoEnvia.value(0) # Para de enviar
tempoLimite = 30000 # Tempo máximo para esperar o som voltar 30kms
tempoInicio = time.ticks_us() # Salva o tempo desde que o esp foi ligado
# Espera o som voltar
while pinoRecebe.value() == 0:
if time.ticks_diff(time.ticks_us(), tempoInicio) > tempoLimite:
return -1 # Se demorar demais, deu erro
tempoPulsoComecou = time.ticks_us() # Marca quando o som começou a voltar
# Espera o som terminar
while pinoRecebe.value() == 1: #vira 1 quando recebe o som
if time.ticks_diff(time.ticks_us(), tempoPulsoComecou) > tempoLimite:#time.ticks_diff é diferença x-y
return -1 # Se demorar demais, deu erro
duracao = time.ticks_diff(time.ticks_us(), tempoPulsoComecou) # Quanto tempo o som levou para ir e voltar
if duracao == -1:
return -1 # Se deu erro antes, volta -1
distancia = (duracao * 0.0343) / 2 # Calcula a distância (velocidade do som) como vai e volta divide por 2
return distancia #cm/ms^^^^
# Função para calcular quanto a lixeira está cheia (em porcentagem)
def calcularQuantoTaCheia(distancia):
if distancia == -1:
return -1 # Se a leitura de distância falhou, retorna erro(pq sempre le -1 quando da ruim?)
if distancia >= DISTANCIA_LIXEIRA_VAZIA: #se tirar a tampa
return 0 # Lixeira vazia
elif distancia <= DISTANCIA_LIXEIRA_CHEIA:
return 100 # Lixeira cheia
else:
espacoTotal = DISTANCIA_LIXEIRA_VAZIA - DISTANCIA_LIXEIRA_CHEIA
espacoAtual = distancia - DISTANCIA_LIXEIRA_CHEIA
porcentagem = (1 - (espacoAtual / espacoTotal)) * 100
return max(0, min(100, int(porcentagem))) # Garante que a porcentagem fique entre 0 e 100
# Função para ver a temperatura e a umidade do ar
def verTemperaturaEUmidade():
temperatura = -1.0 # Começa com valor de erro
umidade = -1.0 # Começa com valor de erro
try:
sensorDeTemperatura.measure() # Faz a leitura
temperatura = sensorDeTemperatura.temperature() # Pega a temperatura
umidade = sensorDeTemperatura.humidity() # Pega a umidade
except OSError as e:
print(f"Erro ao ler sensor DHT22: {e}")
return temperatura, umidade # Retorna os valores
# Função para abrir a tampa
def abrirTampa():
global estadoDaTampa # Avisa que vamos mudar a variável global
motorDaTampa.duty(POSICAO_TAMPA_ABERTA) # Manda o motor para a posição de abrir
estadoDaTampa = "aberta" # Muda o estado da tampa
print("Tampa da lixeira: ABERTA.")
# Função para fechar a tampa
def fecharTampa():
global estadoDaTampa # Avisa que vamos mudar a variável global
motorDaTampa.duty(POSICAO_TAMPA_FECHADA) # Manda o motor para a posição de fechar
estadoDaTampa = "fechada" # Muda o estado da tampa
print("Tampa da lixeira: FECHADA.")
# Função para ligar o LED
def ligarLED():
global estadoDoLED
if estadoDoLED == "desligado":
led.value(1)
estadoDoLED = "ligado"
print("LED: LIGADO.")
# Função para desligar o LED
def desligarLED():
global estadoDoLED
if estadoDoLED == "ligado":
led.value(0)
estadoDoLED = "desligado"
print("LED: DESLIGADO.")
# O que fazer quando a lixeira recebe uma mensagem pela internet (MQTT)
def lidarComMensagemMQTT(topico, mensagem):
print(f"Ordem da internet recebida: {topico.decode()} -> {mensagem.decode()}")
comando = mensagem.decode() # Transforma a mensagem em texto
if comando == "abrir_tampa":
abrirTampa() # Abre a tampa
elif comando == "fechar_tampa":
fecharTampa() # Fecha a tampa
elif comando == "led_on": # Novo comando para ligar o LED via MQTT
ligarLED()
elif comando == "led_off": # Novo comando para desligar o LED via MQTT
desligarLED()
else:
print("Ordem desconhecida.")
# Função para conectar ao Wi-Fi
def conectar_wifi():
print("Conectando no Wi-Fi", end="")
conexaoWiFI = network.WLAN(network.STA_IF) # Prepara para conectar como um aparelho comum
conexaoWiFI.active(True) # Liga o Wi-Fi
conexaoWiFI.connect('Wokwi-GUEST', '') # Tenta conectar (nome da rede, senha)
max_attempts = 100 # Aumenta as tentativas para 10 segundos
attempts = 0
while not conexaoWiFI.isconnected() and attempts < max_attempts:
print(".", end="") # Mostra um ponto
time.sleep(0.1) # Espera um pouquinho
attempts += 1
if conexaoWiFI.isconnected():
print(" Conectado!")
return conexaoWiFI
else:
print("\nFalha ao conectar no Wi-Fi. Reiniciando...")
time.sleep(2)
machine.reset() # Reinicia o ESP32 se não conseguir conectar ao Wi-Fi
return None # Should not reach here
# Função para conectar ao servidor MQTT
def conectar_mqtt():
global clienteMQTT # Declara clienteMQTT como global para poder atribuir a ela
print("Conectando no servidor de mensagens... ", end="")
try:
# Cria o programa que conversa com o servidor MQTT
clienteMQTT = MQTTClient(ID_DA_LIXEIRA, SERVIDOR_MQTT, user=USUARIO_MQTT, password=SENHA_MQTT)
clienteMQTT.set_callback(lidarComMensagemMQTT) # Diz o que fazer quando receber uma mensagem
clienteMQTT.connect() # Tenta conectar
clienteMQTT.subscribe(TOPICO_COMANDOS) # A lixeira começa a 'escutar' as ordens
print("Conectado!")
return True
except Exception as e:
print(f"Deu erro na conexão com o servidor de mensagens: {e}")
return False
# Início do programa principal
conexaoWiFI = conectar_wifi()
if conexaoWiFI is None:
# Se a conexão Wi-Fi falhar e reiniciar, o código não prosseguirá aqui
pass
if not conectar_mqtt():
# Se a conexão MQTT falhar, o código tentará novamente após o reset
time.sleep(5)
machine.reset()
while True:
try:
clienteMQTT.check_msg() # Vê se chegou alguma mensagem da internet
# Lê os sensores
distancia = verDistanciaDoLixo()
porcentagemCheia = calcularQuantoTaCheia(distancia)
temperatura, umidade = verTemperaturaEUmidade()
# Mostra o que está acontecendo no console
print("\nO que a lixeira está fazendo:")
if distancia != -1:
print(f"Distância do lixo: {distancia:.1f} cm")
print(f"Lixeira está cheia: {porcentagemCheia}%")
else:
print("Distância do lixo: Deu erro na leitura")
print("Lixeira está cheia: Não sei")
if temperatura != -1.0:
print(f"Temperatura: {temperatura:.1f} °C")
else:
print("Temperatura: Deu erro na leitura")
if umidade != -1.0:
print(f"Umidade do ar: {umidade:.1f}%")
else:
print("Umidade do ar: Deu erro na leitura")
print(f"Status da Tampa: {estadoDaTampa}")
print(f"Status do LED: {estadoDoLED}") # Updated print statement
print("--------------------------")
# Vê se tem líquido (umidade muito alta)
temLiquido = False
if umidade != -1.0 and umidade > 85.0: # Limite de umidade para detectar líquido (you can adjust this threshold)
temLiquido = True
# Determine if LED should be ON
if porcentagemCheia >= 80 or temLiquido: # LED turns on if trash is >=80% full OR liquid is detected
ligarLED()
if porcentagemCheia >= 80 and not temLiquido:
print("ALERTA: Lixeira quase cheia! LED ligado.")
elif temLiquido and not porcentagemCheia >= 80:
print("ALERTA: Tem líquido! LED ligado.")
elif porcentagemCheia >= 80 and temLiquido:
print("ALERTA: Lixeira quase cheia E tem líquido! LED ligado.")
else:
desligarLED() # LED turns off if neither condition is met
print("Lixeira não está cheia e não tem líquido. LED desligado.")
# Envia o status da lixeira pela internet (MQTT)
mensagemDeStatus = (
"Temp: {:.1f}C, Umid: {:.1f}%, "
"Dist: {:.1f}cm, Cheio: {}%, "
"Tampa: {}, LED: {}".format( # Updated status message
temperatura, umidade, distancia, porcentagemCheia, estadoDaTampa, estadoDoLED
)
)
print(f"Enviando para MQTT: {mensagemDeStatus}")
clienteMQTT.publish(TOPICO_STATUS, mensagemDeStatus.encode('utf-8')) # Publica a mensagem
except OSError as e:
print(f"Erro de conexão MQTT ou de rede: {e}")
# Tenta reconectar
if not conectar_mqtt():
print("Tentando reconectar ao MQTT falhou. Reiniciando...")
time.sleep(5)
machine.reset() # Reinicia o ESP32 se a reconexão MQTT falhar
# A lixeira espera 5 segundos antes de fazer tudo de novo.
time.sleep(5)