#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Dirección I2C del LCD
LiquidCrystal_I2C lcd(0x27, 16, 2); // Ajusta la dirección I2C según tu módulo
// Pines de los botones
const int selectButtonPin = 2;
const int playButtonPin = 3;
const int resetButtonPin = 4;
// Pin del LED
const int ledPin = 13;
// Duración total del programa en milisegundos (10 minutos)
const unsigned long totalDuration = 600000;
// Estados del menú
enum MenuState {
MENU_IDLE,
MENU_RUNNING,
MENU_SELECT,
MENU_RESET
};
MenuState currentState = MENU_IDLE;
int currentSelection = 0;
// Configuración inicial
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(selectButtonPin, INPUT_PULLUP);
pinMode(playButtonPin, INPUT_PULLUP);
pinMode(resetButtonPin, INPUT_PULLUP);
lcd.init(); // Inicializa el LCD
lcd.backlight(); // Enciende la luz de fondo del LCD
showWelcomeMessage(); // Muestra el mensaje de bienvenida
delay(3000); // Retraso inicial de 3 segundos
// Muestra el menú inicial
updateMenuDisplay();
}
// Bucle principal
void loop() {
handleMenuNavigation();
if (currentState == MENU_RUNNING) {
runPsycheSurfer();
}
}
// Función para manejar la navegación del menú
void handleMenuNavigation() {
if (digitalRead(selectButtonPin) == LOW) {
delay(200); // Debounce
currentSelection = (currentSelection + 1) % 2; // Cambia la selección
updateMenuDisplay();
}
if (digitalRead(playButtonPin) == LOW) {
delay(200); // Debounce
if (currentSelection == 0) {
currentState = MENU_RUNNING;
}
updateMenuDisplay();
}
if (digitalRead(resetButtonPin) == LOW) {
delay(200); // Debounce
currentState = MENU_RESET;
updateMenuDisplay();
resetProgram();
}
}
// Función para mostrar el mensaje de bienvenida
void showWelcomeMessage() {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(" Bienvenido! ");
}
// Función para actualizar la pantalla del menú
void updateMenuDisplay() {
lcd.clear();
lcd.setCursor(0, 0);
if (currentState == MENU_IDLE) {
lcd.print("Seleccion:");
lcd.setCursor(0, 1);
lcd.print(currentSelection == 0 ? "> Psyche Surfer" : " Psyche Surfer");
} else if (currentState == MENU_RUNNING) {
lcd.print("Iniciando");
} else if (currentState == MENU_RESET) {
lcd.print("Reiniciando...");
}
}
// Función para reiniciar el programa
void resetProgram() {
currentState = MENU_IDLE;
currentSelection = 0;
updateMenuDisplay();
delay(3000); // Retraso para permitir reinicio visible
}
// Función para ejecutar el programa Psyche Surfer
void runPsycheSurfer() {
float currentFrequency = 8.0; // Comienza en low alfa
unsigned long startTime = millis();
int direction = -1; // Comienza disminuyendo hacia theta
while (millis() - startTime < totalDuration) {
float period = 1000.0 / currentFrequency; // Periodo en milisegundos
// Un ciclo completo de parpadeo
digitalWrite(ledPin, HIGH);
delay(period / 2);
digitalWrite(ledPin, LOW);
delay(period / 2);
// Ajusta la frecuencia gradualmente
currentFrequency += 0.005 * direction;
// Lógica para cambiar la dirección y las fases del programa
unsigned long elapsedTime = millis() - startTime;
if (elapsedTime < totalDuration * 0.2) {
// Primeros 2 minutos: low alfa a hi theta
if (currentFrequency <= 6.0) direction = 1;
} else if (elapsedTime < totalDuration * 0.3) {
// Siguiente 1 minuto: mantener en hi theta
if (currentFrequency < 6.0) direction = 1;
else if (currentFrequency > 8.0) direction = -1;
} else if (elapsedTime < totalDuration * 0.5) {
// Siguientes 2 minutos: hi theta a low alfa
if (currentFrequency >= 10.0) direction = -1;
} else {
// Últimos 5 minutos: enfoque en hi alfa
if (currentFrequency <= 10.0) direction = 1;
else if (currentFrequency >= 13.0) direction = -1;
}
// Asegurarse de que la frecuencia se mantenga dentro de los límites
currentFrequency = constrain(currentFrequency, 6.0, 13.0);
// Verificar si se presionó el botón de reset
if (digitalRead(resetButtonPin) == LOW) {
delay(200); // Debounce
resetProgram();
return;
}
}
// Cuando termina el ciclo de 10 minutos, mantén el LED apagado
while (currentState == MENU_RUNNING) {
digitalWrite(ledPin, LOW);
// Verificar si se presionó el botón de reset
if (digitalRead(resetButtonPin) == LOW) {
delay(200); // Debounce
resetProgram();
}
}
}