#!/usr/bin/env python
from machine import Pin, I2C, PWM
import utime
import dht
from pico_i2c_lcd import I2cLcd
import os
import stepper
# Define the stepper motor pins
IN1 = 28
IN2 = 27
IN3 = 26
IN4 = 22
DHT_PIN = 2
RELAY_HEAT_PIN = 3
FAN_PIN = 4
UMIDIFICADOR_PIN = 6
SPEAKER_PIN = 7
STATUS_LED_PIN = 13
# --- 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 ---
INTERVALO_VIRADA = 1 * 10 * 1000 # 4 horas
ALARME_DELAY = 1 * 60 * 1000 # 1 minuto
UPDATE_LCD_INTERVAL = 2000 # 2 segundos
# --- Variáveis de estado ---
ultima_virada = 0
ultimo_alarme = 0
ultimo_update_lcd = 0
alarme_ativado = False
alarme_eclosao_ativado = False
# --- Contagem de dias (arquivo de armazenamento) ---
START_TIME_FILE = 'start_time.txt'
data_inicio_ms = 0
# --- Configuração dos componentes ---
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))
buzzer_pwm.freq(1000)
buzzer_pwm.duty_u16(0)
# Setup function
lcd.backlight_on()
lcd.clear()
# --- Define as constantes de pino ---
# Configuração dos pinos de saída
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)
# Initialize the stepper motor
stepper_motor = stepper.HalfStepMotor.frompins(IN1, IN2, IN3, IN4)
# Set the current position as position 0
stepper_motor.reset()
# --- Funções ---
def play_alarm():
buzzer_pwm.duty_u16(50000) # Cerca de 75% do ciclo de trabalho
def stop_alarm():
buzzer_pwm.duty_u16(0)
def load_start_time():
global data_inicio_ms
try:
with open(START_TIME_FILE, '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_FILE, '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.clear()
lcd.move_to(0, 0)
lcd.putstr("ChacadeiraDe0v0s")
utime.sleep(2)
load_start_time()
pin_heat.value(0)
pin_fan.value(0)
pin_umidificador.value(0)
pin_status_led.value(0)
ultima_virada = utime.ticks_ms()
ultimo_alarme = utime.ticks_ms()
ultimo_update_lcd = utime.ticks_ms()
# --- 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 e atualização do LCD ---
if utime.ticks_diff(tempo_atual, ultimo_update_lcd) >= UPDATE_LCD_INTERVAL:
try:
dht_sensor.measure()
temperatura = dht_sensor.temperature()
umidade = dht_sensor.humidity()
print("Temperature: {:.2f}°C, Humidity: {:.2f}%".format(temperatura, umidade))
# Exibe a temperatura, umidade e dias no LCD
lcd.clear()
lcd.putstr(f"T:{temperatura:.1f}")
lcd.putchar(f"¨")
lcd.putstr(f"C U:{umidade:.1f}%")
dias_passados = utime.ticks_diff(tempo_atual, data_inicio_ms) // 8640 #mudar o valor para 86400000 que é o valor de segundos por hora.
dias_restantes = TEMPO_INCUBACAO_DIAS - dias_passados
if dias_restantes > 0:
lcd.move_to(0, 1)
lcd.putstr(f"Faltam {dias_restantes} dias")
else:
lcd.move_to(0, 1)
lcd.putstr("Eclosao!")
# Lógica de controle de aquecimento e ventilação
if temperatura < TEMP_MIN:
pin_heat.value(1)
else:
pin_heat.value(0)
if temperatura > TEMP_MAX:
pin_fan.value(1)
else:
pin_fan.value(0)
if umidade < UMIDADE_MIN:
pin_umidificador.value(1)
else:
pin_umidificador.value(0)
except (OSError, ValueError) as e:
lcd.clear()
lcd.putstr("Erro no sensor")
print(f"Erro no sensor DHT: {e}")
ultimo_update_lcd = tempo_atual
# --- Lógica de Alarme ---
try:
temperatura = dht_sensor.temperature()
umidade = dht_sensor.humidity()
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:")
lcd.move_to(0, 1)
lcd.putstr("Fora da faixa")
else:
ultimo_alarme = tempo_atual
if alarme_ativado:
stop_alarm()
alarme_ativado = False
pin_status_led.value(0)
except (OSError, ValueError):
pass
# --- Lógica de Alarme de Eclosão ---
dias_passados = utime.ticks_diff(tempo_atual, data_inicio_ms) // 8640 #mudar o valor para 86400000 que é o valor de segundos por hora.
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.move_to(0, 0)
lcd.putstr("Alerta: Eclosao!")
lcd.move_to(0, 1)
lcd.putstr("Faltam poucas horas")
# --- Viragem dos ovos (não bloqueante) ---
if utime.ticks_diff(tempo_atual, ultima_virada) >= INTERVALO_VIRADA:
stepper_motor.step(180)
utime.sleep(5)
# Go to a specific position (angle, maximum is 359, otherwise it will spin indefinetely)
stepper_motor.step(20)
ultima_virada = tempo_atual
# --- Início do programa ---
if __name__ == "__main__":
setup()
main_loop()