En esta entrada realizaremos un mini TV utilizando la ya conocida ESP32 y una pantalla TFT de 1.65 pulgadas de la marca WavesShare. Esta mini TV es ideal para ver los resultados de los partidos de futbol como la Eurocopa, Copa America, Liga MX y mas torneos o deportes, así como para otras aplicaciones como monitorear el clima de tu ciudad entre otras muchas aplicaciones mas.
Componentes.
Pare este proyecto ocupamos los siguientes componentes.
- Pantalla TFT 1.69″ de la marca WavesShare
- ESP32
- Stand o Carcasa para la pantalla (opcional)
Carcasa para Mini TV (Opcional).
Como primer paso diseñamos un stand para la pantalla en nuestro caso lo diseñaremos para que se vea como una televisión antigua gracias a la forma rectangular de esta, este paso es opcional nosotros lo haremos así para una mejor presentación de este proyecto. En la pagina de WavesShare obtuvimos las medidas de la pantalla, buscamos una referencia de TV antigua y con esto realizamos un modelo para imprimir.


Desarrollo de la Aplicación.
En este ejemplo desarrollaremos una aplicación para ver en la mini TV los resultados de los partidos de futbol del dia en curso, para esto nuestra aplicación constara de tres partes:
- Servidor NTP, para obtener la fecha y hora.
- API-Football, para obtener los resultados de los partidos del día y los próximos partidos.
- Función Main Page, para imprimir en la pantalla la información obtenida como banderas de los equipos, resultados etc,…
Teniendo los tres puntos explicados anteriormente juntaremos todos para obtener nuestra aplicación.

Servidor NTP
A continuación explicaremos el código de programación utilizado para nuestro servidor NTP.
Iniciamos declarando las librerías Wifi y Time y enseguida ingresamos las claves de internet para la conexión por wifi del ESP32.
#include "WiFi.h" #include "time.h" // Claves internet const char* ssid = "SSID"; const char* password = "Your Password";
Enseguida configuramos el servidor para obtener la fecha y la hora, en este caso utilizaremos “pool.ntp.org” en esta parte lo mas importante es configurar el Offset en segundos de la región en la que nos encontramos utilizando el uso horario en nuestro caso la ciudad de monterrey tiene el uso horario GTM-6 para definir el Offset basta con una simple multiplicación, (-6 * 3600), -6 por el uso horario de nuestra ubicación y 3600 por los segundos que tiene una hora, esta multiplicación nos da un resultado de -21600 que es el valor que le daremos a nuestro Offset.
const char* ntpServer = "pool.ntp.org"; const long gmtOffset_sec = -21600; const int daylightOffset_sec = 0;
Por ultimo declaramos dos variables tipo string “todayDate” para almacenar la fecha actual y “fixtureReq” para almacenar el request que queremos solicitar a la API-Football.
String todayDate; String fixtureReq;
En el void setup iniciamos el serial, nos conectamos al Wifi y configuramos el servidor.
void setup() {
// Iniciar serial
Serial.begin(115200);
// Conectar al WiFi
Serial.print("Intentando conectarse a la red: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// Esperar conectarse a la red:
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
// Esperar un segundo para reintentar
delay(1000);
}
Serial.print("\nConectado a: ");
Serial.println(ssid);
// Configurar tiempo
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
}
En el void loop estaremos obteniendo el tiempo cada cinco segundos con la función “getLocalTime” dentro de esta función se declara una estructura del tipo “tm timeinfo” la cual es una estructura estándar en ANSI C con la cual obtenemos la fecha y la hora con el formato que necesitamos. Esta fecha obtenida nos servirá como parámetro en nuestro request para API-Football y así obtendremos los resultados de los partidos del día en curso.
void loop() {
// Obtener fecha y tiempo actual
getLocalTime();
delay(5000);
}
void getLocalTime(){
// Crear una estructura tm llamda timeinfo
struct tm timeinfo;
// Esperar para obtener el tiempo local
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
Serial.println("Fecha y tiempo actual:");
// Obtener la fecha
char formattedDate[16];
strftime(formattedDate, sizeof(formattedDate), "%Y-%m-%d", &timeinfo);
Serial.print("Fecha: ");
Serial.println(formattedDate);
// Obtener la hora
char formattedTime[16];
strftime(formattedTime, sizeof(formattedTime), "%H:%M", &timeinfo);
Serial.print("Hora: ");
Serial.println(formattedTime);
// Imprimir request
fixtureReq = String("/v3/fixtures?date=") + formattedDate + String("&league=4&season=2024&timezone=America%2FMonterrey");
Serial.print("Url: ");
Serial.println(fixtureReq);
}
Cargamos el codigo a la ESP32 y al final deberíamos de ver como se imprime la fecha, enseguida la hora y por ultimo el request que utilizaremos para la API-Football con la fecha que generamos con el servidor NTP.

