#include <TimeLib.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// Define la zona horaria de Santiago de Chile (UTC-3)
const long utcOffsetInSeconds = -3 * 3600;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
// Define nombre de la red a conectarse
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Definir el tamaño de la pantalla OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Crear una instancia de la pantalla OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Definir pines de botones
const int buttonMove = 15;
const int buttonSelect = 4;
// Variables para el menú principal
int currentOption = 0;
const int totalOptions = 4;
const char* options[totalOptions] = {"Horario 1", "Horario 2", "Modo Ejecucion", "Inf. Configuracion"};
// Variables para los menús de horarios
int currentTimeOption = 0;
const int totalTimeOptions = 9;
const char* timeOptions[totalTimeOptions] = {"05:00", "06:00", "07:00", "13:00", "14:00", "19:00", "20:00", "21:00", "Volver"};
// Estado del menú
enum MenuState { MAIN_MENU, HORARIO_1_MENU, HORARIO_2_MENU };
MenuState menuState = MAIN_MENU;
void setup() {
// Iniciar la comunicación serial para depuración
Serial.begin(115200);
// Configurar los pines de los botones
pinMode(buttonMove, INPUT_PULLUP);
pinMode(buttonSelect, INPUT_PULLUP);
// Configurar los pines I2C manualmente
Wire.begin(19, 18); // SDA = GPIO 19, SCL = GPIO 18
// Iniciar la pantalla OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("No se encuentra la pantalla OLED SSD1306"));
for(;;);
}
// Limpiar la pantalla
display.clearDisplay();
// Conecta a la red Wifi
conexion_wifi();
// Inicializa el cliente NTP
timeClient.begin();
// Obtener la hora actual y guardarla en una variable
String horaActual = NTP_Hora();
Serial.print("Hora actual: ");
Serial.println(horaActual);
// Mostrar el menú inicial
updateMenu();
}
String NTP_Hora() {
// Actualiza el cliente NTP para obtener la hora actual
timeClient.update();
// Retorna la hora actual formateada como String
return timeClient.getFormattedTime();
}
String obtenerHora() {
// Obtener la hora actual
time_t now = time(nullptr);
struct tm* timeinfo;
timeinfo = localtime(&now);
// Construir un String con la hora formateada
String hora = "";
hora += timeinfo->tm_hour < 10 ? "0" + String(timeinfo->tm_hour) : String(timeinfo->tm_hour);
hora += ":";
hora += timeinfo->tm_min < 10 ? "0" + String(timeinfo->tm_min) : String(timeinfo->tm_min);
hora += ":";
hora += timeinfo->tm_sec < 10 ? "0" + String(timeinfo->tm_sec) : String(timeinfo->tm_sec);
return hora;
}
void conexion_wifi() {
Serial.println("Conectando a la red WiFi...");
// Conectar a la red WiFi
WiFi.begin(ssid, password);
Serial.print("Conectando a ");
Serial.print(ssid);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Conectado!");
Serial.print("Dirección IP: ");
Serial.println(WiFi.localIP());
}
void loop() {
// Leer el estado de los botones
bool buttonMoveState = digitalRead(buttonMove) == LOW;
bool buttonSelectState = digitalRead(buttonSelect) == LOW;
// Manejar la navegación del menú
if (buttonMoveState) {
if (menuState == MAIN_MENU) {
currentOption = (currentOption + 1) % totalOptions;
} else {
currentTimeOption = (currentTimeOption + 1) % totalTimeOptions;
}
updateMenu();
delay(200); // Antirrebote
}
// Manejar la selección del menú
if (buttonSelectState) {
if (menuState == MAIN_MENU) {
if (currentOption == 0) {
menuState = HORARIO_1_MENU;
currentTimeOption = 0;
} else if (currentOption == 1) {
menuState = HORARIO_2_MENU;
currentTimeOption = 0;
} else {
selectOption();
}
} else {
if (currentTimeOption == totalTimeOptions - 1) {
menuState = MAIN_MENU;
} else {
selectTimeOption();
}
}
updateMenu();
delay(200); // Antirrebote
}
}
void updateMenu() {
// Limpiar la pantalla
display.clearDisplay();
if (menuState == MAIN_MENU) {
// Mostrar el título del menú principal
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("Menu Principal"));
// Mostrar las opciones del menú principal
display.setTextSize(1); // Tamaño de texto del menú
for (int i = 0; i < totalOptions; i++) {
if (i == currentOption) {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Texto invertido para la opción seleccionada
display.setCursor(0, (i + 2) * 10); // Ajustar la posición vertical
display.print(F("> "));
} else {
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, (i + 2) * 10); // Ajustar la posición vertical
}
display.println(options[i]);
}
} else {
// Mostrar el título del menú de horarios
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
if (menuState == HORARIO_1_MENU) {
display.println(F("Horario 1"));
} else {
display.println(F("Horario 2"));
}
// Mostrar las opciones del menú de horarios en dos columnas
display.setTextSize(1); // Tamaño de texto del menú
for (int i = 0; i < totalTimeOptions; i++) {
int x = (i % 2) * 64; // Columna (0 o 1)
int y = (i / 2 + 1) * 10; // Fila
if (i == currentTimeOption) {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Texto invertido para la opción seleccionada
display.setCursor(x, y); // Ajustar la posición
display.print(F("> "));
display.setCursor(x + 10, y); // Ajustar la posición después del símbolo ">"
} else {
display.setTextColor(SSD1306_WHITE);
display.setCursor(x + 10, y); // Ajustar la posición
}
display.println(timeOptions[i]);
}
}
// Mostrar el menú actualizado
display.display();
}
void selectOption() {
// Aquí puedes agregar el código para manejar la selección de cada opción en el menú principal
Serial.println("Seleccionaste la opción " + String(currentOption + 1) + ": " + options[currentOption]);
}
void selectTimeOption() {
// Aquí puedes agregar el código para manejar la selección de cada opción en el menú de horarios
Serial.println("Seleccionaste el horario " + String(currentTimeOption + 1) + ": " + timeOptions[currentTimeOption]);
}