################## SISTEMA DE RIEGO CONTROLADO ##################
from machine import Pin, I2C 
import utime
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
from Teclado import Teclado

# Definimos la division de cada seccion considerando 9 plantas y 200 pasos
PASOS_POR_REVOLUCION = 600
secuencia_riego = [1, 2, 3, 4, 5, 6, 7, 8, 9]  # Secuencia

# Definimos las coordenadas de cada sección
COORDENADAS_SECCIONES = [
    (33, 33),    # Posición 1
    (67, 0),    # Posición 2
    (66, 0),    # Posición 3
    (0, 67),    # Posición 4
    (66, 0),    # Posición 5
    (67, 0),    # Posición 6
    (0, 66),    # Posición 7
    (66, 0),    # Posición 8
    (66, 0),    # Posición 9 
]

# LCD display 
I2C_ADDR = 0x27
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16
i2c = I2C(0, sda=machine.Pin(12), scl=machine.Pin(13), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)    
lcd.putstr("  INICIANDO...")
utime.sleep(3)
lcd.clear()

# Configuracion del teclado matricial
teclado = Teclado([8, 9, 10, 11],[20, 21, 22, 26])  

# MOTOR de la Válvula (marrón) [Amarillo]
dir_pin = Pin(18, Pin.OUT)
step_pin = Pin(19, Pin.OUT)
enable_pin = Pin(7, Pin.OUT)

# MOTOR del eje X (naranja) [Verde]
dir_X_pin = Pin(17, Pin.OUT)
step_X_pin = Pin(16, Pin.OUT)
enable_X_pin = Pin(6, Pin.OUT)

# MOTOR del eje Y (celeste) [Rojo]
dir_Y_pin = Pin(15, Pin.OUT)
step_Y_pin = Pin(14, Pin.OUT)
enable_Y_pin = Pin(5, Pin.OUT)

# LEDS
led_rojo = Pin(0, Pin.OUT)
led_verde = Pin(1, Pin.OUT)

# Manejo
cantidad_agua_previa = 0
n = 0

# Seteo de direccion de los pins
dir_Y_pin.value(1)
dir_X_pin.value(1)


# Función para mover el motor del eje X 
def mover_motor_X(posicion):
    direccion_del_motor = 1
    pasos_necesarios = int((posicion / 200) * PASOS_POR_REVOLUCION)

    for i in range(pasos_necesarios):
        step_X_pin.value(1)
        utime.sleep_us(2000)
        step_X_pin.value(0)
        utime.sleep_ms(10)

# Función para mover el motor del eje Y 
def mover_motor_Y(posicion):
    pasos_necesarios = int((posicion / 200) * PASOS_POR_REVOLUCION)

    for i in range(pasos_necesarios):
        step_Y_pin.value(1)
        utime.sleep_us(2000)
        step_Y_pin.value(0)
        utime.sleep_ms(10)

