// =========================================================================
// == PROYECTO TAREA 6: SECUENCIA DE BARRIDO (VERSIÓN CORREGIDA) ==
// =========================================================================
// Autor: Josue Cardenas Aguirre (Adaptado por Gemini)
// Descripción: Simulación de 16 LEDs donde un patrón de 4 luces se
// desplaza de izquierda a derecha y viceversa.
// =========================================================================
// --- LIBRERÍAS ---
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_SSD1306.h>
// =========================================================================
// == CONFIGURACIÓN GENERAL ==
// =========================================================================
// --- PINES DE CONEXIÓN ---
#define TFT_CS 15
#define TFT_DC 2
#define TFT_RST 4
#define POT_PIN 34
// --- CONFIGURACIÓN OLED ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
// --- CONFIGURACIÓN DE LA ANIMACIÓN ---
const int NUM_LEDS = 16;
const int SPEED_MIN = 50;
const int SPEED_MAX = 400;
// --- CONFIGURACIÓN VISUAL (TFT) ---
#define FOOTER_HEIGHT 40
#define COLOR_BACKGROUND ILI9341_YELLOW
#define COLOR_FOOTER 0x2104 // Azul oscuro
#define COLOR_TEXT_TITLE ILI9341_WHITE
#define COLOR_TEXT_AUTHOR ILI9341_LIGHTGREY
#define COLOR_LED_ON ILI9341_BLUE
#define COLOR_LED_OFF ILI9341_WHITE
#define COLOR_BORDER 0x4A49 // Borde oscuro
const int LED_DIAMETER = 12;
const int LED_SPACING = 4;
// =========================================================================
// == INSTANCIAS Y VARIABLES ==
// =========================================================================
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
enum AnimationState { MOVING_RIGHT, MOVING_LEFT };
AnimationState currentState = MOVING_RIGHT;
const char* statusMessage = "Ida ->";
unsigned long lastUpdateTime = 0;
int animationStep = 0; // Representa el patrón actual (0, 1, 2, o 3)
long cycleCount = 0;
int startX, startY;
// =========================================================================
// == FUNCIONES DE VISUALIZACIÓN ==
// =========================================================================
void drawTFTFooter() {
tft.fillRect(0, tft.height() - FOOTER_HEIGHT, tft.width(), FOOTER_HEIGHT, COLOR_FOOTER);
tft.setTextSize(2);
tft.setTextColor(COLOR_TEXT_TITLE);
tft.setCursor(35, tft.height() - 28);
tft.print("Control de 16 leds");
tft.setTextSize(1);
tft.setTextColor(COLOR_TEXT_AUTHOR);
tft.setCursor(80, tft.height() - 12);
tft.print("JOSUE CARDENAS AGUIRRE");
}
void updateOLED(long speed_ms) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
int speedPercent = map(speed_ms, SPEED_MAX, SPEED_MIN, 0, 100);
display.setCursor(0, 2);
display.print("Velocidad: ");
display.print(speedPercent);
display.print("% (");
display.print(speed_ms);
display.print("ms)");
int barWidth = map(speedPercent, 0, 100, 0, 100);
display.drawRect(14, 15, 102, 8, SSD1306_WHITE);
display.fillRect(15, 16, barWidth, 6, SSD1306_WHITE);
display.setCursor(0, 32);
display.print("Direccion: ");
display.print(statusMessage);
display.setCursor(0, 48);
display.print("Patron/Paso: ");
display.print(animationStep);
display.display();
}
void drawPattern(int step) {
// Primero, apagar todos los LEDs
for (int i = 0; i < NUM_LEDS; i++) {
drawLed(i, COLOR_LED_OFF);
}
// Luego, encender los 4 LEDs del patrón actual
for (int i = 0; i < 4; i++) {
drawLed(step + (i * 4), COLOR_LED_ON);
}
}
void drawLed(int index, uint16_t fillColor) {
int ledX_center = startX + index * (LED_DIAMETER + LED_SPACING) + LED_DIAMETER / 2;
tft.fillCircle(ledX_center, startY, LED_DIAMETER / 2, fillColor);
tft.drawCircle(ledX_center, startY, LED_DIAMETER / 2, COLOR_BORDER);
}
// =========================================================================
// == PROGRAMA PRINCIPAL ==
// =========================================================================
void setup() {
tft.begin();
tft.setRotation(1);
tft.fillScreen(COLOR_BACKGROUND);
drawTFTFooter();
int totalLedsWidth = NUM_LEDS * LED_DIAMETER + (NUM_LEDS - 1) * LED_SPACING;
int drawingAreaHeight = tft.height() - FOOTER_HEIGHT;
startX = (tft.width() - totalLedsWidth) / 2;
startY = (drawingAreaHeight / 2);
// Dibujar el estado inicial
drawPattern(animationStep);
Wire.begin();
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { for(;;); }
}
void loop() {
long animationInterval = map(analogRead(POT_PIN), 0, 4095, SPEED_MAX, SPEED_MIN);
updateOLED(animationInterval);
if (millis() - lastUpdateTime < animationInterval) return;
lastUpdateTime = millis();
// ** LÓGICA CORREGIDA PARA EL MOVIMIENTO **
switch (currentState) {
case MOVING_RIGHT:
animationStep++;
if (animationStep > 3) {
// Al llegar al final (paso 3), el siguiente paso debe ser el 2
animationStep = 2;
currentState = MOVING_LEFT;
statusMessage = "<- Vuelta";
}
break;
case MOVING_LEFT:
animationStep--;
if (animationStep < 0) {
// Al llegar al inicio (paso 0), el siguiente paso debe ser el 1
animationStep = 1;
currentState = MOVING_RIGHT;
statusMessage = "Ida ->";
cycleCount++;
}
break;
}
// Dibujar el patrón correspondiente al nuevo paso
drawPattern(animationStep);
}