#!/usr/bin/env python 
from machine import Pin, I2C, PWM
import utime
import dht
from pico_i2c_lcd import I2cLcd
import os
import stepper
# --- Constantes de Pinos ---
# Note a ordem dos pinos do motor de passo
DHT_PIN = 2
RELAY_HEAT_PIN = 3
FAN_PIN = 4
UMIDIFICADOR_PIN = 6
SPEAKER_PIN = 7
STATUS_LED_PIN = 13
STEPPER_PINS = [28, 27, 26, 22] 
# --- Constantes de Controle da Incubadora ---
TEMP_MIN = 37.0
TEMP_MAX = 38.0
UMIDADE_MIN = 45.0
UMIDADE_MAX = 55.0
TEMPO_INCUBACAO_DIAS = 21
DIAS_ALARME_ECLOSAO = 3
# --- Constantes de Tempo em Milissegundos ---
# O intervalo para virar os ovos (4 horas)
INTERVALO_VIRADA = 4 * 60 * 60 * 1000  
ALARME_DELAY = 1 * 60 * 1000           
UPDATE_LCD_INTERVAL = 2000             
MILISSEGUNDOS_POR_DIA = 86400000
# --- Variáveis de Estado (globais) ---
ultima_virada = 0
ultimo_alarme = 0
ultimo_update_lcd = 0
alarme_ativado = False
alarme_eclosao_ativado = False
data_inicio_ms = 0
# --- Inicialização de Hardware ---
dht_sensor = dht.DHT22(Pin(DHT_PIN, Pin.PULL_UP))
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
lcd = I2cLcd(i2c, 0x27, 2, 16)
buzzer_pwm = PWM(Pin(SPEAKER_PIN))
stepper_motor = stepper.HalfStepMotor.frompins(*STEPPER_PINS)
pin_heat = Pin(RELAY_HEAT_PIN, Pin.OUT)
pin_fan = Pin(FAN_PIN, Pin.OUT)
pin_umidificador = Pin(UMIDIFICADOR_PIN, Pin.OUT)
pin_status_led = Pin(STATUS_LED_PIN, Pin.OUT)
# --- Funções de Controle ---
def play_alarm():
    buzzer_pwm.duty_u16(50000)
def stop_alarm():
    buzzer_pwm.duty_u16(0)
def load_start_time():
    global data_inicio_ms
    try:
        with open('start_time.txt', 'r') as f:
            data_inicio_ms = int(f.read())
            print(f"Data de início carregada: {data_inicio_ms}")
    except (OSError, ValueError):
        data_inicio_ms = utime.ticks_ms()
        with open('start_time.txt', 'w') as f:
            f.write(str(data_inicio_ms))
        print("Nova data de início salva.")
def setup():
    global ultima_virada, ultimo_alarme, ultimo_update_lcd
    
    lcd.backlight_on()
    lcd.clear()
    lcd.move_to(0, 0)
    lcd.putstr("ChacadeiraDe0v0s")
    utime.sleep(2)
    lcd.clear()
    
    load_start_time()
    
    pin_heat.value(0)
    pin_fan.value(0)
    pin_umidificador.value(0)
    pin_status_led.value(0)
    stepper_motor.reset()
    ultima_virada = utime.ticks_ms()
    ultimo_alarme = utime.ticks_ms()
    ultimo_update_lcd = utime.ticks_ms()
    buzzer_pwm.freq(1000)
    buzzer_pwm.duty_u16(0)
# --- LOOP PRINCIPAL ---
def main_loop():
    global ultimo_update_lcd, ultimo_alarme, alarme_ativado, alarme_eclosao_ativado, ultima_virada
    while True:
        tempo_atual = utime.ticks_ms()
        # Leitura do sensor
        try:
            dht_sensor.measure()
            temperatura = dht_sensor.temperature()
            umidade = dht_sensor.humidity()
        except (OSError, ValueError) as e:
            print(f"Erro no sensor DHT: {e}")
            lcd.clear()
            lcd.putstr("Erro no sensor")
            utime.sleep(2)
            continue
        
        # --- Lógica de controle de aquecimento, ventilação e umidade ---
        if temperatura < TEMP_MIN:
            pin_heat.value(1)
            pin_fan.value(0)
        else:
            pin_heat.value(0)
            
        if temperatura > TEMP_MAX:
            pin_fan.value(1)
            pin_heat.value(0)
        else:
            pin_fan.value(0)
            
        if umidade < UMIDADE_MIN:
            pin_umidificador.value(1)
        else:
            pin_umidificador.value(0)
        
        # --- Atualização do LCD (não bloqueante) ---
        if utime.ticks_diff(tempo_atual, ultimo_update_lcd) >= UPDATE_LCD_INTERVAL:
            print(f"Temperatura: {temperatura:.2f}°C, Umidade: {umidade:.2f}%")
            lcd.clear()
            lcd.putstr(f"T:{temperatura:.1f}C U:{umidade:.1f}%")
            
            dias_passados = utime.ticks_diff(tempo_atual, data_inicio_ms) // MILISSEGUNDOS_POR_DIA
            dias_restantes = TEMPO_INCUBACAO_DIAS - dias_passados
            
            lcd.move_to(0, 1)
            if dias_restantes > 0:
                lcd.putstr(f"Faltam {dias_restantes} dias")
            else:
                lcd.putstr("Eclosao!")
            
            ultimo_update_lcd = tempo_atual
        # --- Lógica de Alarme de Faixa (Temperatura/Umidade) ---
        fora_da_faixa = (temperatura < TEMP_MIN or temperatura > TEMP_MAX or umidade < UMIDADE_MIN or umidade > UMIDADE_MAX)
        if fora_da_faixa:
            if utime.ticks_diff(tempo_atual, ultimo_alarme) >= ALARME_DELAY:
                if not alarme_ativado:
                    play_alarm()
                    alarme_ativado = True
                    pin_status_led.value(1)
                    lcd.clear()
                    lcd.putstr("ALARME: Fora da faixa")
        else:
            ultimo_alarme = tempo_atual
            if alarme_ativado:
                stop_alarm()
                alarme_ativado = False
                pin_status_led.value(0)
        # --- Lógica de Alarme de Eclosão ---
        dias_passados = utime.ticks_diff(tempo_atual, data_inicio_ms) // MILISSEGUNDOS_POR_DIA
        dias_restantes = TEMPO_INCUBACAO_DIAS - dias_passados
        if dias_restantes <= DIAS_ALARME_ECLOSAO and dias_restantes > 0 and not alarme_eclosao_ativado:
            play_alarm()
            alarme_eclosao_ativado = True
            lcd.clear()
            lcd.putstr("Alerta: Eclosao!")
            lcd.move_to(0, 1)
            lcd.putstr("Faltam poucos dias")
        # --- Viragem dos ovos (não bloqueante) ---
        if utime.ticks_diff(tempo_atual, ultima_virada) >= INTERVALO_VIRADA:
            stepper_motor.step(180) 
            ultima_virada = tempo_atual
# --- Início do programa ---
if __name__ == "__main__":
    setup()
    main_loop()
Loading
pi-pico-w
pi-pico-w