# Función principal para riego automático
def riego_automatico(cantidad_plantas, configuracion_agua, tiempo_entre_riegos):
    # Posición inicial de referencia
    posicion_referencia_X = 0
    posicion_referencia_Y = 0
    dir_pin.value(1)  # Configurar la dirección hacia la derecha (válvula)

    ############# PROCESO DE RIEGO #################
    while True:

        for planta_numero in range(1, cantidad_plantas + 1):
            cantidad_agua = configuracion_agua
            
            # Verifico y establezco el nivel del agua
            if cantidad_agua == 1:
                pasos_valvula = 33
            elif cantidad_agua == 2:
                pasos_valvula = 100
            elif cantidad_agua == 3:
                pasos_valvula = 166

            # Obtener coordenadas de la planta actual
            posicion_X, posicion_Y = COORDENADAS_SECCIONES[planta_numero - 1]

            posicion_referencia_Y += posicion_Y

            # En caso de estar en la zona 5 o 7 invertimos el sentido del motor X
            if planta_numero == 5 or planta_numero == 7:
                dir_X_pin.value(not dir_X_pin.value())  # Cambiar la dirección del motor X
            
            mover_motor_X(posicion_X)
            mover_motor_Y(posicion_Y)

            # Abrir la válvula
            led_rojo.off()
            led_verde.on()
            for i in range(pasos_valvula):
                step_pin.value(1)
                utime.sleep_us(2000)
                step_pin.value(0)
                utime.sleep_ms(10)


            lcd.clear()
            lcd.putstr(f"REGANDO ZONA {planta_numero}")
            utime.sleep(10)

            # Cerrar la válvula
            dir_pin.value(0)  
            led_rojo.on()
            for i in range(pasos_valvula):
                step_pin.value(1)
                utime.sleep_us(2000)
                step_pin.value(0)
                utime.sleep_ms(10)
            led_verde.off()
    
            dir_pin.value(1)

        ####### FINAL DE LA SECUENCIA ########
        # Establecemos los parametros para que los motores vuelvan al valor inicial
        if planta_numero == 1 or planta_numero == 6 or planta_numero == 7:
            posicion_referencia_X = 33
        elif planta_numero == 2 or planta_numero == 5 or planta_numero == 8:
            posicion_referencia_X = 100
        elif planta_numero == 3 or planta_numero == 4 or planta_numero == 9:
            posicion_referencia_X = 166

        # Volvemos a la posición inicial una vez termina todo el proceso
        dir_X_pin.value(0)  
        dir_Y_pin.value(0)  
        mover_motor_X(posicion_referencia_X)
        mover_motor_Y(posicion_referencia_Y)
        dir_X_pin.value(1) 
        dir_Y_pin.value(1)  

        # Establecer una pausa antes del siguiente ciclo
        utime.sleep(tiempo_entre_riegos)


