#Proyecto_Progra4_Alejandra_Garro_M CU 05
#Automatización de mini invernadero

from machine import Pin, I2C, ADC #se importan clases para control de pines
import dht # Importar módulo para el sensor DHT22, mide temperatura y humedad
import ssd1306 # Importar módulo para la pantalla OLED
from hcsr04 import HCSR04 #importar módulo para sensor ultrasónico (mide distancia)
from time import sleep # Importar función para introducir pausas de tiempo
from servo import Servo #importar clase para controlar servo motor
from neopixel import NeoPixel #Importar clase para control de LEDs NeoPixel

#se define la clase para controlar los sensores
class SensorController:
    def __init__(self):
        # Inicializar componentes y pines
        self.dht_sensor = dht.DHT22(Pin(15)) #Se inicializa sensor DHT22 en el pin 15
        self.ultrasonic_sensor = HCSR04(trigger_pin=2, echo_pin=4, echo_timeout_us=10000) #Configura sensor ultrasónico
        self.servo = Servo(Pin(14))  #Se inicializa el servo motor en el pin 14
        self.pot_pin = Pin(27)  #Configurar el pin para el potenciómetro como entrada
        self.adc = ADC(self.pot_pin)  # Configurar el conversor analógico-digital (ADC)
        self.button = Pin(5, Pin.IN, Pin.PULL_UP)  # Configurar el pin para el botón como entrada
        self.neopixel_pin = Pin(12)  # Configurar el pin para los NeoPixels
        self.num_pixels = 16  # Número de LEDs NeoPixel
        self.neopixels = NeoPixel(self.neopixel_pin, self.num_pixels)  # Inicializar NeoPixels

    #función para medir temperatura y humedad
    def measure_temperature_humidity(self):
        try:
            self.dht_sensor.measure() #Realiza la medición de temperatura y humedad
            return self.dht_sensor.temperature(), self.dht_sensor.humidity() #Devolver los valores medidos

        except Exception as e:
            print('ERROR obteniendo temperatura y humedad:', e) #Imprimir el error
            return None, None #Devolver valores nulos en caso de error

    #función para medir distancia
    def measure_distance(self):
        try:
            distance = self.ultrasonic_sensor.distance_cm() #Medir la distancia en centímetros
            return distance
        except OSError as ex:
            print('ERROR obteniendo distancia:', ex) #Manejo de error en caso de problema con el sensor
            return None

    #Función para controlar el servo motor
    def control_servo(self):
        self.servo.write_angle(15) #Mover el servo a 15 grados
        sleep(2)  # Pausa de 2 segundos
        self.servo.write_angle(165) #Mover el servo a 165 grados
        sleep(2)  # Pausa de 2 segundos
        self.servo.write_angle(90) #Mover el servo a 90 grados (posición neutral)
        sleep(2)  # Pausa de 2 segundos

    #Función para leer el valor del potenciómetro
    def read_potentiometer(self):
        pot_value = self.adc.read() #Leer el valor analógico del potenciómetro
        return pot_value

    #Función para detectar el estado del botón
    def detect_button(self):
        button_state = self.button.value() #Leer el estado del botón (0 si está presionado, 1 si no lo está)
        return not button_state #Devolver True si el botón está presionado, False si no


    #clase para controlar la pantalla y los LEDs
class DisplayController:
    def __init__(self):
        #Inicializar la comunicación I2C y los componentes relacionados
        self.i2c = I2C(0, scl=Pin(22), sda=Pin(21)) #Configurar la comunicación I2C
        self.display = ssd1306.SSD1306_I2C(128, 64, self.i2c)  #Configurar la pantalla OLED
        self.neo_pixel = NeoPixel(Pin(12), 16) #Configurar los LEDs NeoPixel

    #Función para cambiar los colores de los LEDs NeoPixel
    def change_neo_pixel_colors(self):
        for _ in range(5):  #Repetir el patrón de parpadeo 5 veces
            for x in range(0, 16, 2): #Cambiar solo los índices pares (verde)
                self.neo_pixel[x] = (0,255,0)  #verde
            self.neo_pixel.write() #Actualizar los LEDs NeoPixel
            sleep(0.5)  # Pausa de 0.5 segundos

            for x in range(0, 16, 2): #Apagar los índices pares
                self.neo_pixel[x] = (0, 0, 0) #Apagar LED NeoPixel
            self.neo_pixel.write() #Actualizar los LEDs NeoPixel
            sleep(0.5) #Pausa de 0.5 segundos

            for x in range(1, 16, 2): #Cambiar solo los índices impares (rojos)
                self.neo_pixel[x] = (255,0,0)  #rojos
            self.neo_pixel.write()  # Actualizar los LEDs NeoPixel
            sleep(0.5)  # Pausa de 0.5 segundos

            for x in range(1, 16, 2):  # Apagar los índices impares
                self.neo_pixel[x] = (0, 0, 0)  # Apagar LED NeoPixel
            self.neo_pixel.write()  # Actualizar los LEDs NeoPixel
            sleep(0.5)  # Pausa de 0.5 segundos

    #Función para mostrar valores en la pantalla OLED
    def show_on_display(self, value1, value2):
        try:
            self.display.fill(0)  #Limpiar pantalla OLED
            self.display.text(str(value1), 20, 20)  # Mostrar el primer valor en la posición (20, 20)
            self.display.text(str(value2), 20, 40)  # Mostrar el segundo valor en la posición (20, 40)
            self.display.show()  # Actualizar la pantalla OLED
        except Exception as e:
            print('ERROR mostrando en pantalla OLED:', e)  # Imprimir el error

   

#Función principal o main
def main():
    #Se crean instancias de las clases para controlar sensores y pantalla
    sensor_controller = SensorController()
    display_controller = DisplayController()

    while True:
        # Medir temperatura y humedad
        temperature, humidity = sensor_controller.measure_temperature_humidity()
        print('Temperatura:', temperature, '°C')
        print('Humedad:', humidity, '%')
        sleep(0.5)  #Pausa de 0.5 segundos

        #Cambiar los colores de los LEDs NeoPixel
        display_controller.change_neo_pixel_colors()

        # Mostrar valores en la pantalla OLED
        display_controller.show_on_display(temperature, humidity)
        sleep(0.5)  #Pausa de 0.5 segundos

        # Medir distancia y controlar el servo motor
        distance = sensor_controller.measure_distance()
        if distance is not None:
            print('Distancia:', distance, 'cm')
        sleep(1)  #Pausa de 1 segundo
        sensor_controller.control_servo()

        # Leer el valor del potenciómetro
        pot_value = sensor_controller.read_potentiometer()
        print('Valor del potenciómetro:', pot_value)
        sleep(0.1)  #Pausa de 0.1 segundos

        # Detectar el estado del botón
        button_pressed = sensor_controller.detect_button()
        if button_pressed:
            print('Botón pulsado')
        else:
            print('Botón no pulsado')
        sleep(0.1)  # Pausa de 0.1 segundos

# Iniciar el programa si se ejecuta como script principal
if __name__ == "__main__":
    main()
$abcdeabcde151015202530fghijfghij