API-Football
A continuación se muestra el código de programación para obtener los resultados de los partidos de la API-Football, por ser este muy extenso se recomiendo que vean la explicación de este en el video que mostraremos mas adelante.
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include "WiFi.h"
// Claves internet
const char* ssid = "SSID";
const char* password = "PASSWORD";
// Server api-football
const char* serverName = "api-football-v1.p.rapidapi.com";
String host = "api-football-v1.p.rapidapi.com";
String apiKey = "Your-Api-Key";
//Certificado del server
const char* test_root_ca =
"-----BEGIN CERTIFICATE-----\n"
"MIIEdTCCA12gAwIBAgIJAKcOSkw0grd/MA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV\n"
"BAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTIw\n"
"MAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0\n"
"eTAeFw0wOTA5MDIwMDAwMDBaFw0zNDA2MjgxNzM5MTZaMIGYMQswCQYDVQQGEwJV\n"
"UzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTElMCMGA1UE\n"
"ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjE7MDkGA1UEAxMyU3RhcmZp\n"
"ZWxkIFNlcnZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi\n"
"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVDDrEKvlO4vW+GZdfjohTsR8/\n"
"y8+fIBNtKTrID30892t2OGPZNmCom15cAICyL1l/9of5JUOG52kbUpqQ4XHj2C0N\n"
"Tm/2yEnZtvMaVq4rtnQU68/7JuMauh2WLmo7WJSJR1b/JaCTcFOD2oR0FMNnngRo\n"
"Ot+OQFodSk7PQ5E751bWAHDLUu57fa4657wx+UX2wmDPE1kCK4DMNEffud6QZW0C\n"
"zyyRpqbn3oUYSXxmTqM6bam17jQuug0DuDPfR+uxa40l2ZvOgdFFRjKWcIfeAg5J\n"
"Q4W2bHO7ZOphQazJ1FTfhy/HIrImzJ9ZVGif/L4qL8RVHHVAYBeFAlU5i38FAgMB\n"
"AAGjgfAwge0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O\n"
"BBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMB8GA1UdIwQYMBaAFL9ft9HO3R+G9FtV\n"
"rNzXEMIOqYjnME8GCCsGAQUFBwEBBEMwQTAcBggrBgEFBQcwAYYQaHR0cDovL28u\n"
"c3MyLnVzLzAhBggrBgEFBQcwAoYVaHR0cDovL3guc3MyLnVzL3guY2VyMCYGA1Ud\n"
"HwQfMB0wG6AZoBeGFWh0dHA6Ly9zLnNzMi51cy9yLmNybDARBgNVHSAECjAIMAYG\n"
"BFUdIAAwDQYJKoZIhvcNAQELBQADggEBACMd44pXyn3pF3lM8R5V/cxTbj5HD9/G\n"
"VfKyBDbtgB9TxF00KGu+x1X8Z+rLP3+QsjPNG1gQggL4+C/1E2DUBc7xgQjB3ad1\n"
"l08YuW3e95ORCLp+QCztweq7dp4zBncdDQh/U90bZKuCJ/Fp1U1ervShw3WnWEQt\n"
"8jxwmKy6abaVd38PMV4s/KCHOkdp8Hlf9BRUpJVeEXgSYCfOn8J3/yNTd126/+pZ\n"
"59vPr5KW7ySaNRB6nJHGDn2Z9j8Z3/VyVOEVqQdZe4O/Ui5GjLIAZHYcSNPYeehu\n"
"VsyuLAOQ1xk4meTKCRlb/weWsKh/NEnfVqn3sF/tM+2MR7cwA130A4w=\n"
"-----END CERTIFICATE-----\n";
// Datos de los requests
String fixtureReq = "/v3/fixtures?date=2024-06-30&league=4&season=2024&timezone=America/Monterrey";
String nextGamesReq = "/v3/fixtures?&league=4&season=2024&next=4&timezone=America/Monterrey";
String eventReq;
// Constantes
const int maxFixtures = 6;
const int maxGoals = 20;
// Varibles
int fixturesResults = 0;
int eventsResults = 0;
int goalsCounter = 0;
int isGameLiveSum = 0;
int todayGames = 1;
int isGameLive[maxFixtures];
int firstTeamGoalsCounterArray[maxFixtures];
int secondTeamGoalsCounterArray[maxFixtures];
String eventType;
String matchGoals;
String gameDate;
String gameTime;
String fixtureID[maxFixtures];
String eventDate[maxFixtures];
String gameStatus[maxFixtures];
String timeElapsed[maxFixtures];
String extraTime[maxFixtures];
String firstTeam[maxFixtures];
String firstTeamGoals[maxFixtures];
String firstTeamPenaltyGoals[maxFixtures];
String secondTeam[maxFixtures];
String secondTeamGoals[maxFixtures];
String secondTeamPenaltyGoals[maxFixtures];
String firstTeamPlayerGoal[maxFixtures][maxGoals];
String firstTeamMinuteGoal[maxFixtures][maxGoals];
String secondTeamPlayerGoal[maxFixtures][maxGoals];
String secondTeamMinuteGoal[maxFixtures][maxGoals];
// Definimos el cliente
WiFiClientSecure client;
void setup() {
// Iniciar serial
Serial.begin(115200);
// Conectar al WiFi
Serial.print("Intentando conectarse a la red: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// Esperar conectarse a la red:
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
// Esperar un segundo para reintentar
delay(1000);
}
Serial.print("Conectado a: ");
Serial.println(ssid);
// Configurar certificado
client.setCACert(test_root_ca);
// Realizar un fixture request con los partidos de la fecha indicada
getFixtureData(fixtureReq);
// Ver si hay partidos en la fecha indicada
if (todayGames == 0) {
// De no ser así imprimir la info de los siguientes cuatro fixtures
Serial.println("No se encontraron fixtures la fecha indicada, solicitando los siguientes cuatro partidos");
getFixtureData(nextGamesReq);
} else {
// De ser así obtener la información de los fixtures del día
Serial.print("Se encontraron ");
Serial.print(fixturesResults);
Serial.println(" fixtures la fecha indicada");
}
// Imprimir en el serial la información
printFixturesData();
// Si hay partidos en la fecha indicada obtener los eventos
if (todayGames > 0) {
for (int i = 0; i < fixturesResults; i++) {
// Construir el request de los evenfos fixture por fixture
Serial.print("Solicitando eventos del fixture: ");
Serial.println(fixtureID[i]);
eventReq = String("/v3/fixtures/events") + String("?fixture=") + fixtureID[i];
// Realizar la solicitud
getEventsData(i, eventReq);
}
// Imprimir los eventos gol en el serial
printEventsData();
}
}
void loop() {
// Si hay partidos en el día
if (todayGames == 0) {
// De no ser así obtener la información de los siguientes cuatro fixtures
getFixtureData(nextGamesReq);
} else {
// De ser así obtener la información de los fixtures del día
getFixtureData(fixtureReq);
}
// Imprimir la cantidad de fixtures encontrados con la información de los fixtures
Serial.print("Se encontraron ");
Serial.print(fixturesResults);
Serial.println(" fixtures la fecha indicada");
printFixturesData();
// Imprimir los eventos de los fixtures sólo si están en vivo
for (int i = 0; i < fixturesResults; i++) {
if (isGameLive[i]) {
Serial.print("Solicitando eventos del fixture: ");
Serial.println(fixtureID[i]);
eventReq = String("/v3/fixtures/events") + String("?fixture=") + fixtureID[i];
getEventsData(i, eventReq);
}
}
printEventsData();
// Esperar un minuto
delay(60000);
}
void getFixtureData(String req) {
String result;
//Conectar al servidor
Serial.println("\nStarting connection to server...");
client.setTimeout(15000);
if (!client.connect(serverName, 443)) {
Serial.println("Connection failed!");
return;
}
Serial.println("Connected to server!");
// Solicitud GET
client.print(String("GET ") + req + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "X-RapidAPI-Key: " + apiKey + "\r\n" + "Connection: close\r\n\r\n");
// Esperar a la respuesta del servidor
while (client.connected() && !client.available()) {
delay(10);
}
// Leer respuesta
while (client.connected() || client.available()) {
if (client.available()) {
result = client.readStringUntil('\n');
Serial.println(result);
}
}
// Cerrar la conexión
Serial.println("Closing connection");
client.stop();
// Deserializar información de la respuesta
JsonDocument doc;
DeserializationError error = deserializeJson(doc, result);
Serial.println("Deserializing api data");
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
Serial.println("Deserialize succesfull");
fixturesResults = doc["results"];
if (fixturesResults == 0 && req == fixtureReq) {
todayGames = 0;
}
int fixtureCounter = 0;
// Leer información de la respuesta por fixture
for (JsonObject response_item : doc["response"].as<JsonArray>()) {
JsonObject response_item_fixture = response_item["fixture"];
fixtureID[fixtureCounter] = String(response_item_fixture["id"]);
eventDate[fixtureCounter] = String(response_item_fixture["date"]);
JsonObject response_item_fixture_status = response_item_fixture["status"];
gameStatus[fixtureCounter] = String(response_item_fixture_status["short"]);
timeElapsed[fixtureCounter] = String(response_item_fixture_status["elapsed"]);
JsonObject response_teams = response_item["teams"];
firstTeam[fixtureCounter] = String(response_teams["home"]["name"]);
secondTeam[fixtureCounter] = String(response_teams["away"]["name"]);
firstTeamGoals[fixtureCounter] = String(response_item["goals"]["home"]);
secondTeamGoals[fixtureCounter] = String(response_item["goals"]["away"]);
for (JsonPair response_item_score_item : response_item["score"].as<JsonObject>()) {
if (response_item_score_item.key().c_str() == "penalty") {
firstTeamPenaltyGoal[fixtureCounter] = response_item_score_item.value()["home"];
secondTeamPenaltyGoal[fixtureCounter] = response_item_score_item.value()["away"];
}
}
if (gameStatus[fixtureCounter] == "1H" || gameStatus[fixtureCounter] == "2H" || gameStatus[fixtureCounter] == "ET" || gameStatus[fixtureCounter] == "P") {
isGameLive[fixtureCounter] = 1;
} else {
isGameLive[fixtureCounter] = 0;
}
fixtureCounter += 1;
}
}
void getEventsData(int fixtureNumber, String req) {
String result;
//Conectar al servidor
Serial.println("\nStarting connection to server...");
client.setTimeout(15000);
if (!client.connect(serverName, 443)) {
Serial.println("Connection failed!");
return;
}
Serial.println("Connected to server!");
// Solicitud GET
client.print(String("GET ") + req + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "X-RapidAPI-Key: " + apiKey + "\r\n" + "Connection: close\r\n\r\n");
// Esperar a la respuesta del servidor
while (client.connected() && !client.available()) {
delay(10);
}
// Leer respuesta
while (client.connected() || client.available()) {
if (client.available()) {
result = client.readStringUntil('\n');
Serial.println(result);
}
}
// Cerrar la conexión
Serial.println("Closing connection");
client.stop();
// Deserializar información de la respuesta
JsonDocument doc;
DeserializationError error = deserializeJson(doc, result);
Serial.println("Deserializing api data");
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
Serial.println("Deserialize succesfull");
int eventsCounter = 0;
int firstTeamGoalsCounter = 0;
int secondTeamGoalsCounter = 0;
String extraTime = "";
// Leer información de la respuesta por evento
for (JsonObject response_item : doc["response"].as<JsonArray>()) {
extraTime = "";
// Si el evento es tipo Goal
if (response_item["type"] == "Goal") {
JsonObject response_item_team = response_item["team"];
// Si es del primer equipo
if (firstTeam[fixtureNumber] == response_item_team["name"]) {
firstTeamPlayerGoal[fixtureNumber][firstTeamGoalsCounter] = String(response_item["player"]["name"]);
extraTime = String(response_item["time"]["extra"]);
// Si no fue en tiempo añadido
if (extraTime == "null") {
firstTeamMinuteGoal[fixtureNumber][firstTeamGoalsCounter] = String(response_item["time"]["elapsed"]) + "'";
}
// Si fue en tiempo añadido
else {
firstTeamMinuteGoal[fixtureNumber][firstTeamGoalsCounter] = String(response_item["time"]["elapsed"]) + "+" + extraTime + "'";
}
firstTeamGoalsCounter += 1;
}
// Si es del segundo equipo
if (secondTeam[fixtureNumber] == response_item_team["name"]) {
secondTeamPlayerGoal[fixtureNumber][secondTeamGoalsCounter] = String(response_item["player"]["name"]);
extraTime = String(response_item["time"]["extra"]);
// Si no fue en tiempo añadido
if (extraTime == "null") {
secondTeamMinuteGoal[fixtureNumber][secondTeamGoalsCounter] = String(response_item["time"]["elapsed"]) + "'";
}
// Si fue en tiempo añadido
else {
secondTeamMinuteGoal[fixtureNumber][secondTeamGoalsCounter] = String(response_item["time"]["elapsed"]) + "+" + extraTime + "'";
}
secondTeamGoalsCounter += 1;
}
}
}
}
void printFixturesData() {
for (int i = 0; i < fixturesResults; i++) {
Serial.print("Id: ");
Serial.println(fixtureID[i]);
Serial.print("Primer equipo: ");
Serial.println(firstTeam[i]);
Serial.print("Segundo equipo: ");
Serial.println(secondTeam[i]);
Serial.print("Date: ");
Serial.println(eventDate[i]);
Serial.print("El partido está en vivo: ");
Serial.println(isGameLive[i]);
Serial.print("Game Status: ");
Serial.println(gameStatus[i]);
Serial.print("Elapsed: ");
Serial.println(timeElapsed[i]);
Serial.print("Goles primer equipo: ");
Serial.println(firstTeamGoals[i]);
Serial.print("Goles segundo equipo: ");
Serial.println(secondTeamGoals[i]);
}
}
void printEventsData() {
for (int i = 0; i < fixturesResults; i++) {
Serial.print("Anotadores de ");
Serial.println(firstTeam[i]);
for (int j = 0; j < firstTeamGoals[i].toInt(); j++) {
Serial.print(firstTeamPlayerGoal[i][j]);
Serial.print(" ");
Serial.println(firstTeamMinuteGoal[i][j]);
}
Serial.print("Anotadores de ");
Serial.println(secondTeam[i]);
for (int j = 0; j < secondTeamGoals[i].toInt(); j++) {
Serial.print(secondTeamPlayerGoal[i][j]);
Serial.print(" ");
Serial.println(secondTeamMinuteGoal[i][j]);
}
}
}
Conexiones ESP32 – Pantalla.
A continuación se muestra las tabla para las conexiones entre el ESP32 y la Pantalla LCD de 1.69″.