# Función principal para riego controlado
def riego_controlado(cantidad_plantas, configuraciones_plantas):
    # Posición inicial de referencia
    posicion_referencia_X = 0
    posicion_referencia_Y = 0
    dir_pin.value(1)  # Configurar la dirección hacia la derecha (válvula)

    # Bucle para riego inicial (chequeo de configuracion)
    for planta_numero in range(1, int(cantidad_plantas) + 1):
        cantidad_agua = configuraciones_plantas[planta_numero - 1]['cantidad_agua']

        # Verificamos y establecemos los niveles de agua
        if cantidad_agua == "1":
            pasos_valvula = 33
        elif cantidad_agua == "2":
            pasos_valvula = 100
        elif cantidad_agua == "3":
            pasos_valvula = 166

        # Obtener coordenadas de la planta actual
        posicion_X, posicion_Y = COORDENADAS_SECCIONES[planta_numero - 1]

        # En caso de estar en la zona 5 o 7 invertimos el sentido del motor X
        if planta_numero == 5 or planta_numero == 7:
            dir_X_pin.value(not dir_X_pin.value())  # Cambiar la dirección del motor X
            
        # Mover motores a la posición actual
        mover_motor_X(posicion_X)
        mover_motor_Y(posicion_Y)

        posicion_referencia_Y += posicion_Y

        # Abrir la válvula
        for i in range(pasos_valvula):
            step_pin.value(1)
            utime.sleep_us(2000)
            step_pin.value(0)
            utime.sleep_ms(10)

        lcd.clear()
        lcd.putstr(f"REGANDO ZONA {planta_numero}")
        utime.sleep(10)  # Esperar 10 segundos después de abrir la válvula

        # Cerrar la vlvula
        dir_pin.value(0)  # Configurar la dirección hacia la izquierda (válvula)
        for i in range(pasos_valvula):
            step_pin.value(1)
            utime.sleep_us(2000)
            step_pin.value(0)
            utime.sleep_ms(10)

        dir_pin.value(1)

        ####### FINAL DE LA SECUENCIA AUTOMATICA########
        # Al igual que el paso automatico, configuramos el cierre del motor X
        if planta_numero == 1 or planta_numero == 6 or planta_numero == 7:
            posicion_referencia_X = 33
        elif planta_numero == 2 or planta_numero == 5 or planta_numero == 8:
            posicion_referencia_X = 100
        elif planta_numero == 3 or planta_numero == 4 or planta_numero == 9:
            posicion_referencia_X = 166

    # Volver a la posición inicial
    dir_X_pin.value(0)  # Configurar la dirección hacia la izquierda
    dir_Y_pin.value(0)  # Configurar la dirección hacia la izquierda
    mover_motor_X(posicion_referencia_X)
    mover_motor_Y(posicion_referencia_Y)
    dir_X_pin.value(1)  # Configurar la dirección hacia la izquierda
    dir_Y_pin.value(1)  # Configurar la dirección hacia la izquierda

    # Establecer una pausa antes de que el usuario elija una sección
    utime.sleep(2)

    # Bucle en el cual se simula una zona fuera de condiciones normales
    while True:
        lcd.clear()
        lcd.move_to(0, 0)
        lcd.putstr("ELIJA UNA ZONA")
        lcd.move_to(0, 1)
        lcd.putstr("(ENTRE 1 Y 9): ")
        seccion_elegida = teclado.ingresar_valor(['1', '2', '3', '4', '5', '6', '7', '8', '9'])

        # Posición inicial de referencia
        posicion_referencia_X = 0
        posicion_referencia_Y = 0
        dir_pin.value(1)  # Configurar la dirección hacia la derecha (válvula)

        # Si la zona es valida va a la zona elegida, y la riega 
        # (Simulado que seria reemplazada con sensores)
        if 1 <= int(seccion_elegida) <= int(cantidad_plantas):
            # Bucle para riego inicial
            for planta_numero in range(1, int(seccion_elegida) + 1):
                # Buscamos la configuracion de esa zona
                cantidad_agua = configuraciones_plantas[planta_numero - 1]['cantidad_agua']

                # En base a la configuracion nos posicionamos y regamos
                if cantidad_agua == "1":
                    pasos_valvula = 33
                elif cantidad_agua == "2":
                    pasos_valvula = 100
                elif cantidad_agua == "3":
                    pasos_valvula = 166

                # Obtener coordenadas de la planta actual
                posicion_X, posicion_Y = COORDENADAS_SECCIONES[planta_numero - 1]


                # En caso de estar en la zona 5 o 7 invertimos el sentido del motor X
                if planta_numero == 5 or planta_numero == 7:
                    dir_X_pin.value(not dir_X_pin.value())  # Cambiar la dirección del motor X
            
                # Mover motores a la posición actual
                mover_motor_X(posicion_X)
                mover_motor_Y(posicion_Y)

                posicion_referencia_Y += posicion_Y

                
            # Abrir la válvula
            for i in range(pasos_valvula):
                step_pin.value(1)
                utime.sleep_us(2000)
                step_pin.value(0)
                utime.sleep_ms(10)

            lcd.clear()
            lcd.putstr(f"REGANDO ZONA {planta_numero}")
            utime.sleep(1)  # Esperar 10 segundos después de abrir la válvula

            # Cerrar la válvula
            dir_pin.value(0)  
            for i in range(pasos_valvula):
                step_pin.value(1)
                utime.sleep_us(2000)
                step_pin.value(0)
                utime.sleep_ms(10)

            dir_pin.value(1)
            utime.sleep(1)
            
            ####### FINAL DE LA SECUENCIA AUTOMATICA########
            if planta_numero == 1 or planta_numero == 6 or planta_numero == 7:
                posicion_referencia_X = 33
            elif planta_numero == 2 or planta_numero == 5 or planta_numero == 8:
                posicion_referencia_X = 100
            elif planta_numero == 3 or planta_numero == 4 or planta_numero == 9:
                posicion_referencia_X = 166

        else:
            # Marcar error si la sección elegida está fuera de rango
            lcd.clear()
            lcd.move_to(0, 0)
            lcd.putstr("ERROR, OPCÍON")
            lcd.move_to(0, 1)
            lcd.putstr("NO VÁLIDA")
            utime.sleep(3)

        # Volver a la posición inicial
        dir_X_pin.value(0)  
        dir_Y_pin.value(0)  
        mover_motor_X(posicion_referencia_X)
        mover_motor_Y(posicion_referencia_Y)
        dir_X_pin.value(1)  
        dir_Y_pin.value(1) 

        # Establecer una pausa antes de que el usuario elija otra sección
        utime.sleep(3)

