//Inclusión de librerías//
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include<Keypad.h>

//Variables de funcionamiento; Inicializadas en Cero//
int velocidad = 0;
int minutos = 0;
int segundos = 0;

//Coeficientes del polinomio, ordenados en orden creciente al grado//
const float f [6] = {37.7840628546,-0.6763407155, 0.0085925358,-0.0000430185030344714,
0.0000000968984079403198,-0.0000000000747251447228472};

//Pines utilizados por el L298N//
int IN1 = 11; // Input1 conectada al pin 12
int IN2 = 12; // Input2 conectada al pin 11
int ENA = 10; // ENA conectada al pin 10 de Arduino

//Constantes útiles//
const int mm = 30; //minutos máximos de la máquina//
const int vv= 400; //velocidad máximo de la máquina//
const int ss= 59; //segundo máximos de la máquina//
const int vm= 50; //velocidad mínima de la máquina//

const int tl= 2000; //tiempo de lectura estándar//

const int v = 300; //velocidad programa estándar//
const int m = 2; //minutos programa estándar//
const int s = 0; //segundos programa estándar//

//Variables auxiliares//
int aux= 1; //auxiliar para poner en marcha funcionamiento//
int num= 0; //auxiliar para tomar números de teclado//
char tecla; //auxiliar para tomar carácter de teclado//

//Declaración de variables keypad//
const byte filas = 4; //4 filas//
const byte columnas = 4; //4 columnas//
byte pinesF [filas] = {9, 8, 7, 6}; //Definimos los pines a los que estarán conectadas las filas de nuestra matriz==“pinesF”//
byte pinesC [columnas] = {5, 4, 3, 2}; //Definimos los pines a los que estarán conectadas las columnas de nuestra matriz== “pinesC”//
char teclas [filas] [columnas] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};

//Ahora declaramos las teclas que conforman nuestra matriz, EN ORDEN//
Keypad teclado =Keypad (makeKeymap (teclas), pinesF, pinesC, filas, columnas);
//Esta instrucción sirve para realizar el mapeo de nuestro teclado matricial//

//Declaración de conjunto DISPLAY LCD//
LiquidCrystal_I2C lcd (0x27, 20, 4);

void setup () {
 //Declaración de variables que serán pines de salida//
 pinMode (ENA, OUTPUT);
 pinMode (IN1, OUTPUT);
 pinMode (IN2, OUTPUT);
 lcd.init();
 lcd.init();// Inicializar el LCD.//
 lcd.backlight();//Encender la luz de fondo.//
 lcd.clear();//Borra la pantalla LCD y posiciona el cursor en la esquina superior izquierda (posición (0,0)).//
}

void loop(){
 lcd.setCursor(0, 0);
 lcd.print("Para comenzar: '#' ");
 leer();
 aux= 1;
 if (tecla=='#') {
  aux= 0;
  lcd.clear();
  while (aux == 0) {
   lcd.setCursor(0, 0);
   lcd.print("A:Velocidad: ");
   lcd.print(velocidad);
   lcd.setCursor(17, 0);
   lcd.print("rpm");
   lcd.setCursor(0, 1);
   lcd.print("B:Minutos: ");
   lcd.print(minutos);
   lcd.setCursor(17, 1);
   lcd.print("min");
   lcd.setCursor(0, 2);
   lcd.print("C:Segundos: ");
   lcd.print(segundos);
   lcd.setCursor(17, 2);
   lcd.print("seg");
   lcd.setCursor(0, 3);
   lcd.print("D:Programa/ *:inicio");
   leer();
   if (tecla!= 0) {
    lcd.clear();
    switch (tecla) {
     case'A':
      tomarVel();
      lcd.clear();
      break;
     case'B':
      tomarMin();
      lcd.clear();
      break;
     case'C':
      tomarSeg();
      lcd.clear();
      break;
     case'D':
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.println("Por defecto + inicio");
      velocidad= v; //Valores x defecto//
      lcd.setCursor(0, 1);
      lcd.print(" Velocidad: ");
      lcd.print(velocidad);
      minutos= m;
      lcd.setCursor(0, 2);
      lcd.print(" Minutos: ");
      lcd.print(minutos);
      segundos= s;
      lcd.setCursor(0, 3);
      lcd.print(" Segundos: ");
      lcd.print(segundos);
      delay(2 *tl);
      break;
      default: {
        if (num< 10 ||tecla=='#') {
         lcd.clear();
         lcd.print("--Tecla no valida--");
         delay(tl);
         lcd.clear();
        }
      }
     }
   }
   if (tecla=='*'||tecla=='D') {
   aux= 1;
    delay(tl);
   }//fin if de salida//
  }
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("-FIN CARGA DE DATOS-");
  delay(tl);
  if (velocidad != 0) {
   if ((minutos != 0 || segundos != 0)) {
     funcionar();
   }
   else {
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print(" VELOCIDAD /=0 ");
    lcd.setCursor(0, 1);
    lcd.print("   v: ");
    lcd.print(velocidad);
    lcd.setCursor(0, 2);
    lcd.print(" TIEMPO NULO ");
    lcd.setCursor(0, 3);
    lcd.print(" VUELVA A INGRESAR ");
    delay(tl);
    lcd.clear();
    }
  }
  else {
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print(" VELOCIDAD NULA ");
   lcd.setCursor(0, 2);
   lcd.print(" VUELVA A INGRESAR ");
   delay(tl);
   lcd.clear();
  }
 }
 else {
  if (tecla!=0) {
  lcd.clear();
  lcd.print("Error, no eligio #");
  delay(tl/ 2);
  }
 }
}//FIN LOOP//

