// Librerías necesarias
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_FT6206.h>
#include <SPI.h>
#include <Wire.h>
#include <ESP32Servo.h>
// Pines para la pantalla TFT
const int TFT_CS = 1;
const int TFT_DC = 42;
const int TFT_MOSI = 41;
const int TFT_CLK = 40;
const int TFT_MISO = 16;
#define TFT_RST -1
// Pin del servomotor
const int SERVO_PIN = 13;
// Dimensiones de pantalla y botones
#define SCREEN_W 320
#define SCREEN_H 240
#define BTN_W 200
#define BTN_H 40
#define BTN_X (SCREEN_W - BTN_W)/2
#define BTN_Y1 55
#define BTN_Y2 105
#define BTN_Y3 155
#define BTN_Y_BACK 205
// Inicialización de objetos hardware:
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_MISO, TFT_RST);
Adafruit_FT6206 ctp = Adafruit_FT6206();
Servo servo;
// Estado de pantalla
enum EstadoPantalla { MENU_PRINCIPAL, SUBMENU_A, SUBMENU_B, SUBMENU_C };
EstadoPantalla estadoPantalla = MENU_PRINCIPAL;
void setup() {
Serial.begin(115200);
Serial.println("Options Menu Design.");
Wire.setPins(10, 8);
if (!ctp.begin(40)) {
Serial.println("Couldn't start FT6206 touchscreen controller.");
while (1);
}
Serial.println("Capacitive touchscreen started.");
tft.begin();
tft.setRotation(1);
// Configuración del servomotor
servo.setPeriodHertz(50);
servo.attach(SERVO_PIN, 500, 2500);
servo.write(90);
dibujarMenu();
Serial.println("Esperando selección ...");
}
// Variables de estado adicionales
bool estadoActual = false;
void loop() {
static bool tocando = false;
if (!estadoActual && ctp.touched()) {
if (!tocando) {
tocando = true;
TS_Point p = ctp.getPoint();
int x = map(p.y, 0, 320, 0, SCREEN_W);
int y = map(240 - p.x, 0, 240, 0, SCREEN_H);
Serial.print("Touch x = "); Serial.print(x);
Serial.print(" | y = "); Serial.println(y);
if (estadoPantalla == MENU_PRINCIPAL) {
if (x > BTN_X && x < BTN_X + BTN_W) {
if (y > BTN_Y1 && y < BTN_Y1 + BTN_H) {
dibujarSubmenuA();
estadoPantalla = SUBMENU_A;
} else if (y > BTN_Y2 && y < BTN_Y2 + BTN_H) {
dibujarSubmenuB();
estadoPantalla = SUBMENU_B;
} else if (y > BTN_Y3 && y < BTN_Y3 + BTN_H) {
dibujarSubmenuC();
estadoPantalla = SUBMENU_C;
}
}
} else if (estadoPantalla == SUBMENU_A) {
if (x > BTN_X && x < BTN_X + BTN_W) {
if (y > BTN_Y1 && y < BTN_Y1 + BTN_H) {
ejecutarOpcion('A');
} else if (y > BTN_Y2 && y < BTN_Y2 + BTN_H) {
ejecutarCalibracionA();
} else if (y > BTN_Y_BACK && y < BTN_Y_BACK + BTN_H) {
dibujarMenu();
estadoPantalla = MENU_PRINCIPAL;
}
}
} else if (estadoPantalla == SUBMENU_B) {
if (x > BTN_X && x < BTN_X + BTN_W) {
if (y > BTN_Y1 && y < BTN_Y1 + BTN_H) {
ejecutarOpcion('B');
} else if (y > BTN_Y2 && y < BTN_Y2 + BTN_H) {
ejecutarCalibracionB();
} else if (y > BTN_Y_BACK && y < BTN_Y_BACK + BTN_H) {
dibujarMenu();
estadoPantalla = MENU_PRINCIPAL;
}
}
} else if (estadoPantalla == SUBMENU_C) {
if (x > BTN_X && x < BTN_X + BTN_W) {
if (y > BTN_Y1 && y < BTN_Y1 + BTN_H) {
ejecutarOpcion('C');
} else if (y > BTN_Y2 && y < BTN_Y2 + BTN_H) {
ejecutarCalibracionC();
} else if (y > BTN_Y_BACK && y < BTN_Y_BACK + BTN_H) {
dibujarMenu();
estadoPantalla = MENU_PRINCIPAL;
}
}
}
}
}
else {
tocando = false;
}
delay(200);
}
void dibujarMenu() {
tft.fillScreen(ILI9341_CYAN);
tft.setTextSize(2);
tft.setTextColor(ILI9341_MAROON);
tft.setCursor(40, 10);
tft.println("Selecciona un modulo");
tft.setCursor(50, 30);
tft.println(" para empezar:");
tft.fillRect(BTN_X, BTN_Y1, BTN_W, BTN_H, ILI9341_YELLOW);
for (int i = 0; i < 3; i++) tft.drawRect(BTN_X + i, BTN_Y1 + i, BTN_W - 2 * i, BTN_H - 2 * i, ILI9341_BLACK);
tft.setTextColor(ILI9341_BLACK);
tft.setCursor(BTN_X + 54, BTN_Y1 + 12);
tft.setTextSize(2);
tft.print("Modulo A");
tft.fillRect(BTN_X, BTN_Y2, BTN_W, BTN_H, ILI9341_RED);
for (int i = 0; i < 3; i++) tft.drawRect(BTN_X + i, BTN_Y2 + i, BTN_W - 2 * i, BTN_H - 2 * i, ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(BTN_X + 54, BTN_Y2 + 12);
tft.setTextSize(2);
tft.print("Modulo B");
tft.fillRect(BTN_X, BTN_Y3, BTN_W, BTN_H, ILI9341_GREEN);
for (int i = 0; i < 3; i++) tft.drawRect(BTN_X + i, BTN_Y3 + i, BTN_W - 2 * i, BTN_H - 2 * i, ILI9341_BLACK);
tft.setTextColor(ILI9341_BLACK);
tft.setCursor(BTN_X + 54, BTN_Y3 + 12);
tft.setTextSize(2);
tft.print("Modulo C");
}
void dibujarSubmenuA() {
tft.fillScreen(ILI9341_LIGHTGREY);
tft.setTextSize(2);
tft.setTextColor(ILI9341_BLUE);
tft.setCursor(40, 10);
tft.println("Modulo A - Opciones");
tft.fillRect(BTN_X, BTN_Y1, BTN_W, BTN_H, ILI9341_ORANGE);
for (int i = 0; i < 2; i++) tft.drawRect(BTN_X + i, BTN_Y1 + i, BTN_W - 2 * i, BTN_H - 2 * i, ILI9341_BLACK);
tft.setCursor(BTN_X + 20, BTN_Y1 + 12);
tft.setTextColor(ILI9341_BLACK);
tft.print("Funcionamiento A");
tft.fillRect(BTN_X, BTN_Y2, BTN_W, BTN_H, ILI9341_MAGENTA);
for (int i = 0; i < 2; i++) tft.drawRect(BTN_X + i, BTN_Y2 + i, BTN_W - 2 * i, BTN_H - 2 * i, ILI9341_BLACK);
tft.setCursor(BTN_X + 35, BTN_Y2 + 12);
tft.setTextColor(ILI9341_WHITE);
tft.print("Calibracion A");
tft.fillRect(BTN_X, BTN_Y_BACK, BTN_W, BTN_H, ILI9341_BLUE);
for (int i = 0; i < 2; i++) tft.drawRect(BTN_X + i, BTN_Y_BACK + i, BTN_W - 2 * i, BTN_H - 2 * i, ILI9341_BLACK);
tft.setCursor(BTN_X + 40, BTN_Y_BACK + 12);
tft.setTextColor(ILI9341_WHITE);
tft.print("Volver al menu");
}
void dibujarSubmenuB() {
dibujarSubmenuA();
tft.setCursor(40, 10);
tft.setTextColor(ILI9341_RED);
tft.fillRect(0, 0, SCREEN_W, 30, ILI9341_LIGHTGREY);
tft.setCursor(40, 10);
tft.print("Modulo B - Opciones");
tft.setCursor(BTN_X + 20, BTN_Y1 + 12);
tft.setTextColor(ILI9341_BLACK);
tft.fillRect(BTN_X, BTN_Y1, BTN_W, BTN_H, ILI9341_ORANGE);
tft.print("Funcionamiento B");
tft.fillRect(BTN_X, BTN_Y2, BTN_W, BTN_H, ILI9341_MAGENTA);
tft.setCursor(BTN_X + 35, BTN_Y2 + 12);
tft.setTextColor(ILI9341_WHITE);
tft.print("Calibracion B");
}
void dibujarSubmenuC() {
dibujarSubmenuA();
tft.setCursor(40, 10);
tft.setTextColor(ILI9341_GREEN);
tft.fillRect(0, 0, SCREEN_W, 30, ILI9341_LIGHTGREY);
tft.setCursor(40, 10);
tft.print("Modulo C - Opciones");
tft.setCursor(BTN_X + 20, BTN_Y1 + 12);
tft.setTextColor(ILI9341_BLACK);
tft.fillRect(BTN_X, BTN_Y1, BTN_W, BTN_H, ILI9341_ORANGE);
tft.print("Funcionamiento C");
tft.fillRect(BTN_X, BTN_Y2, BTN_W, BTN_H, ILI9341_MAGENTA);
tft.setCursor(BTN_X + 35, BTN_Y2 + 12);
tft.setTextColor(ILI9341_WHITE);
tft.print("Calibracion C");
}
void ejecutarOpcion(char modulo) {
estadoActual = true;
Serial.print("Se está ejecutando el módulo ");
Serial.print(modulo);
Serial.println(".");
char mensaje[30];
snprintf(mensaje, sizeof(mensaje), "Ejecutar acciones Mo%c", modulo);
mostrarEstado(mensaje);
switch (modulo) {
case 'A': servo.write(45); break;
case 'B': servo.write(135); break;
case 'C': servo.write(90); break;
}
delay(500);
Serial.println("Ejecución y acciones concluidas.");
Serial.print("\n");
delay(500);
Serial.println("Esperando selección ...");
estadoActual = false;
}
void ejecutarCalibracionA() {
estadoActual = true;
mostrarEstado("Calibrando...");
Serial.println("Ejecutando Calibracion A");
servo.write(180);
delay(1000);
servo.write(90);
delay(500);
mostrarEstado("Calibracion OK");
estadoActual = false;
}
void ejecutarCalibracionB() {
estadoActual = true;
mostrarEstado("Calibrando...");
Serial.println("Ejecutando Calibracion B");
servo.write(10);
delay(1000);
servo.write(90);
delay(500);
mostrarEstado("Calibracion OK");
estadoActual = false;
}
void ejecutarCalibracionC() {
estadoActual = true;
mostrarEstado("Calibrando...");
Serial.println("Ejecutando Calibracion C");
servo.write(170);
delay(1000);
servo.write(90);
delay(500);
mostrarEstado("Calibracion OK");
estadoActual = false;
}
void mostrarEstado(const char* texto) {
int estadoY = SCREEN_H - 35;
tft.fillRect(0, estadoY, SCREEN_W, 25, ILI9341_BLUE);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(31, estadoY + 5);
tft.setTextSize(2);
tft.print(texto);
}
Loading
esp32-s3-devkitc-1
esp32-s3-devkitc-1
Loading
ili9341-cap-touch
ili9341-cap-touch