#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Stepper.h>
// Configuración del LCD I2C (dirección, columnas, filas)
LiquidCrystal_I2C lcd(0x27, 20, 4); // Pantalla LCD de 20x4
// Pines para botones de navegación del menú
const int buttonReturn = 4;
const int buttonSelect = 2;
const int buttonUp = 5;
const int buttonDown = 3;
// Variables de estado del menú
bool isMenuActive = true; // Estado del menú principal
bool needsRedraw = true; // Indica si la pantalla necesita ser redibujada
// Variables de estado para los submenús
bool isSubmenuActive = false;
int activeSubmenu = -1; // -1 significa que no hay submenú activo
// Definición de los elementos del menú principal
const char* menuItems[] = {"Probador Sensores", "Probador Actuador", "Simulador Senales"};
const int totalMenuItems = sizeof(menuItems) / sizeof(menuItems[0]);
// Definición de los elementos del submenú de "Probador de Sensores"
const char* sensorMenuItems[] = {
"Prueba sensor TPS", "Prueba sensor MAP", "Prueba sensor MAF",
"Prueba sensor OPS", "Prueba sensor FRP", "Prueba sensor IAT",
"Prueba sensor ECT", "Prueba sensor CKP", "Prueba sensor CMP",
"Prueba sensor ABS", "Prueba sensor VSS", "Prueba sensor Knoc",
"Prueba sensor Oxigeno", "Prueba sensor APP", "Frecuencimetro"
};
const int totalSensorMenuItems = sizeof(sensorMenuItems) / sizeof(sensorMenuItems[0]);
// Definición de los elementos del submenú de "Probador de Actuadores"
const char* actuatorMenuItems[] = {
"Inyectores ", "IAC 2 Cables", "IAC 3 Cables", "IAC 4 Cables",
"IAC 5 Cables", "IAC 6 Cables", "Opturador.",
"Solenoides PWM", "Valvula EGR", "Generador de PWM"
};
const int totalActuatorMenuItems = sizeof(actuatorMenuItems) / sizeof(actuatorMenuItems[0]);
// Definición de los elementos del submenú de "Simulador de Señales"
const char* signalSimulatorMenuItems[] = {
"Sensor TPS", "Sensor MAP", "Sensor MAF", "Sensor APP",
"Sensor OPS", "Sensor FRP", "Oxigeno", "Sensor IAT",
"Sensor ECT", "CKP y CMP", "Sensor ABS", "Sensor VSS", "Trazador de Curvas"
};
const int totalSignalSimulatorMenuItems = sizeof(signalSimulatorMenuItems) / sizeof(signalSimulatorMenuItems[0]);
// Variables de navegación de menú
int menuIndex = 0; // Índice del elemento seleccionado en el menú principal
int submenuIndex = 0; // Índice del elemento seleccionado en el submenú activo
int windowStart = 0; // Controla el inicio de la ventana de visualización en el menú principal o submenú
void setup() {
lcd.init(); // Inicializa la pantalla LCD
lcd.backlight(); // Activa la luz de fondo
mostrarMensajeInicio(); // Muestra un mensaje inicial en la pantalla LCD
// Configuración de pines de los botones como entradas
pinMode(buttonUp, INPUT);
pinMode(buttonDown, INPUT);
pinMode(buttonSelect, INPUT);
pinMode(buttonReturn, INPUT);
delay(2000); // Pausa de 2 segundos antes de iniciar el menú
lcd.clear();
}
void loop() {
handleButtons(); // Gestiona los botones presionados
if (isMenuActive) {
navigateMenu(); // Navegación del menú principal
} else if (isSubmenuActive) {
navigateSubmenu(); // Navegación del submenú activo
}
}
// Muestra un mensaje inicial en la pantalla LCD
void mostrarMensajeInicio() {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(" Sistema Iniciado ");
lcd.setCursor(0, 2);
lcd.print(" OSCORP ");
}
// Manejo del menú principal
void navigateMenu() {
if (needsRedraw) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("- MENU OSDIAG 2.0 -");
// Mostrar hasta 3 elementos del menú en la pantalla
for (int i = 0; i < 3 && windowStart + i < totalMenuItems; i++) {
int itemIndex = windowStart + i;
lcd.setCursor(0, i + 1);
lcd.print(menuIndex == itemIndex ? "->" : " "); // Indica la opción seleccionada
lcd.print(menuItems[itemIndex]); // Imprime el elemento del menú
}
needsRedraw = false; // Redibujado completado
}
}
// Navegación de submenús según la selección en el menú principal
void navigateSubmenu() {
const char** submenuItems;
int totalSubmenuItems;
// Asigna los elementos y el tamaño del submenú basado en el submenú activo
switch (activeSubmenu) {
case 0:
submenuItems = sensorMenuItems;
totalSubmenuItems = totalSensorMenuItems;
lcd.setCursor(0, 0);
lcd.print("Probador de Sensores");
break;
case 1:
submenuItems = actuatorMenuItems;
totalSubmenuItems = totalActuatorMenuItems;
lcd.setCursor(0, 0);
lcd.print("Probador Actuadores");
break;
case 2:
submenuItems = signalSimulatorMenuItems;
totalSubmenuItems = totalSignalSimulatorMenuItems;
lcd.setCursor(0, 0);
lcd.print("Simulador Senales");
break;
}
if (needsRedraw) {
lcd.clear();
lcd.setCursor(0, 0);
for (int i = 0; i < 3 && windowStart + i < totalSubmenuItems; i++) {
int itemIndex = windowStart + i;
lcd.setCursor(0, i + 1);
lcd.print(submenuIndex == itemIndex ? "->" : " "); // Indica la opción seleccionada
lcd.print(submenuItems[itemIndex]); // Imprime el elemento del submenú
}
needsRedraw = false; // Redibujado completado
}
}
// Función para manejar la navegación con los botones
void handleButtons() {
// Detecta el botón presionado y actúa en consecuencia
if (digitalRead(buttonUp) == HIGH) {
handleButtonUp();
} else if (digitalRead(buttonDown) == HIGH) {
handleButtonDown();
} else if (digitalRead(buttonSelect) == HIGH) {
handleButtonSelect();
} else if (digitalRead(buttonReturn) == HIGH) {
handleButtonReturn();
}
}
// Maneja la acción del botón "Up"
void handleButtonUp() {
if (isMenuActive) {
// Navegación en el menú principal
if (menuIndex > 0) {
menuIndex--;
if (menuIndex < windowStart) windowStart--;
needsRedraw = true;
}
} else if (isSubmenuActive) {
// Navegación en el submenú activo
if (submenuIndex > 0) {
submenuIndex--;
if (submenuIndex < windowStart) windowStart--;
needsRedraw = true;
}
}
}
// Maneja la acción del botón "Down"
void handleButtonDown() {
if (isMenuActive) {
// Navegación en el menú principal
if (menuIndex < totalMenuItems - 1) {
menuIndex++;
if (menuIndex > windowStart + 2) windowStart++;
needsRedraw = true;
}
} else if (isSubmenuActive) {
// Navegación en el submenú activo
const int totalSubmenuItems = getTotalSubmenuItems();
if (submenuIndex < totalSubmenuItems - 1) {
submenuIndex++;
if (submenuIndex > windowStart + 2) windowStart++;
needsRedraw = true;
}
}
}
// Maneja la acción del botón "Select"
void handleButtonSelect() {
if (isMenuActive) {
// Activa el submenú basado en la opción seleccionada en el menú principal
isMenuActive = false;
isSubmenuActive = true;
activeSubmenu = menuIndex;
submenuIndex = 0;
windowStart = 0;
needsRedraw = true;
}
}
// Maneja la acción del botón "Return"
void handleButtonReturn() {
if (isSubmenuActive) {
// Regresa al menú principal desde el submenú activo
isSubmenuActive = false;
isMenuActive = true;
activeSubmenu = -1;
menuIndex = 0;
windowStart = 0;
needsRedraw = true;
}
}
// Devuelve el número total de elementos en el submenú activo
int getTotalSubmenuItems() {
switch (activeSubmenu) {
case 0: return totalSensorMenuItems;
case 1: return totalActuatorMenuItems;
case 2: return totalSignalSimulatorMenuItems;
default: return 0;
}
}