MODELO MENU
CODIGO
//librerias #include <EEPROM.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ //PINES DE ENTRADA DE LOS PULSADORES █ const int in_A = 2; //ADD █ const int in_B = 4; //LESS █ const int swPin = 3; //OK █ bool btnpress = false; //memoria boton OK █ //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█ //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ //PINES DE SALIDA PARA CONTROLAR LOS MOTORES █ #define pwm_motor1 9 //Salidas PWM para el motor 1 █ #define pwm_motor2 10 //Salidas PWM para el motor 2 █ #define der_m1 5 // señal para que el motor 1 gire hacia la derecha █ #define izq_m1 6 // señal para que el motor 1 gire hacia la izquierda █ #define der_m2 7 // señal para que el motor 2 gire hacia la derecha █ #define izq_m2 8 // señal para que el motor 2 gire hacia la ziquierda █ \ ///// █ //MEMORIAS PARA LA VELOCIDAD DEL MOTOR █ int vel_moto1 = 0; // variable para la velocidad del motor1 █ int vel_moto2 = 0; // variable para la velocidad del motor2 █ int direc_moto1 = 1; //Direccion EEPROM para almacenar la variable vel_moto1 █ int direc_moto2 = 2; //Direccion EEPROM para almacenar la variable vel_moto2 █ //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█ //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ //---------------------------------------------------MENUS-------------------------------------------------------------------------------------------------- String menu1[] = { "ON // OFF", "ADJ VELOCIDAD", "INVER GIRO", "Atras" }; //Palabras del menu principal int sizemenu1 = sizeof(menu1) / sizeof(menu1[0]); // Aqui vamos a obtener el número de elementos ocupados en la matriz. en este caso 3 String menu2[] = { "Motor1", "Motor2", "Atras" }; int sizemenu2 = sizeof(menu2) / sizeof(menu2[0]); String menu3[] = { "ON", "OFF", "Atras" }; int sizemenu3 = sizeof(menu3) / sizeof(menu3[0]); String menu4[] = { "Izquierda", "Derecha", "Atras" }; int sizemenu4 = sizeof(menu4) / sizeof(menu4[0]); String linea1, linea2; //lines o filas del lcd 16x2 int level_menu = 0; // para ubicarnos en un menú { "ON // OFF", "ADJ VELOCIDAD", "INVER GIRO", "Atras" } { "Motor1", "Motor2", "Atras" }; int level2_menu = 0; // para ubicarnos en el subnemu { "ON", "OFF", "Atras" } { "Izquierda", "Derecha", "Atras" } int contador = 0; // CONTADOR PARA EL DESPLAZAMIENTO ENTRE LOS MENUS byte flecha[] = { B10000, B11000, B11100, B11110, B11100, B11000, B10000, B00000 }; //Creamos un array de 8 posiciones para la flecha del menu //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ void setup() { pinMode(in_A, INPUT); pinMode(in_B, INPUT); pinMode(swPin, INPUT); pinMode(pwm_motor1, OUTPUT); pinMode(pwm_motor2, OUTPUT); pinMode(der_m1, OUTPUT); pinMode(izq_m1, OUTPUT); pinMode(der_m2, OUTPUT); pinMode(izq_m2, OUTPUT); lcd.init(); lcd.backlight(); lcd.createChar(0, flecha); //Caracter personalizado vel_moto1 = EEPROM.read(direc_moto1); // Obtiene el dato de EEPROM y lo envía a la variable vel_moto1 vel_moto2 = EEPROM.read(direc_moto2); analogWrite(pwm_motor1, map(vel_moto1, 0, 9, 0, 255)); //Enviamos el dato leido de EEPROM al MOTOR 1 analogWrite(pwm_motor2, map(vel_moto2, 0, 9, 0, 255)); } void loop() { selectOption(); //Funcion para detectar cuando se Presionar el pusador de OK //███████████████████████████████████ PANTALLA PRINCIPAL ██████████████████████████████████████████ if (level_menu == 0) { lcd.setCursor(0, 0); //Detalles mas importantes del motor1 // linea0 lcd.print("Motor1: "); if (vel_moto1) lcd.print("ON, "); else lcd.print("OFF, "); lcd.print(vel_moto1); lcd.setCursor(0, 1); //Detalles mas importantes del motor2 // linea1 lcd.print("Motor2: "); if (vel_moto2) lcd.print("ON, "); else lcd.print("OFF, "); lcd.print(vel_moto2); if (btnpress) { // si se presiona el pulsador de OK nos llevará al menu principal level_menu = 1; fn_menu(contador, menu1, sizemenu1); btnpress = false; } } //███████████████████████████████████████████████████████████████████████████████████████████████ //███████████████████████████████████ MENU 1 PRINCIPAL ██████████████████████████████████████████ if (level_menu == 1) { //Esta variable corresponde al nivel principal del menu. level_menu = 1. if (fnSwitch(sizemenu1)) { //Esta funcion muestra en el LCD el menu en el que estamos fn_menu(contador, menu1, sizemenu1); //Esta funcion muestra la posicion dentro de ese menu segun el valor de la variable contador } if (btnpress) { //Verificamos si el boton del encoder fue oprimido. btnpress == true // >ON // OFF if (contador == 0) { contador = 0; //Seleccionamos la posicion donde quedara la flecha de seleccion. On, Off, Atras fn_menu(contador, menu2, sizemenu2); //Vamos a la funcion que nos muestra las opciones para el Led 1 level_menu = 2; //Esta variable corresponde al nivel secundario del menu. level_menu = 1. } // > ADJ VELOCIDAD if (contador == 1) { contador = 0; fn_menu(contador, menu2, sizemenu2); level_menu = 3; } //> INVERSION DE GIRO if (contador == 2) { contador = 0; fn_menu(contador, menu2, sizemenu2); level_menu = 4; } //>Atras if (contador == 3) { contador = 0; level_menu = 0; } btnpress = false; // Nos aseguramos que esta variable de retorno de la funcion selectOption() vuelva a su estado inicial } } //██████████████████████████████████████████████████████████████████████████████████████████████████████████████ //███████████████████████████████████ MENU2: { "Motor1", "Motor2", "Atras" } ██████████████████████████████████████████ if (level_menu == 2) { if (level2_menu == 0) { if (fnSwitch(sizemenu2)) { //Nos desplazamos con el encoder sleccionando las diferentes opciones fn_menu(contador, menu2, sizemenu2); } if (btnpress) { //Verificamos si el boton del encoder fue oprimido. btnpress == true if (contador == 0) { // motor1 contador = 0; fn_menu(contador, menu3, sizemenu3); level2_menu = 1; } if (contador == 1) { // motor2 contador = 0; fn_menu(contador, menu3, sizemenu3); level2_menu = 2; } if (contador == 2) { //atras contador = 0; fn_menu(contador, menu1, sizemenu1); level_menu = 1; } btnpress = false; } } //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ MENU 3: { "ON", "OFF", "Atras" } ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ if (level2_menu == 1) { if (fnSwitch(sizemenu3)) { //Nos desplazamos con el encoder sleccionando las diferentes opciones fn_menu(contador, menu3, sizemenu3); } if (btnpress) { if (contador == 0) { digitalWrite(pwm_motor1, HIGH); //Encedemos motor 1 vel_moto1 = 9; //Maximo velocidad EEPROM.write(direc_moto1, vel_moto1); } if (contador == 1) { digitalWrite(pwm_motor1, LOW); //Apagamos motor 1 vel_moto1 = 0; //minima velocidad EEPROM.write(direc_moto1, vel_moto1); } if (contador == 2) { //atras contador = 0; fn_menu(contador, menu2, sizemenu2); level2_menu = 0; } btnpress = false; } } if (level2_menu == 2) { if (fnSwitch(sizemenu3)) { //Nos desplazamos con el encoder sleccionando las diferentes opciones fn_menu(contador, menu3, sizemenu3); } if (btnpress) { if (contador == 0) { digitalWrite(pwm_motor2, HIGH); // ON MOTOR 2 vel_moto2 = 9; // velocidad maxima EEPROM.write(direc_moto2, vel_moto2); } if (contador == 1) { digitalWrite(pwm_motor2, LOW); //OFF MOTOR2 vel_moto2 = 0; //Velocidad minima EEPROM.write(direc_moto2, vel_moto2); } if (contador == 2) { //atras contador = 0; fn_menu(contador, menu2, sizemenu2); level2_menu = 0; } btnpress = false; } } //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ } //██████████████████████████████████████████████████████████████████████████████████████████████████████████████ //███████████████████████████████████ MENU3: velocidad motor1, velocidad motor2 ██████████████████████████████████████████ if (level_menu == 3) { if (fnSwitch(sizemenu2)) { // MENU2: { "Motor1", "Motor2", "Atras" } fn_menu(contador, menu2, sizemenu2); } if (btnpress) { if (contador == 0) { contador = vel_moto1; lcd.clear(); do { fn_contador_brillo(); vel_moto1 = contador; lcd.setCursor(0, 0); lcd.print("velocidad motor1"); analogWrite(pwm_motor1, map(vel_moto1, 0, 9, 0, 255)); lcd.setCursor(0, 1); lcd.print(vel_moto1); } while (digitalRead(swPin) == LOW); //Instrucciones despues del do se repetirán mientras esta condición sea cierta delay(500); EEPROM.write(direc_moto1, vel_moto1); // Se agrega a EEPROM con la dirección primero y valor de la variable después contador = 0; fn_menu(contador, menu2, sizemenu2); } if (contador == 1) { contador = vel_moto2; lcd.clear(); do { fn_contador_brillo(); vel_moto2 = contador; lcd.setCursor(0, 0); lcd.print("velocidad motor2"); analogWrite(pwm_motor2, map(vel_moto2, 0, 9, 0, 255)); lcd.setCursor(0, 1); lcd.print(vel_moto2); } while (digitalRead(swPin) == LOW); //Instrucciones despues del do se repetirán mientras esta condición sea cierta delay(500); EEPROM.write(direc_moto2, vel_moto2); contador = 1; fn_menu(contador, menu2, sizemenu2); } if (contador == 2) { //ATRAS contador = 1; //Posicion del menu donde se genero el llamado 0 --> 5 fn_menu(contador, menu1, sizemenu1); //Retorna al Menu Principal a la posicion del menu donde se genero el llamado level_menu = 1; } btnpress = false; } } //██████████████████████████████████████████████████████████████████████████████████████████████████████████████ //███████████████████████████████████ MENU2: { "Motor1", "Motor2", "Atras" } ██████████████████████████████████████████ if (level_menu == 4) { if (level2_menu == 0) { if (fnSwitch(sizemenu2)) { fn_menu(contador, menu2, sizemenu2); } if (btnpress) { if (contador == 0) { // MOTOR 1 contador = 0; fn_menu(contador, menu4, sizemenu4); level2_menu = 1; } if (contador == 1) { // MOTOR 2 contador = 0; fn_menu(contador, menu4, sizemenu4); level2_menu = 2; } if (contador == 2) { //ATRAS contador = 0; fn_menu(contador, menu1, sizemenu1); level_menu = 1; } btnpress = false; } } //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ MENU 3.1: { "IZQUIERDA", "DERECHA", "Atras" } ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ if (level2_menu == 1) { // IZQUIERDA, DERECHA, ATRAS: MOTOR 2 if (fnSwitch(sizemenu4)) { fn_menu(contador, menu4, sizemenu4); } if (btnpress) { if (contador == 0) { //IZQUIERDA digitalWrite(der_m1, 1); digitalWrite(izq_m1, 0); } if (contador == 1) { //DERECHA digitalWrite(der_m1, 0); digitalWrite(izq_m1, 1); } if (contador == 2) { //ATRAS contador = 0; fn_menu(contador, menu2, sizemenu2); level2_menu = 0; } btnpress = false; } } if (level2_menu == 2) { // IZQUIERDA, DERECHA, ATRAS: MOTOR 2 if (fnSwitch(sizemenu4)) { fn_menu(contador, menu4, sizemenu4); } if (btnpress) { if (contador == 0) { // IZQUIERDA digitalWrite(der_m2, 1); digitalWrite(izq_m2, 0); } if (contador == 1) { //DERECHA digitalWrite(der_m2, 0); digitalWrite(izq_m2, 1); } if (contador == 2) { //ATRAS contador = 1; fn_menu(contador, menu2, sizemenu2); level2_menu = 0; } btnpress = false; } } //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ } //██████████████████████████████████████████████████████████████████████████████████████████████████████████████ } void selectOption() { //funcion para leer el pulsador de ok if (digitalRead(swPin) == HIGH) { delay(500); btnpress = true; } } void fn_contador_brillo() { if (digitalRead(in_A) == HIGH) { contador++; delay(250); } else if (digitalRead(in_B) == HIGH) { contador--; delay(250); } if (contador > 9) { contador = 9; } if (contador < 0) { contador = 0; } } void fn_menu(int pos, String menus[], byte sizemenu) { // funcion de desplazamiento de los menús lcd.clear(); linea1 = ""; linea2 = ""; if ((pos % 2) == 0) { lcd.setCursor(0, 0); lcd.write(byte(0)); linea1 = menus[pos]; if (pos + 1 != sizemenu) { linea2 = menus[pos + 1]; } } else { linea1 = menus[pos - 1]; lcd.setCursor(0, 1); lcd.write(byte(0)); linea2 = menus[pos]; } lcd.setCursor(1, 0); lcd.print(linea1); lcd.setCursor(1, 1); lcd.print(linea2); } bool fnSwitch(byte sizemenu) { //Lee las señales de los pulsadores, exepto el de ok bool retorno = false; if (digitalRead(in_A) == 1 || digitalRead(in_B) == 1) { if (digitalRead(in_A) == HIGH) { contador++; delay(250); } else if (digitalRead(in_B) == HIGH) { contador--; delay(250); } if (contador <= 0) { contador = 0; } if (contador >= sizemenu - 1) { contador = sizemenu - 1; } retorno = true; } return retorno; }