//**********************************************//

void leer() {
  tecla= 0;
  num= 0;
  tecla=teclado.getKey();
  switch (tecla) {
   case'1':num= 1; break;
   case'2':num= 2; break;
   case'3':num= 3; break;
   case'4':num= 4; break;
   case'5':num= 5; break;
   case'6':num= 6; break;
   case'7':num= 7; break;
   case'8':num= 8; break;
   case'9':num= 9; break;
   case'0':num= 0; break;
   default:num= 99;
  }
}//Fin leer//

//**********************************************//

void tomarVel() {
  tecla= 0;
  num= 0;
  velocidad= 0;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(" Indique velocidad ");
  lcd.setCursor(0, 1);
  lcd.print("Entre ");
  lcd.print(vm);
  lcd.print(" y ");
  lcd.print(vv);
  lcd.print("   rpm. ");
  lcd.setCursor(0, 3);
  lcd.print("Para terminar #");
  for (int i= 0; i<3; i++) {
   int j = 0; //variable de corte ante lectura de errores//
   while (j == 0) {
    leer();
    if (tecla!=0) {
      if (num< 10) {
       j = 1;
       velocidad= velocidad * 10 +num;
       lcd.setCursor(0, 2);
       lcd.print("V:");
       lcd.setCursor(i+ 4, 2);
       lcd.print(num);
       lcd.print("   rpm.");
       delay(tl/ 2);
      }
      else {
       if (tecla=='#') {
        j= 1;
        i= 3;
        num= 0;
       }
       else {
        
       }
      }
    }
   }
  }
  delay(tl);
}
//Fin tomar velocidad//

//**********************************************//

void tomarMin() {
 minutos= 0;
 tecla= 0;
 num= 0;
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(" Indique minutos ");
 lcd.setCursor(0, 1);
 lcd.print("Menor a ");
 lcd.print(mm);
 lcd.print(" min. ");
 lcd.setCursor(0, 3);
 lcd.print("Para terminar #");
 for (int i= 0; i< 2; i++) {
  int j = 0; //variable de corte ante lecturaerrores//
  while (j == 0) {
   leer();
   if (tecla!=0) {
     if (num< 10) {
      j = 1;
      minutos= minutos * 10 +num;
      lcd.setCursor(0, 2);
      lcd.print("M: ");
      lcd.setCursor(i+ 4, 2);
      lcd.print(num);
      lcd.print(" minutos.");
      delay(tl/ 20);
     }
     else {
      if (tecla=='#') {
       j = 1;
       i= 3;
       num= 0;
      }
      else {
      }
     }
   }
  }
 }
 delay(tl);
}
//Fin tomar minutos//

//**********************************************//

void tomarSeg() {
  segundos= 0;
  tecla= 0;
  num= 0;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(" Indique segundos ");
  lcd.setCursor(0, 1);
  lcd.print("Menor a ");
  lcd.print(ss);
  lcd.print(" seg. ");
  lcd.setCursor(0, 3);
  lcd.print("Para terminar #");
  for (int i= 0; i< 2; i++) {
   int j = 0; //variable de corte ante lecturaerrores//
   while (j == 0) {
    leer();
    if (tecla!=0) {
      if (num< 10) {
        j = 1;
        segundos= segundos * 10 +num;
        lcd.setCursor(0, 2);
        lcd.print("S: ");
        lcd.setCursor(i+ 4, 2);
        lcd.print(num);
        lcd.print(" segundos.");
        delay(tl/ 20);
      }
      else {
        if (tecla=='#') {
         j = 1;
         i= 3;
         num= 0;
        }
        else {
        }
      }
    }
   }
  }
  delay(tl);
}
//Fin toma segundos//

//**********************************************//

