from machine import Pin, I2C,PWM,ADC
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
from dht import DHT22
from hcsr04 import HCSR04 # Aggiunto import HCSR04
import random
import time
# Setup componenti
i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
lcd = I2cLcd(i2c, 0x27, 2, 16)
# Aggiunto setup DHT11/22
dht = DHT22(Pin(16)) # DHT11 su GPIO16
# Aggiunto setup sensore ultrasuoni (trigger=Pin 22, echo=Pin 21)
sonar = HCSR04(trigger_pin=22, echo_pin=21)
# Aggiunto setup LED
led_allarme = Pin(15, Pin.OUT) # LED su GPIO15
SOGLIA_TEMPERATURA = 28 # Soglia in gradi Celsius
# Aggiunto setup buzzer
buzzer = PWM(Pin(6)) # Buzzer su GPIO6
buzzer.duty_u16(0) # Spento inizialmente
# Aggiunto setup potenziometro
pot = ADC(26) # Potenziometro su GPIO26 (ADC0)
# Configurazione range temperatura
TEMP_MIN = 25 # Temperatura minima impostabile
TEMP_MAX = 35 # Temperatura massima impostabile
# Aggiunto setup PIR
pir = Pin(14, Pin.IN) # Sensore PIR su GPIO14
movimento_rilevato = False
ultimo_movimento = 0
# Aggiunto setup LED movimento
led_movimento = Pin(13, Pin.OUT) # Nuovo LED su GPIO13
# Aggiunto setup servo
servo = PWM(Pin(12)) # Servo su GPIO12
servo.freq(50) # Frequenza standard per servo (50Hz)
# Costanti per il servo
ANGOLO_MIN = 0
ANGOLO_MAX = 90
SOGLIA_DISTANZA = 30 # Soglia in cm
def inizializza_display():
# Pulisci il display
lcd.clear()
# Mostra il titolo sulla prima riga
lcd.move_to(0, 0)
lcd.putstr("Monitor Ambiente")
# Mostra il messaggio di inizializzazione sulla seconda riga
lcd.move_to(0, 1)
lcd.putstr("Inizializzazione")
time.sleep(1)
lcd.clear()
# Aggiunge punti di sospensione animati
for _ in range(3):
lcd.putstr(".")
time.sleep(0.5)
print("Display inizializzato con successo!")
# Nuova funzione per leggere DHT11
def leggi_temperatura_umidita():
dht.measure()
return dht.temperature(), dht.humidity()
def controlla_temperatura(temperatura):
soglia = leggi_soglia_temperatura()
if temperatura > soglia:
led_allarme.value(1)
suona_allarme()
return True
else:
led_allarme.value(0)
buzzer.duty_u16(0)
return False
# Nuova funzione per mostrare i dati
def mostra_dati_ambiente():
temp, umid = leggi_temperatura_umidita()
if temp is not None and umid is not None:
soglia = leggi_soglia_temperatura()
allarme = controlla_temperatura(temp)
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr(f"T:{temp}C S:{soglia}C") # Mostra temperatura e soglia
lcd.move_to(0, 1)
lcd.putstr(f"Umid:{umid}%")
if allarme:
lcd.move_to(15, 0)
lcd.putstr("!")
else:
lcd.clear()
lcd.putstr("Errore Sensore")
led_allarme.value(0)
# Nuova funzione per leggere la distanza
def leggi_distanza():
distanza = sonar.measure_distance_cm()
return round(distanza, 1) # Arrotonda a 1 decimale
def imposta_angolo_servo(angolo):
"""Imposta l'angolo del servo (0-180 gradi)"""
# Converti angolo in duty cycle (0.5ms - 2.5ms)
duty = int(((angolo / 180) * (8200 - 1700) + 1700))
servo.duty_u16(duty)
def controlla_distanza_servo():
"""Controlla la distanza e muove il servo di conseguenza"""
distanza = leggi_distanza()
if distanza is not None:
if distanza < SOGLIA_DISTANZA:
# Movimento di avviso
for _ in range(2): # Oscilla due volte
imposta_angolo_servo(ANGOLO_MAX)
time.sleep(0.5)
imposta_angolo_servo(ANGOLO_MIN)
time.sleep(0.5)
# Suona allarme
buzzer.freq(1500)
buzzer.duty_u16(32768)
time.sleep(0.2)
buzzer.duty_u16(0)
else:
# Riporta il servo alla posizione iniziale
imposta_angolo_servo(ANGOLO_MIN)
def mostra_distanza():
distanza = leggi_distanza()
if distanza is not None:
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr(f"Distanza:")
lcd.move_to(0, 1)
lcd.putstr(f"{distanza} cm")
# Aggiungi controllo servo
controlla_distanza_servo()
else:
lcd.clear()
lcd.putstr("Errore Sonar")
imposta_angolo_servo(ANGOLO_MIN) # Posizione di sicurezza
def suona_allarme():
buzzer.freq(1000) # Frequenza 1kHz
buzzer.duty_u16(32768) # Volume al 50%
time.sleep(0.2) # Suona per 0.2 secondi
buzzer.duty_u16(0) # Spegne il buzzer
time.sleep(0.2) # Pausa di 0.2 secondi
def leggi_soglia_temperatura():
"""Legge il potenziometro e converte il valore in temperatura"""
val = pot.read_u16() # Legge valore (0-65535)
# Mappa il valore del potenziometro al range di temperatura
temperatura = TEMP_MIN + (val / 65535) * (TEMP_MAX - TEMP_MIN)
return round(temperatura, 1)
def mostra_soglia():
"""Mostra la soglia di temperatura corrente"""
soglia = leggi_soglia_temperatura()
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("Soglia Temp:")
lcd.move_to(0, 1)
lcd.putstr(f"{soglia}C")
return soglia
def lampeggia_led_movimento():
"""Fa lampeggiare il LED di movimento rapidamente"""
for _ in range(5): # Lampeggia 5 volte
led_movimento.value(1)
time.sleep(0.1)
led_movimento.value(0)
time.sleep(0.1)
def rileva_movimento():
"""Controlla se è stato rilevato movimento"""
global movimento_rilevato, ultimo_movimento
if pir.value() == 1: # Movimento rilevato
if not movimento_rilevato or (time.time() - ultimo_movimento) > 5:
movimento_rilevato = True
ultimo_movimento = time.time()
mostra_movimento()
lampeggia_led_movimento() # Aggiunta segnalazione LED
return True
else:
movimento_rilevato = False
led_movimento.value(0) # Assicura che il LED sia spento
return False
def mostra_movimento():
"""Visualizza il messaggio di movimento rilevato"""
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("Movimento")
lcd.move_to(0, 1)
lcd.putstr("Rilevato!")
# Attiva buzzer e LED per segnalazione
buzzer.freq(2000)
buzzer.duty_u16(32768)
led_movimento.value(1) # Accende il LED
time.sleep(0.1)
buzzer.duty_u16(0)
# Inizializzazione
inizializza_display()
led_allarme.value(0)
led_movimento.value(0)
buzzer.duty_u16(0)
imposta_angolo_servo(ANGOLO_MIN) # Posizione iniziale servo
# Loop principale modificato
while True:
if rileva_movimento():
time.sleep(1)
else:
mostra_dati_ambiente()
time.sleep(2)
mostra_distanza() # Include ora il controllo del servo
time.sleep(2)