Codigo de programación Pantalla.
Ahora solo nos queda realizar la programación para la pantalla LCD para esto ademas de la fecha, la hora y la información de los partidos tambien ocupamos generar las banderas de los equipos que esten jugando cada partido. Para este caso mostraremos en la pantalla los resultados de los partidos de la Eurocopa Alemania 2024, es por esto que debemos de generar la bandera de cada una de las selecciones participantes, al ser esto muy laborioso optamos por el uso de una de las herramientas mas utilizadas actualmente la Inteligencia Artificial a la cual le solicitamos nos genere el codigo para cada bander. El codigo de programación quedo de la siguiente manera:
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
// Pines TFT
#define TFT_CS 5
#define TFT_RST 32
#define TFT_DC 33
// Colores texto
#define ORANGE_TEXT 0xDAE0
#define GREY_TEXT 0xEF7D
#define BLACK_TEXT 0x31C6
#define GREEN_TEXT 0x0680
// Colores banderas
#define WHITE 0xFFFF
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
#define BLUE 0x001F
#define YELLOW 0xFFE0
#define ORANGE 0xFD20
#define PURPLE 0x780F
#define CYAN 0x07FF
#define LIGHT_BLUE 0x5D9E
// Enum de Países
enum countries {
PORTUGAL,
CZECH,
SPAIN,
FRANCE,
GERMANY,
ITALY,
ENGLAND,
GEORGIA,
SWITZERLAND,
SCOTLAND,
HUNGARY,
ROMANIA,
SLOVAKIA,
BELGIUM,
UKRAINE,
AUSTRIA,
POLAND,
NETHERLANDS,
SERBIA,
SLOVENIA,
DENMARK,
CROATIA,
ALBANIA,
TURKEY
};
// Declarar pantalla tft
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
void setup() {
// Iniciar serial
Serial.begin(115200);
// Inicializar pantalla TFT
tft.init(240, 280);
tft.setRotation(3);
tft.fillScreen(GREY_TEXT);
tft.setTextSize(3);
drawtext("Iniciando", BLACK_TEXT, 60, 110);
delay(1000);
// Mostrar página principal
mainPage();
}
void loop() {
}
// Función para imprimir texto en pantalla tft
void drawtext(String text, uint16_t color, int x, int y) {
tft.setCursor(x, y);
tft.setTextColor(color);
tft.setTextWrap(true);
tft.print(text);
}
// Funciones para dibujar banderas
void drawPortugalFlag(int x_center, int y_center) {
int radius = 20; // Radio para un diámetro de 40 píxeles
// Dibujar el fondo (verde y rojo)
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
int x_pos = x_center + x;
int y_pos = y_center + y;
if (x < 0) {
tft.drawPixel(x_pos, y_pos, GREEN);
} else {
tft.drawPixel(x_pos, y_pos, RED);
}
}
}
}
// Dibujar el círculo amarillo central (escudo)
for (int y = -10; y <= 10; y++) {
for (int x = -10; x <= 10; x++) {
if (x * x + y * y <= 10 * 10) {
tft.drawPixel(x_center - 5 + x, y_center + y, YELLOW);
}
}
}
// Dibujar el círculo rojo dentro del círculo amarillo
for (int y = -7; y <= 7; y++) {
for (int x = -7; x <= 7; x++) {
if (x * x + y * y <= 7 * 7) {
tft.drawPixel(x_center - 5 + x, y_center + y, RED);
}
}
}
// Dibujar el círculo blanco dentro del círculo rojo
for (int y = -5; y <= 5; y++) {
for (int x = -5; x <= 5; x++) {
if (x * x + y * y <= 5 * 5) {
tft.drawPixel(x_center - 5 + x, y_center + y, WHITE);
}
}
}
// Detalles del escudo (cruces azules)
for (int i = -1; i <= 1; i++) {
tft.drawPixel(x_center - 5 - 2 + i, y_center, BLUE);
tft.drawPixel(x_center - 5 + 2 + i, y_center, BLUE);
tft.drawPixel(x_center - 5 - 1, y_center - 1 + i, BLUE);
tft.drawPixel(x_center - 5 + 1, y_center - 1 + i, BLUE);
tft.drawPixel(x_center - 5, y_center - 2 + i, BLUE);
tft.drawPixel(x_center - 5, y_center + 2 + i, BLUE);
}
// Castillos amarillos
int castles[12][2] = {
{-8, -5}, {-8, 5}, {-6, -7}, {-6, 7},
{0, -7}, {0, 7}, {2, -5}, {2, 5},
{4, -5}, {4, 5}, {4, -7}, {4, 7}
};
for (int i = 0; i < 12; i++) {
tft.drawPixel(x_center - 5 + castles[i][0], y_center + castles[i][1], YELLOW);
}
}
void drawCzechFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (x < 0 && abs(x) >= abs(y)) {
tft.drawPixel(x_center + x, y_center + y, BLUE); // Triángulo azul
} else if (y <= 0) {
tft.drawPixel(x_center + x, y_center + y, WHITE); // Parte superior blanca
} else {
tft.drawPixel(x_center + x, y_center + y, RED); // Parte inferior roja
}
}
}
}
}
void drawSpainFlag(int x_center, int y_center) {
int radius = 20;
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, RED);
if (y >= -radius / 3 && y <= radius / 3) {
tft.drawPixel(x_center + x, y_center + y, YELLOW);
}
}
}
}
}
void drawFranceFlag(int x_center, int y_center) {
int radius = 20;
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (x < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, BLUE);
} else if (x > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
}
void drawGermanyFlag(int x_center, int y_center) {
int radius = 20;
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, BLACK);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, YELLOW);
} else {
tft.drawPixel(x_center + x, y_center + y, RED);
}
}
}
}
}
void drawItalyFlag(int x_center, int y_center) {
int radius = 20;
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (x < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, GREEN);
} else if (x > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
}
void drawEnglandFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
int cross_thickness = 6; // Grosor de la cruz
// Dibujar el círculo blanco de fondo
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
// Dibujar la línea vertical de la cruz
for (int i = -radius; i <= radius; i++) {
for (int j = -cross_thickness / 2; j <= cross_thickness / 2; j++) {
if ((i * i + j * j) <= radius * radius) {
tft.drawPixel(x_center + j, y_center + i, RED);
}
}
}
// Dibujar la línea horizontal de la cruz
for (int i = -radius; i <= radius; i++) {
for (int j = -cross_thickness / 2; j <= cross_thickness / 2; j++) {
if ((i * i + j * j) <= radius * radius) {
tft.drawPixel(x_center + i, y_center + j, RED);
}
}
}
}
void drawGeorgiaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
// Dibujar la cruz central
for (int i = -radius; i <= radius; i++) {
if (i * i <= radius * radius) {
// Línea vertical de la cruz central
tft.drawPixel(x_center, y_center + i, RED);
tft.drawPixel(x_center - 1, y_center + i, RED);
tft.drawPixel(x_center + 1, y_center + i, RED);
// Línea horizontal de la cruz central
tft.drawPixel(x_center + i, y_center, RED);
tft.drawPixel(x_center + i, y_center - 1, RED);
tft.drawPixel(x_center + i, y_center + 1, RED);
}
}
// Dibujar las cuatro cruces pequeñas
int cross_size = 3;
int cross_offset = radius / 2;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
if (abs(dx) + abs(dy) == 1) {
for (int i = -cross_size; i <= cross_size; i++) {
// Cruces pequeñas superior izquierda
tft.drawPixel(x_center - cross_offset + dx * cross_size, y_center - cross_offset + dy * cross_size + i, RED);
tft.drawPixel(x_center - cross_offset + dx * cross_size + i, y_center - cross_offset + dy * cross_size, RED);
// Cruces pequeñas superior derecha
tft.drawPixel(x_center + cross_offset + dx * cross_size, y_center - cross_offset + dy * cross_size + i, RED);
tft.drawPixel(x_center + cross_offset + dx * cross_size + i, y_center - cross_offset + dy * cross_size, RED);
// Cruces pequeñas inferior izquierda
tft.drawPixel(x_center - cross_offset + dx * cross_size, y_center + cross_offset + dy * cross_size + i, RED);
tft.drawPixel(x_center - cross_offset + dx * cross_size + i, y_center + cross_offset + dy * cross_size, RED);
// Cruces pequeñas inferior derecha
tft.drawPixel(x_center + cross_offset + dx * cross_size, y_center + cross_offset + dy * cross_size + i, RED);
tft.drawPixel(x_center + cross_offset + dx * cross_size + i, y_center + cross_offset + dy * cross_size, RED);
}
}
}
}
}
void drawSwitzerlandFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo rojo de fondo
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, RED);
}
}
}
// Dibujar la cruz blanca
int cross_size = 5;
for (int i = -cross_size; i <= cross_size; i++) {
tft.drawPixel(x_center, y_center + i, WHITE);
tft.drawPixel(x_center + i, y_center, WHITE);
if (abs(i) <= 2) {
tft.drawPixel(x_center - 2, y_center + i, WHITE);
tft.drawPixel(x_center + 2, y_center + i, WHITE);
tft.drawPixel(x_center + i, y_center - 2, WHITE);
tft.drawPixel(x_center + i, y_center + 2, WHITE);
}
}
}
void drawScotlandFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo azul de fondo
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, LIGHT_BLUE);
}
}
}
// Dibujar las dos cruces diagonales blancas
int width = 4; // Ancho de la cruz
for (int i = -radius; i <= radius; i++) {
for (int j = -width; j <= width; j++) {
// Diagonal positiva
int x1 = i;
int y1 = i + j;
if (x1 * x1 + y1 * y1 <= radius * radius) {
tft.drawPixel(x_center + x1, y_center + y1, WHITE);
}
// Diagonal negativa
int x2 = i;
int y2 = -i + j;
if (x2 * x2 + y2 * y2 <= radius * radius) {
tft.drawPixel(x_center + x2, y_center + y2, WHITE);
}
}
}
}
void drawHungaryFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, GREEN);
} else {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
}
void drawRomaniaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (x < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, BLUE);
} else if (x > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else {
tft.drawPixel(x_center + x, y_center + y, YELLOW);
}
}
}
}
}
void drawSlovakiaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo de fondo de la bandera
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, WHITE);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else {
tft.drawPixel(x_center + x, y_center + y, BLUE);
}
}
}
}
// Dibujar el escudo simplificado
int shield_width = 10;
int shield_height = 12;
int shield_x = x_center - radius / 2; // Posicionarlo hacia la izquierda
int shield_y = y_center - radius / 3; // Posicionarlo ligeramente hacia arriba
// Dibujar el contorno del escudo con una parte inferior redondeada
for (int y = 0; y <= shield_height; y++) {
for (int x = 0; x <= shield_width; x++) {
if (x == 0 || x == shield_width || y == 0 || (y == shield_height && (x > 1 && x < shield_width - 1)) ||
(y > shield_height - 3 && (x == 1 || x == shield_width - 1))) {
tft.drawPixel(shield_x + x, shield_y + y, WHITE);
} else {
tft.drawPixel(shield_x + x, shield_y + y, RED);
}
}
}
// Dibujar la cruz blanca en el escudo
for (int y = 2; y <= 10; y++) {
for (int x = 4; x <= 5; x++) {
tft.drawPixel(shield_x + x, shield_y + y, WHITE);
}
}
for (int y = 4; y <= 5; y++) {
for (int x = 2; x <= 7; x++) {
tft.drawPixel(shield_x + x, shield_y + y, WHITE);
}
}
// Dibujar las montañas azules en el escudo
for (int y = 8; y <= 10; y++) {
for (int x = 3; x <= 6; x++) {
tft.drawPixel(shield_x + x, shield_y + y, BLUE);
}
}
}
void drawBelgiumFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (x < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, BLACK);
} else if (x > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else {
tft.drawPixel(x_center + x, y_center + y, YELLOW);
}
}
}
}
}
void drawUkraineFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < 0) {
tft.drawPixel(x_center + x, y_center + y, BLUE);
} else {
tft.drawPixel(x_center + x, y_center + y, YELLOW);
}
}
}
}
}
void drawAustriaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
}
void drawPolandFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < 0) {
tft.drawPixel(x_center + x, y_center + y, WHITE);
} else {
tft.drawPixel(x_center + x, y_center + y, RED);
}
}
}
}
}
void drawNetherlandsFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, BLUE);
} else {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
}
void drawSerbiaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo de fondo de la bandera
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, BLUE);
} else {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
// Dibujar el escudo simplificado
int shield_radius = 6;
int shield_center_x = x_center - radius / 3; // Posicionarlo hacia la izquierda
int shield_center_y = y_center - radius / 4; // Posicionarlo ligeramente hacia arriba
// Dibujar el contorno del escudo
for (int y = -shield_radius; y <= shield_radius; y++) {
for (int x = -shield_radius; x <= shield_radius; x++) {
if (x * x + y * y <= shield_radius * shield_radius) {
tft.drawPixel(shield_center_x + x, shield_center_y + y, RED);
}
}
}
// Dibujar la cruz blanca en el escudo
int cross_size = 2;
for (int y = -cross_size; y <= cross_size; y++) {
for (int x = -cross_size; x <= cross_size; x++) {
tft.drawPixel(shield_center_x + x, shield_center_y + y, WHITE);
}
}
// Dibujar las coronas amarillas en el escudo
int crown_radius = 3;
for (int y = -crown_radius; y <= crown_radius; y++) {
for (int x = -crown_radius; x <= crown_radius; x++) {
if (x * x + y * y <= crown_radius * crown_radius) {
tft.drawPixel(shield_center_x + x, shield_center_y - 8 + y, YELLOW);
}
}
}
// Dibujar el águila blanca simplificada en el escudo
int eagle_width = 4;
for (int y = -eagle_width; y <= eagle_width; y++) {
for (int x = -eagle_width; x <= eagle_width; x++) {
if (abs(x) == eagle_width || abs(y) == eagle_width || (abs(x) <= 2 && abs(y) <= 2)) {
tft.drawPixel(shield_center_x + x, shield_center_y + y, WHITE);
}
}
}
}
void drawSloveniaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo de fondo de la bandera
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, WHITE);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else {
tft.drawPixel(x_center + x, y_center + y, LIGHT_BLUE);
}
}
}
}
// Dibujar el escudo simplificado
int shield_radius = 6;
int shield_center_x = x_center - radius / 3; // Posicionarlo hacia la izquierda
int shield_center_y = y_center - radius / 3; // Posicionarlo ligeramente hacia arriba
// Dibujar el contorno del escudo
for (int y = -shield_radius; y <= shield_radius; y++) {
for (int x = -shield_radius; x <= shield_radius; x++) {
if (x * x + y * y <= shield_radius * shield_radius) {
tft.drawPixel(shield_center_x + x, shield_center_y + y, BLUE);
}
}
}
// Dibujar las montañas blancas en el escudo
int mountain_height = 3;
for (int y = -mountain_height; y <= mountain_height; y++) {
for (int x = -mountain_height; x <= mountain_height; x++) {
if (y == -x || y == x || y == mountain_height) {
tft.drawPixel(shield_center_x + x, shield_center_y + y, WHITE);
}
}
}
// Dibujar las estrellas amarillas en el escudo
int star_points[5][2] = { { 0, -2 }, { 1, 0 }, { 2, 0 }, { 1, 1 }, { 0, 1 } };
for (int i = 0; i < 5; i++) {
tft.drawPixel(shield_center_x + star_points[i][0], shield_center_y - 5 + star_points[i][1], YELLOW);
tft.drawPixel(shield_center_x + star_points[i][0] - 2, shield_center_y - 4 + star_points[i][1], YELLOW);
tft.drawPixel(shield_center_x + star_points[i][0] + 2, shield_center_y - 4 + star_points[i][1], YELLOW);
}
}
void drawDenmarkFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo rojo de fondo
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, RED);
}
}
}
// Dibujar la cruz blanca
int cross_thickness = 6; // Grosor de la cruz
int cross_offset = 2; // Desplazamiento de la línea horizontal de la cruz hacia arriba
// Dibujar la línea vertical de la cruz
for (int i = -radius; i <= radius; i++) {
for (int j = -cross_thickness / 2; j <= cross_thickness / 2; j++) {
if ((i * i + j * j) <= radius * radius) {
tft.drawPixel(x_center + j - cross_offset, y_center + i, WHITE);
}
}
}
// Dibujar la línea horizontal de la cruz
for (int i = -radius; i <= radius; i++) {
for (int j = -cross_thickness / 2; j <= cross_thickness / 2; j++) {
if ((i * i + j * j) <= radius * radius) {
tft.drawPixel(x_center + i, y_center + j, WHITE);
}
}
}
}
void drawCroatiaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo y la bandera dentro de él
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
if (y < -radius / 3) {
tft.drawPixel(x_center + x, y_center + y, RED);
} else if (y > radius / 3) {
tft.drawPixel(x_center + x, y_center + y, BLUE);
} else {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
// Dibujar el escudo central simplificado
int shield_radius = 5;
for (int y = -shield_radius; y <= shield_radius; y++) {
for (int x = -shield_radius; x <= shield_radius; x++) {
if (x * x + y * y <= shield_radius * shield_radius) {
tft.drawPixel(x_center + x, y_center + y, RED);
if ((x + y) % 2 == 0) {
tft.drawPixel(x_center + x, y_center + y, WHITE);
}
}
}
}
}
void drawAlbaniaFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo rojo de fondo
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, RED);
}
}
}
// Dibujar el águila negra simplificada (rectángulo negro en el centro)
for (int y = -5; y <= 5; y++) {
for (int x = -5; x <= 5; x++) {
tft.drawPixel(x_center + x, y_center + y, BLACK);
}
}
}
void drawTurkeyFlag(int x_center, int y_center) {
int radius = 20; // 40 pixels diameter, radius is half
// Dibujar el círculo rojo de fondo
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
tft.drawPixel(x_center + x, y_center + y, RED);
}
}
}
// Dibujar el semicírculo blanco (luna)
int moon_radius_outer = 8;
int moon_radius_inner = 6;
int moon_offset_x = -5; // Offset para centrar la luna a la izquierda
for (int y = -moon_radius_outer; y <= moon_radius_outer; y++) {
for (int x = -moon_radius_outer; x <= moon_radius_outer; x++) {
if (x * x + y * y <= moon_radius_outer * moon_radius_outer) {
tft.drawPixel(x_center + moon_offset_x + x, y_center + y, WHITE);
}
}
}
for (int y = -moon_radius_inner; y <= moon_radius_inner; y++) {
for (int x = -moon_radius_inner; x <= moon_radius_inner; x++) {
if (x * x + y * y <= moon_radius_inner * moon_radius_inner) {
tft.drawPixel(x_center + moon_offset_x + 2 + x, y_center + y, RED);
}
}
}
// Dibujar la estrella blanca inclinada
int star_center_x = x_center + 7;
int star_center_y = y_center - 3;
int star_size = 3; // Tamaño de la estrella
// Coordenadas relativas de la estrella inclinada hacia la izquierda
int star_points[10][2] = {
{ 0, -star_size }, { star_size / 2, -star_size / 2 }, { star_size, -star_size }, { star_size / 2, star_size / 2 }, { star_size, star_size }, { 0, star_size / 2 }, { -star_size, star_size }, { -star_size / 2, star_size / 2 }, { -star_size, -star_size }, { -star_size / 2, -star_size / 2 }
};
for (int i = 0; i < 10; i++) {
tft.drawPixel(star_center_x + star_points[i][0], star_center_y + star_points[i][1], WHITE);
}
}
// Crear array de funciones
typedef void (*DrawFlagArray)(int, int);
DrawFlagArray drawFlagArray[] = {
drawPortugalFlag,
drawCzechFlag,
drawSpainFlag,
drawFranceFlag,
drawGermanyFlag,
drawItalyFlag,
drawEnglandFlag,
drawGeorgiaFlag,
drawSwitzerlandFlag,
drawScotlandFlag,
drawHungaryFlag,
drawRomaniaFlag,
drawSlovakiaFlag,
drawBelgiumFlag,
drawUkraineFlag,
drawAustriaFlag,
drawPolandFlag,
drawNetherlandsFlag,
drawSerbiaFlag,
drawSloveniaFlag,
drawDenmarkFlag,
drawCroatiaFlag,
drawAlbaniaFlag,
drawTurkeyFlag
};
// Obtener el valor de la posición del array de funciones de la bandera deseada
countries getCountry(String country) {
if (country == "Portugal") return PORTUGAL;
if (country == "Czech Republic") return CZECH;
if (country == "Spain") return SPAIN;
if (country == "France") return FRANCE;
if (country == "Germany") return GERMANY;
if (country == "Italy") return ITALY;
if (country == "England") return ENGLAND;
if (country == "Georgia") return GEORGIA;
if (country == "Switzerland") return SWITZERLAND;
if (country == "Scotland") return SCOTLAND;
if (country == "Hungary") return HUNGARY;
if (country == "Romania") return ROMANIA;
if (country == "Slovakia") return SLOVAKIA;
if (country == "Belgium") return BELGIUM;
if (country == "Ukraine") return UKRAINE;
if (country == "Austria") return AUSTRIA;
if (country == "Poland") return POLAND;
if (country == "Netherlands") return NETHERLANDS;
if (country == "Serbia") return SERBIA;
if (country == "Slovenia") return SLOVENIA;
if (country == "Denmark") return DENMARK;
if (country == "Croatia") return CROATIA;
if (country == "Albania") return ALBANIA;
if (country == "Türkiye") return TURKEY;
return PORTUGAL; // Default case, handle as needed
}
// Dibujar bandera con switch case
void drawFlag(String flag, int x, int y) {
countries country = getCountry(flag);
switch (country) {
case GERMANY:
drawFlagArray[GERMANY](x, y);
break;
case ALBANIA:
drawFlagArray[ALBANIA](x, y);
break;
case AUSTRIA:
drawFlagArray[AUSTRIA](x, y);
break;
case BELGIUM:
drawFlagArray[BELGIUM](x, y);
break;
case CROATIA:
drawFlagArray[CROATIA](x, y);
break;
case CZECH:
drawFlagArray[CZECH](x, y);
break;
case DENMARK:
drawFlagArray[DENMARK](x, y);
break;
case ENGLAND:
drawFlagArray[ENGLAND](x, y);
break;
case FRANCE:
drawFlagArray[FRANCE](x, y);
break;
case GEORGIA:
drawFlagArray[GEORGIA](x, y);
break;
case HUNGARY:
drawFlagArray[HUNGARY](x, y);
break;
case ITALY:
drawFlagArray[ITALY](x, y);
break;
case NETHERLANDS:
drawFlagArray[NETHERLANDS](x, y);
break;
case POLAND:
drawFlagArray[POLAND](x, y);
break;
case PORTUGAL:
drawFlagArray[PORTUGAL](x, y);
break;
case ROMANIA:
drawFlagArray[ROMANIA](x, y);
break;
case SCOTLAND:
drawFlagArray[SCOTLAND](x, y);
break;
case SERBIA:
drawFlagArray[SERBIA](x, y);
break;
case SLOVAKIA:
drawFlagArray[SLOVAKIA](x, y);
break;
case SLOVENIA:
drawFlagArray[SLOVENIA](x, y);
break;
case SPAIN:
drawFlagArray[SPAIN](x, y);
break;
case SWITZERLAND:
drawFlagArray[SWITZERLAND](x, y);
break;
case TURKEY:
drawFlagArray[TURKEY](x, y);
break;
case UKRAINE:
drawFlagArray[UKRAINE](x, y);
break;
default:
Serial.println("País no reconocido");
break;
}
}
// Imprimir página principal tft
void mainPage() {
Serial.print("Mostrando partido de ");
Serial.println("Portugal vs Georgia");
// EURO2024
tft.fillScreen(BLACK_TEXT);
tft.setTextSize(4);
drawtext("EURO2024", GREY_TEXT, 47, 6);
// Fecha
tft.setTextSize(2);
tft.fillRoundRect(70, 45, 140, 20, 4, ORANGE_TEXT);
drawtext("2024-06-30", BLACK_TEXT, 80, 48);
// Hora a empezar /Minutos / Finalizado
tft.setTextSize(2);
drawtext("13:00", ORANGE_TEXT, 110, 80);
// Marcador
tft.setTextSize(5);
drawtext(" - ", GREY_TEXT, 68, 100);
// Banderas
drawFlag("Portugal", 30, 116);
drawFlag("Georgia", 245, 116);
//Nombre de jugadores que anotaron con minuto
tft.setTextSize(1.5);
drawtext("Quaresma", GREY_TEXT, 10, 150);
drawtext("2'", GREY_TEXT, 110, 150);
drawtext("L. Dvali", GREY_TEXT, 145, 150);
drawtext("1'", GREY_TEXT, 240, 150);
}