void funcionar() {
 int a = 0;
 int b = 0;
 int c = 0;
 int pausa = 0;
 //Preparamos la salida para que el motor gire en un sentido//
 digitalWrite (IN1,LOW);
 digitalWrite (IN2,HIGH);
 
 //Variables auxiliares para escribir que se excedio el limite//
 lcd.clear();
 if (velocidad>vv) {
  velocidad=vv;
  lcd.setCursor(0, 0);
  lcd.print("Vel mayor a limite");
  a = 1;
 }
 else {
  if (velocidad <vm) {
  velocidad=vm;
  lcd.setCursor(0, 0);
  lcd.print("Vel menor a limite");
  a = 1;
  }
  else {
   lcd.setCursor(0, 0);
   lcd.print("Velocidad correcta");
  }
 }
 if (minutos > mm) {
  minutos= mm;
  lcd.setCursor(0, 1);
  lcd.print("Min mayor a limite");
  b = 1;
 }
 else {
  lcd.setCursor(0, 1);
  lcd.print("Minutos correctos");
 }
 if (segundos >ss) {
  segundos=ss;
  lcd.setCursor(0, 2);
  lcd.print("Seg mayor a limite");
  c = 1;
 }
 else {
  lcd.setCursor(0, 2);
  lcd.print("Segundos correctos");
  }
 if ( a == 1 || b == 1 || c == 1 ) {
  lcd.setCursor(0, 3);
  lcd.print("Valor/es corregidos");
 }
 delay(tl*2);
int tiempo = ((minutos * 60) + (segundos));//tiempo deseado, en segundos//
float v2 = 0; //Variable auxiliar de calculo % del total//
float v3 = 0; //Variable auxiliar de calculo entre 0 y 255//

//calculo de % respecto al total para obtener las rpm deseadas- polinomio calibrado previamente//
 for (int i= 0; i<= 5; i++) {
  v2 = v2 + (f[i] *pow(velocidad,i));
 }
 v3 = v2 * 255 / 100; //se calcula la tension correspondiente al porcentaje del PWM//
 if (v3 >= 255) {
  v3 = 255;
 }
 if (v3 <= 0) {
  v3 = 0;
 }

 lcd.clear();
 lcd.setCursor(0, 1);
 lcd.print("*******INICIO*******");
 delay(tl* 0.5);
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(" FUNCIONANDO ");
 lcd.setCursor(0, 1);
 lcd.print("Fin: * // Pausa: #"); //Indicadores de finalizacion y parada//
 analogWrite(ENA, v3); //PRENDE motor a velocidad indicada por v3//
 int tactual= (millis() / 1000); // inicializar el tiempo actual//
 const int ti = (millis() / 1000); // Definir tiempo de inicio como invariante para calculos//
 int t = tiempo +tactual ; //calculo tiempo objetivo en segundos//
 int tpausa= 0; //Inicializar pausa en cero//
 int tip = 0;

 while (tactual < t ) {
  lcd.setCursor(0, 2);
  lcd.print("Velocidad: ");
  lcd.print(velocidad);
  lcd.setCursor(0, 3);
  lcd.print("Tiempo: ");
  int maux= ((millis() / 1000) - ti -tpausa) / 60; //Minutos auxiliares para escritura//
  lcd.print(maux);
  lcd.print(" m. ");
  int saux= ((millis() / 1000) - ti -tpausa);//Segundos auxiliares para escritura//
  int taux=saux- (60 *maux);
  lcd.print(taux);
  if (taux>= 10) {
   lcd.print(" s.");
  }
  else {
   lcd.print(" s. ");
  }
  leer();
  if (tecla!= 0) {
    if (tecla=='*') {
     tpausa= 0 - t;
    }
    if (tecla=='#') {
     pausa= 1;
    tip= (millis() / 1000); // Toma tiempo de inicio de pausa//
     analogWrite(ENA, 0);
     lcd.clear();
     lcd.setCursor(0, 0);
     lcd.print("----Menu de Pausa---");
     lcd.setCursor(0, 1);
     lcd.print("Tiempo: ");
     lcd.print(maux);
     lcd.print(" m. ");
     lcd.print(taux);
     if (taux>= 10) {
      lcd.print(" s.");
     }
     else {
      lcd.print(" s. ");
     }
    }
  lcd.setCursor(0, 2);
  lcd.print("Reanudar: A,B,C o D ");
  lcd.setCursor(0, 3);
  lcd.print("Finalizar:   *   ");
  
  while (pausa== 1) {
   leer();
   if (tecla!= 0) {
    if (tecla=='A'||tecla=='B'||tecla=='C'||tecla=='D' ) {
      pausa= 0;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" FUNCIONANDO ");
      lcd.setCursor(0, 1);
      lcd.setCursor(0, 1);
      lcd.print("Fin: * // Pausa: #");
      analogWrite(ENA, v3);
      int tfp= (millis() / 1000);// Toma tiempo final de pausa//
      tpausa=tfp-tip+tpausa;
    }
    else {
      if ( tecla=='*' ) {
       tpausa= 0 - t;
       pausa= 0;
      }
    }
   }
  }
 }
 tactual= ((millis() / 1000) -tpausa);
}//fin while//

  analogWrite(ENA, 0);
  delay(tl/ 2);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("*********FIN********");
  delay(tl);
  lcd.clear();
}//Fin funcionar//

//************************************************//
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
L298N Breakout
L298N_chip1:EN A
L298N_chip1:IN1
L298N_chip1:IN2
L298N_chip1:IN3
L298N_chip1:IN4
L298N_chip1:EN B
L298N_chip1:OUT1
L298N_chip1:OUT2
L298N_chip1:OUT3
L298N_chip1:OUT4
L298N_chip1:5V
L298N_chip1:GND
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
stepper1:A-
stepper1:A+
stepper1:B+
stepper1:B-
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4
stepper2:A1-
stepper2:A1+
stepper2:B1+
stepper2:B1-
stepper2:A2-
stepper2:A2+
stepper2:B2+
stepper2:B2-