from machine import Pin, I2C, PWM
import dht
import time
import ssd1306
# --- 1. CONFIGURAÇÃO DE HARDWARE ---
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
sensor = dht.DHT22(Pin(23))
buzzer = Pin(19, Pin.OUT)
led_verde = Pin(14, Pin.OUT)
led_vermelho = Pin(27, Pin.OUT)
rele_seguranca = Pin(18, Pin.OUT)
ptc_pwm = PWM(Pin(17), freq=1000)
servo_pwm = PWM(Pin(13), freq=50)
# Botões
botao_verde = Pin(25, Pin.IN, Pin.PULL_UP)
botao_amarelo = Pin(26, Pin.IN, Pin.PULL_UP)
botao_cinza = Pin(32, Pin.IN, Pin.PULL_UP)
botao_vermelho = Pin(33, Pin.IN, Pin.PULL_UP)
# --- 2. BANCO DE DADOS E ESTADOS ---
config_filamentos = {
"PLA": {"Normal": 45, "Hard": 50, "Tempo": 14400000},
"PETG": {"Normal": 50, "Hard": 55, "Tempo": 21600000},
"ABS": {"Normal": 60, "Hard": 65, "Tempo": 14400000},
"NYLON": {"Normal": 70, "Hard": 75, "Tempo": 43200000}
}
lista_filamentos = list(config_filamentos.keys())
filamento_sel = lista_filamentos[0]
modo_atual = 1 # 1:Normal, 2:Hard, 3:Manual
campo_edicao = 1 # 1:Temp, 2:Tempo
manual_temp = 50
manual_tempo_ms = 3600000
temp_alvo = config_filamentos[filamento_sel]["Normal"]
# Sensores e Variáveis de Controle
temp_atual = 0
umidade_atual = 0
ultima_temp_leitura = 0
contador_estagnado = 0
rodando = False
aviso_quente = False
ciclo_finalizado = False
tempo_restante_ms = 0
ultimo_servo_ms = 0
duty_atual = 0
LIMITE_CRITICO = 85 # Segurança Máxima
# --- 3. FUNÇÕES DE SUPORTE ---
def mover_servo(angulo):
duty = int((angulo / 180 * 75) + 40)
servo_pwm.duty(duty)
def controlar_potencia(atual, alvo):
erro = alvo - atual
if erro > 10: return 800 # Limite Vanessa para caixa de madeira
elif erro > 0: return int((erro / 10) * 800)
return 0
def desligar_tudo(sucesso=False):
global rodando, ciclo_finalizado, duty_atual
rodando = False
ciclo_finalizado = sucesso
duty_atual = 0
rele_seguranca.value(0)
ptc_pwm.duty(0)
mover_servo(0)
def beep(tipo):
if tipo == "curto":
buzzer.value(1); time.sleep(0.05); buzzer.value(0)
elif tipo == "alerta":
for _ in range(3):
buzzer.value(1); time.sleep(0.2); buzzer.value(0); time.sleep(0.1)
def atualizar_display():
oled.fill(0)
agora = time.ticks_ms()
piscar = (agora // 400) % 2 == 0
if aviso_quente:
oled.text("AVISO: QUENTE!", 10, 10)
oled.text(f"Temp: {temp_atual}C", 20, 35)
oled.text("Aguarde...", 25, 50)
elif ciclo_finalizado:
oled.text("SECAGEM OK!", 20, 10)
oled.text(f"Umidade: {umidade_atual}%", 15, 30)
oled.text("> Reset (Verm)", 5, 52)
elif not rodando:
txt_m = ["", "NORMAL", "HARD", "MANUAL"][modo_atual]
oled.text(f"MODO: {txt_m}", 25, 0)
if modo_atual == 3:
t_str = f"Temp: {manual_temp}C" if not (campo_edicao==1 and piscar) else "Temp: --"
m_str = f"Time: {manual_tempo_ms//60000}m" if not (campo_edicao==2 and piscar) else "Time: --"
oled.text(f"{'>' if campo_edicao==1 else ' '} {t_str}", 0, 22)
oled.text(f"{'>' if campo_edicao==2 else ' '} {m_str}", 0, 38)
oled.text("Segure Cin: Sair", 0, 55)
else:
oled.text(f"Fil: {filamento_sel}", 0, 22)
oled.text(f"Alvo: {temp_alvo}C", 0, 38)
oled.text(f"Time: {config_filamentos[filamento_sel]['Tempo']//3600000}h", 0, 52)
else:
# TELA EM OPERAÇÃO (Vanessa Humidity Update)
oled.text("SECANDO...", 30, 0)
oled.text(f"T: {temp_atual}C / {temp_alvo}C", 0, 18)
oled.text(f"UMIDADE: {umidade_atual}%", 0, 32) # Umidade em destaque
pot = int((duty_atual/800)*100)
oled.text(f"Potencia: {pot}%", 0, 44)
oled.text(f"Falta: {tempo_restante_ms//60000} min", 0, 56)
oled.show()
# --- 4. LOOP PRINCIPAL ---
desligar_tudo()
ult_leitura_sensor = 0
while True:
agora = time.ticks_ms()
# Feedback LEDs
if aviso_quente:
led_vermelho.value(1); led_verde.value(0)
elif ciclo_finalizado:
led_vermelho.value(0); led_verde.value((agora // 500) % 2)
elif not rodando:
led_vermelho.value(0); led_verde.value(1)
else:
led_vermelho.value(0); led_verde.value(0)
# Lógica do Sensor (A cada 2 seg)
if time.ticks_diff(agora, ult_leitura_sensor) > 2000:
try:
sensor.measure()
temp_atual = sensor.temperature()
umidade_atual = sensor.humidity()
# Segurança: Sensor Estagnado (Se ligar o fogo e a temp não mudar em 5 min)
if rodando:
if temp_atual == ultima_temp_leitura and duty_atual > 400:
contador_estagnado += 1
else:
contador_estagnado = 0
ultima_temp_leitura = temp_atual
if contador_estagnado > 150: # Falha de segurança
desligar_tudo()
beep("alerta")
# Segurança: Corte Crítico
if temp_atual > LIMITE_CRITICO:
desligar_tudo()
while True:
led_vermelho.value(1); oled.fill(0); oled.text("SUPER-AQUECIMENTO", 0, 30); oled.show()
buzzer.value(1); time.sleep(0.5); buzzer.value(0); time.sleep(0.5)
if rodando:
duty_atual = controlar_potencia(temp_atual, temp_alvo)
ptc_pwm.duty(duty_atual)
# Escotilha (Servo)
if time.ticks_diff(agora, ultimo_servo_ms) > 600000:
mover_servo(90); time.sleep(3); mover_servo(0)
ultimo_servo_ms = agora
tempo_restante_ms = max(0, tempo_restante_ms - 2000)
if tempo_restante_ms <= 0:
desligar_tudo(sucesso=True)
beep("alerta")
except:
print("Erro de leitura sensor!")
if rodando: desligar_tudo() # Se falhar rodando, cancela por segurança
ult_leitura_sensor = agora
# --- LÓGICA DE BOTÕES ---
# Botão Cinza: Ciclo Normal -> Hard -> Manual
if botao_cinza.value() == 0 and not rodando:
p_start = time.ticks_ms()
is_long = False
while botao_cinza.value() == 0:
if time.ticks_diff(time.ticks_ms(), p_start) > 2500:
if modo_atual == 3:
modo_atual = 1
temp_alvo = config_filamentos[filamento_sel]["Normal"]
beep("curto")
is_long = True
break
if not is_long:
if modo_atual != 3:
modo_atual = (modo_atual % 3) + 1
if modo_atual == 1: temp_alvo = config_filamentos[filamento_sel]["Normal"]
elif modo_atual == 2: temp_alvo = config_filamentos[filamento_sel]["Hard"]
else: temp_alvo = manual_temp
else:
campo_edicao = 2 if campo_edicao == 1 else 1
beep("curto")
time.sleep(0.2)
# Botão Amarelo: Muda Filamento / Ajuste Manual / Reset Tempo
if botao_amarelo.value() == 0 and not rodando:
p_start = time.ticks_ms()
is_reset = False
while botao_amarelo.value() == 0:
if modo_atual == 3 and time.ticks_diff(time.ticks_ms(), p_start) > 2500:
manual_tempo_ms = 0
beep("curto"); time.sleep(0.1); beep("curto")
is_reset = True
break
if not is_reset:
if modo_atual == 3:
if campo_edicao == 1:
manual_temp = 40 if manual_temp >= 85 else manual_temp + 1
temp_alvo = manual_temp
else:
manual_tempo_ms += 60000
else:
idx = (lista_filamentos.index(filamento_sel) + 1) % len(lista_filamentos)
filamento_sel = lista_filamentos[idx]
temp_alvo = config_filamentos[filamento_sel]["Hard" if modo_atual == 2 else "Normal"]
beep("curto")
time.sleep(0.2)
# Botão Vermelho: Stop / Reset total
if botao_vermelho.value() == 0:
desligar_tudo()
aviso_quente = False
ciclo_finalizado = False
beep("curto")
time.sleep(0.2)
# Botão Verde: Start
if botao_verde.value() == 0:
if not rodando:
# Trava de Segurança: Não inicia sem sensor
if temp_atual == 0:
beep("alerta")
elif temp_atual > (temp_alvo + 2):
aviso_quente = True
beep("alerta")
else:
tempo_restante_ms = manual_tempo_ms if modo_atual == 3 else config_filamentos[filamento_sel]["Tempo"]
rele_seguranca.value(1) # Ativa os 24V
rodando = True
ultimo_servo_ms = agora
beep("curto")
else:
desligar_tudo()
time.sleep(0.2)
atualizar_display()
time.sleep_ms(50)