Para comprender de mejor manera este código se recomienda ver el video explicativo que les dejaremos en esta entrada mas adelante.
Codigo Final
Para esta parte solo basta con juntar los tres códigos generados anteriormente con la diferencia que la declaración de las funciones y demás se agregaron a un archivo .h llamado “Football_Data.h” y en el código principal queda solo la aplicación. Todos los archivos utilizados en este proyecto se dejaran en un enlace de descarga mas adelante.
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include "WiFi.h"
#include "Football_Data.h"
#include "time.h"
void setup(void) {
// Iniciar serial
Serial.begin(115200);
// Conectar al WiFi
Serial.print("Intentando conectarse a la red: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// Esperar conectarse a la red:
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
// Esperar un segundo para reintentar
delay(1000);
}
Serial.print("Conectado a: ");
Serial.println(ssid);
// Inicializar pantalla TFT
tft.init(240, 280);
tft.setRotation(3);
tft.fillScreen(GREY_TEXT);
tft.setTextSize(3);
testdrawtext("Iniciando", BLACK_TEXT, 55, 100);
delay(1000);
// Init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
getLocalTime();
// Configurar certificado
client.setCACert(test_root_ca);
getFixtureData(fixtureReq);
// Ver si hay partidos en la fecha indicada
if (todayGames == 0) {
// De no ser así imprimir la info de los siguientes cuatro fixtures
Serial.println("No se encontraron fixtures la fecha indicada, solicitando los siguientes cuatro partidos");
getFixtureData(nextGamesReq);
} else if (nextGames == 0) {
// De ser así obtener la información de los fixtures del día
Serial.println("No se encontraron próximos fixtures, solicitando los últimos cuatro partidos");
getFixtureData(lastGamesReq);
} else {
Serial.print("Se encontraron ");
Serial.print(fixturesResults);
Serial.println(" fixtures la fecha indicada");
}
// Imprimir en el serial la información
printFixturesData();
// Si hay partidos en la fecha indicada obtener los eventos
if (nextGames == 1) {
for (int i = 0; i < fixturesResults; i++) {
// Construir el request de los evenfos fixture por fixture
Serial.print("Solicitando eventos del fixture: ");
Serial.println(fixtureID[i]);
eventsReq = String("/v3/fixtures/events") + String("?fixture=") + fixtureID[i];
// Realizar la solicitud
getEventsData(i, eventsReq);
}
// Imprimir los eventos gol en el serial
printEventsData();
}
mainPage();
maxRequestsCounter = round((60 / (fixturesResults * 8)));
}
void loop() {
getLocalTime();
if (requestCounter > maxRequestsCounter) {
requestCounter = 0;
}
mainPage();
requestCounter += 1;
}
void mainPage() {
for (int i = 0; i < fixturesResults; i++) {
String startTime = extractTime(eventDate[i]);
if ((isGameLive[i] || (localTime.substring(0, 2) == startTime.substring(0, 2))) && (requestCounter == maxRequestsCounter)) {
getFixtureData(fixtureReq);
Serial.print("Fuxture en vivo: ");
Serial.println(isGameLive[i]);
eventsReq = String("/v3/fixtures/events") + String("?fixture=") + fixtureID[i];
Serial.print("Solicitando el siguiente request: ");
Serial.println(eventsReq);
getEventsData(i, eventsReq);
// ExtraTime
if (((timeElapsed[i] == "45") && (maxTimeReached[i] == 0)) || ((timeElapsed[i] == "90") && (maxTimeReached[i] == 0))) {
int extraTimeHourStart = localTime.substring(0, 2).toInt();
int extraTimeMinuteStart = localTime.substring(3).toInt();
extraTimeStart[i] = (extraTimeHourStart * 60) + (extraTimeMinuteStart);
maxTimeReached[i] = 1;
}
} else {
delay(8000);
}
//
printFixturesData();
printEventsData();
Serial.print("Mostrando partido de ");
Serial.println(firstTeam[i] + " vs " + secondTeam[i]);
// EURO2024
tft.fillScreen(BLACK_TEXT);
tft.setTextSize(4);
testdrawtext("EURO2024", GREY_TEXT, 47, 6);
// Fecha
tft.setTextSize(2);
tft.fillRoundRect(70, 45, 140, 20, 4, ORANGE_TEXT);
gameDate = extractDate(eventDate[i]);
testdrawtext(gameDate, BLACK_TEXT, 80, 48);
// Hora a empezar /Minutos / Finalizado
tft.setTextSize(2);
if (gameStatus[i] == "NS") {
gameTime = extractTime(eventDate[i]);
testdrawtext(gameTime, GREY_TEXT, 110, 80);
} else if (gameStatus[i] == "FT" || gameStatus[i] == "AET" || gameStatus[i] == "PEN") {
testdrawtext("Finalizado", ORANGE_TEXT, 85, 80);
maxTimeReached[i] = 0;
} else if (gameStatus[i] == "1H" || gameStatus[i] == "2H" || gameStatus[i] == "ET") {
Serial.print("MaxTimeReached");
Serial.println(maxTimeReached[i]);
localTimeMinutes = (localTime.substring(0, 2).toInt() * 60) + localTime.substring(3).toInt();
extratimeElapsed[i] = String(localTimeMinutes - extraTimeStart[i]);
Serial.print("MaxTimeReached");
Serial.println(localTimeMinutes);
Serial.print("MaxTimeReached");
Serial.println(extratimeElapsed[i]);
if (maxTimeReached[i] == 0 || extratimeElapsed[i] == "0") {
testdrawtext(timeElapsed[i] + "'", GREEN_TEXT, 130, 80);
}
else
{
testdrawtext(timeElapsed[i] + "+" + extratimeElapsed[i] + "'", GREEN_TEXT, 115, 80);
}
} else if (gameStatus[i] == "BT") {
testdrawtext("Descanso", GREEN_TEXT, 100, 80);
maxTimeReached[i] = 0;
} else if (gameStatus[i] == "P") {
testdrawtext("Penalties", GREEN_TEXT, 90, 80);
maxTimeReached[i] = 0;
} else if (gameStatus[i] == "HT") {
testdrawtext("Medio Tiempo", GREEN_TEXT, 68, 80);
maxTimeReached[i] = 0;
}
// Marcador
tft.setTextSize(5);
if (firstTeamGoals[i] == "null" && secondTeamGoals[i] == "null") {
testdrawtext(" - ", GREY_TEXT, 68, 100);
} else {
matchGoals = firstTeamGoals[i] + " - " + secondTeamGoals[i];
testdrawtext(matchGoals, GREY_TEXT, 68, 100);
}
// En caso de penalties
if (gameStatus[i] == "PEN" || gameStatus[i] == "P") {
matchGoals = firstTeamPenaltyGoals[i] + " - " + secondTeamPenaltyGoals[i];
tft.setTextSize(1);
testdrawtext("PEN", GREY_TEXT, 131, 125);
tft.setTextSize(2);
testdrawtext(matchGoals, GREY_TEXT, 111, 130);
}
// Banderas
drawFlag(firstTeam[i], 30, 116);
drawFlag(secondTeam[i], 245, 116);
//Nombre Jugadores Primer equipo
tft.setTextSize(1.5);
for (int counter = 0; counter < firstTeamGoals[i].toInt(); counter++) {
testdrawtext(firstTeamPlayerGoal[i][counter], GREY_TEXT, 10, 150 + (playerYGap * counter));
testdrawtext(firstTeamMinuteGoal[i][counter], GREY_TEXT, 110, 150 + (playerYGap * counter));
}
for (int counter = 0; counter < secondTeamGoals[i].toInt(); counter++) {
testdrawtext(secondTeamPlayerGoal[i][counter], GREY_TEXT, 145, 150 + (playerYGap * counter));
testdrawtext(secondTeamMinuteGoal[i][counter], GREY_TEXT, 240, 150 + (playerYGap * counter));
}
}
}
Con esto terminamos nuestra aplicación para ver los resultados en vivo de los partidos de la Eurocopa 2024.

Video Explicativo.
No olviden dar like y subscribirse.
Enlace de descarga.
Enlace de descarga con todos los archivos utilizados en este proyecto.
https://mega.nz/file/OBA1URxA#xllk997bwGeilh5YaOV4ubNh6tU8NOX6_tyKHgbutNY
Contacto.
Si quieres que te ayude en algún proyecto:
ignacio.aguilera.contacto@gmail.com