# Configuración inicial
configuraciones_plantas = []  

while True:
    
    # Seleccion del tipo de riego
    lcd.putstr("SELECCIONE TIPO")
    lcd.move_to(0,1)
    lcd.putstr("DE RIEGO")
    utime.sleep(2)
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("1) AUTOMATICO")
    lcd.move_to(0,1)
    lcd.putstr("2) CONTROLADO")
    tipo_de_riego = teclado.ingresar_opcion(['1', '2'])

    # Datos para establecer el riego automatico
    if tipo_de_riego == "1":
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("CANT DE PLANTAS: ")
        cantidad_plantas_auto = teclado.ingresar_valor_2(['1','2','3','4','5','6','7','8','9'])
        utime.sleep(0.5)
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("CANT DE AGUA: ")
        lcd.move_to(0,1)
        configuracion_agua_auto = teclado.ingresar_valor_2(['1','2','3'])
        utime.sleep(0.5)
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("TIEMPO (EN SEG):")
        lcd.move_to(0,1)
        tiempo_entre_riegos_auto = int(teclado.ingresar_valor_grande(range(0, 1001)))
        utime.sleep(0.5)
        lcd.clear()
        lcd.putstr('CONFIGURANDO...')
        riego_automatico(int(cantidad_plantas_auto), int(configuracion_agua_auto), int(tiempo_entre_riegos_auto))

    # Datos para establecer el riego Controlado
    elif tipo_de_riego == "2": 
        # Configuración inicial
        while True:

            lcd.clear()
            lcd.move_to(0,0)
            lcd.putstr("CANT DE PLANTAS:")
            lcd.move_to(0,1)
            cantidad_plantas = teclado.ingresar_valor_2(['1','2','3','4','5','6','7','8','9'])
            utime.sleep(1)
            lcd.clear()
            if 1 <= int(cantidad_plantas) <= 9:
                break
            else:
                lcd.move_to(0,0)
                lcd.putstr("ERROR, OPCION")
                lcd.move_to(0,1)
                lcd.putstr("NO VÁLIDA")
                utime.sleep(3)

        configuraciones_plantas = []

        for planta in range(int(cantidad_plantas)):

            lcd.clear()
            lcd.move_to(0,0)
            lcd.putstr("CANT DE AGUA ")
            lcd.move_to(0,1)
            lcd.putstr(f"PLANTA {planta + 1}: ")
            cantidad_agua = (teclado.ingresar_valor(['1','2','3']))
            lcd.clear()
            lcd.move_to(0,0)
            lcd.putstr("UMBRAL: ")
            lcd.move_to(0,1)
            lcd.putstr(f"PLANTA {planta + 1}: ")
            temperatura= int(teclado.ingresar_valor_grande(range(0, 101)))
            lcd.clear()
            configuraciones_plantas.append({
                'cantidad_agua': cantidad_agua,
                'umbral': temperatura
            })
    # Para mostrar la configuracion
    print(configuraciones_plantas)

    # Posición inicial de referencia
    posicion_referencia_X = 0
    posicion_referencia_Y = 0
    dir_pin.value(1)  

    # Ejecucion del programa
    while True:
        lcd.clear()
        lcd.putstr('INICIANDO ...')
        utime.sleep(3)
        if tipo_de_riego == "1":
            riego_automatico(cantidad_agua, tiempo_entre_riegos)

        elif tipo_de_riego == "2":
            riego_controlado(cantidad_plantas, configuraciones_plantas)
A4988
A4988
A4988