from machine import Pin, PWM, ADC
from dht import DHT22
import time
#pinagem do pushButton
btn_modo = Pin(32, Pin.IN, Pin.PULL_UP)
#pinagem do led rgb
led_r = Pin(19, Pin.OUT)
led_g = Pin(5, Pin.OUT)
led_b = Pin(16, Pin.OUT)
#valvula de irrigacao (servomotor) (PWM 50Hz, ~0.5ms a ~2.4ms)
servo = Pin(2, Pin.OUT)
servo_valvula = PWM(servo, freq=50) #frequencia 50hz / 20ms
#reservatorio (potenciometro) (ADC 12bits, 0 a 4095)
pot_reservatorio = ADC(Pin(34))
pot_reservatorio.atten(ADC.ATTN_11DB) #permite a leitura completa até 3.3V
#sensor dht22 (umidade/temperatura)
sensor_dht = DHT22(Pin(14))
#variaveis de controle
tempo_inicio = time.ticks_ms()
clique_salvo = tempo_inicio
modo_ativo = 1
angulo_atual_servo = -1 #forca a vazao a zero
intervalo_leitura = tempo_inicio #intervalo leitura de 2seg
#variaveis do sensor dht22 (umidade/temperatura)
umidade_ar = 0.0
temp_ar = 0.0
UMIDADE_SECA = 60.0 # % de umidade limite
#variaveis de irrigacao automatica por tempo (servomotor)
ultima_irrigacao = tempo_inicio
intervalo_irrigacao = 0
status_irrigacao = False
inicio_rega = 0
duracao_rega = 0
angulo_modo = 0
#variaveis de monitoramento do reservatorio (potenciometro)
alerta_reservatorio = False #Flag do sistema em alerta
porcentagem_nivel = 0.0
ultimo_pisca = tempo_inicio
led_alerta = False
#funcao - define as cores do led rgb
def definir_cor_rgb(r, g, b):
led_r.value(r)
led_g.value(g)
led_b.value(b)
#funcao - define o modo de funcionamento
def atualizar_modo(modo):
if modo == 1:
#categoria 1: Standby / Desligado -> LED Apagado
definir_cor_rgb(0, 0, 0)
print("[MODO 1] Sistema em Standby / Irrigação Pausada")
if modo == 2:
#categoria 2: Standby / Desligado -> LED Apagado
definir_cor_rgb(0, 1, 0)
print("[MODO 2] Categoria Selecionada: Hortaliças / Ervas")
if modo == 3:
#categoria 3: Standby / Desligado -> LED Apagado
definir_cor_rgb(1, 1, 0)
print("[MODO 3] Categoria Selecionada: Plantas Tropicais")
if modo == 4:
#categoria 4: Standby / Desligado -> LED Apagado
definir_cor_rgb(1, 0, 0)
print("[MODO 4] Categoria Selecionada: Suculentas / Cactos")
#funcao - define a posicao atual da valvula (servomotor)
def posicionar_servo(angulo):
"""
Controla o ângulo do servomotor (0° a 180°).
0° = Válvula Fechada | 90° = Válvula Aberta
"""
global angulo_atual_servo
if angulo != angulo_atual_servo:
#mapeamento do angulo para nanosegundos no PWM (0.5ms, 1.45ms, 2.4ms)
nanosegundos = int(500000 + (angulo / 180) * 1900000)
servo_valvula.duty_ns(nanosegundos)
angulo_atual_servo = angulo
#funcao - define o intervalo, duracao, intervalo da irrigacao (servomotor)
def configurar_irrigacao(i, d, a):
global intervalo_irrigacao, duracao_rega, angulo_modo
intervalo_irrigacao = i
duracao_rega = d
angulo_modo = a
#funcao - define o intervalo, duracao, intervalo da valvula (servomotor)
def irrigar_automatico(modo, tempo_atual):
global ultima_irrigacao, inicio_rega, status_irrigacao
#configuracao tempo e intervalo irrigacao
if modo == 2: #2: Hortaliças / Ervas
configurar_irrigacao(5000, 8000, 90)
elif modo == 3: #3: Plantas Tropicais
configurar_irrigacao(10000, 4000, 60)
elif modo == 4: #4: Suculentas / Cactos
configurar_irrigacao(15000, 2000, 30)
precisa_irrigar = umidade_ar < UMIDADE_SECA
#inicializacao da rega
if not status_irrigacao:
if time.ticks_diff(tempo_atual, ultima_irrigacao) >= intervalo_irrigacao:
#condicao - umidade abaixo de 60%
if precisa_irrigar:
posicionar_servo(angulo_modo) #abre a valvula no angulo do modo selecionado
status_irrigacao = True
inicio_rega = tempo_atual
#print(f"\n>>> INICIANDO IRRIGAÇÃO (Modo {modo_ativo} | Solo Seco: {umidade_ar:.0f}%) <<<")
else:
#condicao - umidade acima de 60%
ultima_irrigacao = tempo_atual
print(f"\n[INFO] Ciclo verificado: Solo úmido ({umidade_ar:.0f}%). Rega dispensada.")
#finalizacao da rega
if status_irrigacao:
if time.ticks_diff(tempo_atual, inicio_rega) >= duracao_rega:
posicionar_servo(0) #fecha a valvula no angulo zero
status_irrigacao = False
ultima_irrigacao = tempo_atual #reset do timer do intervalo
print(f"\n>>> IRRIGAÇÃO CONCLUÍDA (Válvula Fechada) <<<\n")
#leitura DHT22 (cada 2seg)
def medir_atmosfera(tempo_atual):
global intervalo_leitura, umidade_ar, temp_ar
if time.ticks_diff(tempo_atual, intervalo_leitura) >= 2000:
try:
sensor_dht.measure()
umidade_ar = sensor_dht.humidity()
temp_ar = sensor_dht.temperature()
except OSError:
pass #evita travamento em caso de falha pontual de leitura da onda PWM/DHT
intervalo_leitura = tempo_atual
#monitoramento do reservatorio (potenciometro)
def monitorar_reservatorio():
leitura_nivel = pot_reservatorio.read()
return (leitura_nivel / 4095) * 100 #retorna a porcentagem
#protecao do nivel do reservatorio (potenciometro)
def proteger_reservatorio(tempo_atual):
global porcentagem_nivel, status_irrigacao, alerta_reservatorio, ultimo_pisca, led_alerta
#chamada da funcao monitorar_reservatorio()
porcentagem_nivel = monitorar_reservatorio()
if porcentagem_nivel < 15:
#se reservatorio < 15% - fecha a valvula, aciona pisca-alerta
posicionar_servo(0)
status_irrigacao = False #cancela a irrigacao
alerta_reservatorio = True #sistema entra em alerta
print(f"ALERTA: Reservatório Crítico ({porcentagem_nivel:.0f}%)! Reabasteça.", end="\r")
#alerta do nivel do reservatorio
if time.ticks_diff(tempo_atual, ultimo_pisca) >= 500:
led_alerta = not led_alerta
if led_alerta:
definir_cor_rgb(0, 0, 1)
else:
definir_cor_rgb(0, 0, 0)
ultimo_pisca = tempo_atual
else:
#se reservatorio > 15% : reabastecimento
if alerta_reservatorio:
atualizar_modo(modo_ativo)
alerta_reservatorio = False
#rotina de inicialização
posicionar_servo(0) #garante valvula fechada na partida
#acende o led rgb em Azul (1seg)
definir_cor_rgb(0, 0, 1)
time.sleep(1.0)
#modo ativo padrao
atualizar_modo(modo_ativo)
print("--- Inicialização concluída ---\n")
#loop principal
while True:
#atualiza o tempo_atual com o tempo decorrido
tempo_atual = time.ticks_ms()
#medicao da umidade e temperatura
medir_atmosfera(tempo_atual)
#protecao do reservatorio
proteger_reservatorio(tempo_atual)
#se o sistema entrar em alerta, ignora o resto do codigo
if alerta_reservatorio:
time.sleep_ms(10)
continue
#verifica se o pushButton foi pressionado (NO == 1)
if btn_modo.value() == 0:
if time.ticks_diff(tempo_atual, clique_salvo) >= 300:
modo_ativo += 1
if modo_ativo > 4:
modo_ativo = 1
atualizar_modo(modo_ativo)
clique_salvo = tempo_atual
intervalo_leitura = tempo_atual #reinicia o intervalo_leitura (2seg)
#Se trocar de modo no meio de uma rega, fecha a válvula por segurança
status_irrigacao = False
posicionar_servo(0)
#irrigacao automatica por tempo (servomotor)
if modo_ativo != 1: #impede irrigacao no Standby
irrigar_automatico(modo_ativo, tempo_atual)
#simulacao visual da irrigacao automatica / teste no terminal
print(f"push: {btn_modo.value()} | modo: {modo_ativo}", end="\r")
# Alívio de processamento para a CPU
time.sleep_ms(10)