/* * ============================================================ * 3.5" TFT LCD Shield Test — ESP32 Heltec WiFi * Driver: ILI9486 / ILI9481 (common on 3.5" MCUFRIEND shield) * Libraries needed: * - Adafruit_GFX (Library Manager) * - MCUFRIEND_kbv (Library Manager) * ============================================================ * * WIRING (8-bit parallel — shield pins → ESP32 GPIO): TFT Shield Heltec V3 LCD_RST GPIO48 LCD_CS GPIO47 LCD_RS (DC) GPIO21 LCD_WR GPIO20 LCD_RD GPIO19 LCD_D0 GPIO1 LCD_D1 GPIO2 LCD_D2 GPIO3 LCD_D3 GPIO4 LCD_D4 GPIO5 LCD_D5 GPIO6 LCD_D6 GPIO7 LCD_D7 GPIO8 GND GND 3V3 3.3V * * NOTE: If you're using the shield on a dedicated adapter/PCB * for Heltec, adjust GPIO numbers to match your adapter. * Shield backlight (BL/LED) → 3.3V or GPIO with PWM. * ============================================================ */ #include #include MCUFRIEND_kbv tft; // ── Color shortcuts ────────────────────────────────────────── #define BLACK 0x0000 #define WHITE 0xFFFF #define RED 0xF800 #define GREEN 0x07E0 #define BLUE 0x001F #define YELLOW 0xFFE0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define ORANGE 0xFD20 // ── Test helpers ────────────────────────────────────────────── void fillColorTest(); void drawGridTest(); void textTest(); void drawShapesTest(); void touchReadTest(); // ───────────────────────────────────────────────────────────── void setup() { Serial.begin(115200); Serial.println("\n=== TFT LCD Shield Test — ESP32 Heltec ==="); // Auto-detect driver ID uint16_t ID = tft.readID(); Serial.print("Driver ID: 0x"); Serial.println(ID, HEX); if (ID == 0xD3D3) { ID = 0x9486; // Most 3.5" shields use ILI9486 Serial.println("Forcing ILI9486 (write-only display)"); } tft.begin(ID); tft.setRotation(1); // Landscape: 0=Portrait, 1=Landscape, 2=Portrait flip, 3=Landscape flip Serial.print("Screen size: "); Serial.print(tft.width()); Serial.print(" x "); Serial.println(tft.height()); } // ───────────────────────────────────────────────────────────── void loop() { // ── TEST 1: Full-screen color fills ── fillColorTest(); delay(500); // ── TEST 2: Grid lines ── drawGridTest(); delay(1500); // ── TEST 3: Text rendering ── textTest(); delay(2000); // ── TEST 4: Geometric shapes ── drawShapesTest(); delay(2000); // ── TEST 5: Gradient bar ── gradientTest(); delay(2000); // ── TEST 6: TrailNav splash ── trailNavSplash(); delay(3000); } // ───────────────────────────────────────────────────────────── // TEST 1 — Color fills // ───────────────────────────────────────────────────────────── void fillColorTest() { uint16_t colors[] = { RED, GREEN, BLUE, YELLOW, CYAN, MAGENTA, WHITE, BLACK }; const char* names[] = { "RED","GREEN","BLUE","YELLOW","CYAN","MAGENTA","WHITE","BLACK" }; for (uint8_t i = 0; i < 8; i++) { tft.fillScreen(colors[i]); tft.setCursor(10, tft.height() / 2 - 8); tft.setTextColor(colors[i] == WHITE ? BLACK : WHITE); tft.setTextSize(3); tft.print(names[i]); Serial.print("Color: "); Serial.println(names[i]); delay(400); } } // ───────────────────────────────────────────────────────────── // TEST 2 — Grid // ───────────────────────────────────────────────────────────── void drawGridTest() { tft.fillScreen(BLACK); int w = tft.width(), h = tft.height(); // Vertical lines every 40px for (int x = 0; x <= w; x += 40) tft.drawFastVLine(x, 0, h, GREEN); // Horizontal lines every 40px for (int y = 0; y <= h; y += 40) tft.drawFastHLine(0, y, w, GREEN); // Centre cross tft.drawFastVLine(w / 2, 0, h, RED); tft.drawFastHLine(0, h / 2, w, RED); tft.setTextColor(WHITE); tft.setTextSize(2); tft.setCursor(4, 4); tft.print("GRID TEST"); Serial.println("Grid drawn"); } // ───────────────────────────────────────────────────────────── // TEST 3 — Text // ───────────────────────────────────────────────────────────── void textTest() { tft.fillScreen(BLACK); tft.setTextColor(WHITE); tft.setTextSize(1); tft.setCursor(0, 0); tft.println("Size 1 — Hello World!"); tft.setTextSize(2); tft.setCursor(0, 16); tft.println("Size 2 — Hello!"); tft.setTextSize(3); tft.setCursor(0, 40); tft.println("Size 3"); tft.setTextSize(4); tft.setCursor(0, 72); tft.println("Size 4"); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor(0, 120); tft.println("RED text"); tft.setTextColor(GREEN); tft.setCursor(0, 145); tft.println("GREEN text"); tft.setTextColor(BLUE); tft.setCursor(0, 170); tft.println("BLUE text"); tft.setTextColor(YELLOW); tft.setCursor(0, 195); tft.println("YELLOW text"); Serial.println("Text test complete"); } // ───────────────────────────────────────────────────────────── // TEST 4 — Shapes // ───────────────────────────────────────────────────────────── void drawShapesTest() { tft.fillScreen(BLACK); int cx = tft.width() / 2, cy = tft.height() / 2; // Filled + outlined circles tft.fillCircle(cx - 100, cy, 50, BLUE); tft.drawCircle(cx - 100, cy, 50, WHITE); // Filled + outlined rectangle tft.fillRect(cx - 30, cy - 50, 80, 100, GREEN); tft.drawRect(cx - 30, cy - 50, 80, 100, WHITE); // Triangle tft.fillTriangle(cx + 80, cy - 50, cx + 150, cy + 50, cx + 10, cy + 50, RED); tft.drawTriangle(cx + 80, cy - 50, cx + 150, cy + 50, cx + 10, cy + 50, WHITE); // Rounded rect tft.fillRoundRect(10, 10, 120, 60, 12, MAGENTA); tft.drawRoundRect(10, 10, 120, 60, 12, WHITE); tft.setTextColor(WHITE); tft.setTextSize(2); tft.setCursor(10, tft.height() - 30); tft.print("SHAPES TEST"); Serial.println("Shapes drawn"); } // ───────────────────────────────────────────────────────────── // TEST 5 — Gradient bar // ───────────────────────────────────────────────────────────── void gradientTest() { tft.fillScreen(BLACK); int w = tft.width(), h = tft.height(); int barH = 40; tft.setTextColor(WHITE); tft.setTextSize(2); tft.setCursor(10, 10); tft.print("GRADIENT TEST"); // Red gradient bar for (int x = 0; x < w; x++) { uint16_t r = map(x, 0, w, 0, 31); tft.drawFastVLine(x, 60, barH, tft.color565(r * 8, 0, 0)); } // Green gradient bar for (int x = 0; x < w; x++) { uint16_t g = map(x, 0, w, 0, 63); tft.drawFastVLine(x, 110, barH, tft.color565(0, g * 4, 0)); } // Blue gradient bar for (int x = 0; x < w; x++) { uint16_t b = map(x, 0, w, 0, 31); tft.drawFastVLine(x, 160, barH, tft.color565(0, 0, b * 8)); } // Full RGB sweep for (int x = 0; x < w; x++) { uint16_t hue = map(x, 0, w, 0, 359); // Simple HSV→RGB (S=1, V=1) uint8_t hi = hue / 60; float f = (hue / 60.0) - hi; uint8_t q = 255 * (1 - f); uint8_t t8 = 255 * f; uint8_t r, g, b; switch(hi % 6) { case 0: r=255; g=t8; b=0; break; case 1: r=q; g=255; b=0; break; case 2: r=0; g=255; b=t8; break; case 3: r=0; g=q; b=255; break; case 4: r=t8; g=0; b=255; break; default:r=255; g=0; b=q; break; } tft.drawFastVLine(x, 220, barH, tft.color565(r, g, b)); } Serial.println("Gradient test complete"); } // ───────────────────────────────────────────────────────────── // TEST 6 — TrailNav project splash screen // ───────────────────────────────────────────────────────────── void trailNavSplash() { tft.fillScreen(BLACK); int w = tft.width(), h = tft.height(); // Header bar tft.fillRect(0, 0, w, 50, 0x0460); // Dark teal // Title tft.setTextColor(WHITE); tft.setTextSize(3); tft.setCursor(20, 12); tft.print("TrailNav"); // Compass icon (simple lines) int ox = w - 60, oy = 25; tft.drawCircle(ox, oy, 20, CYAN); tft.fillTriangle(ox, oy - 18, ox - 6, oy + 8, ox + 6, oy + 8, RED); // N arrow (red) tft.fillTriangle(ox, oy + 18, ox - 6, oy - 8, ox + 6, oy - 8, WHITE); // S arrow (white) // Status info tft.setTextSize(2); tft.setTextColor(GREEN); tft.setCursor(10, 70); tft.print("GPS: Searching..."); tft.setTextColor(YELLOW); tft.setCursor(10, 98); tft.print("ALT: --- m"); tft.setTextColor(CYAN); tft.setCursor(10, 126); tft.print("SPD: 0.0 km/h"); tft.setTextColor(WHITE); tft.setCursor(10, 154); tft.print("HDG: ---°"); // Divider tft.drawFastHLine(0, 180, w, 0x0460); // Footer tft.setTextColor(0x8410); // Dark grey tft.setTextSize(1); tft.setCursor(10, h - 20); tft.print("ESP32 Heltec WiFi | TFT 3.5\" | OK"); // Screen OK badge tft.fillRoundRect(w - 80, h - 35, 70, 25, 6, GREEN); tft.setTextColor(BLACK); tft.setTextSize(2); tft.setCursor(w - 75, h - 31); tft.print("OK"); Serial.println("TrailNav splash rendered — screen PASS"); }