LITTLE WEB SERVER TF CARD CODE
Generic Web Server + FTP + TF Card Storage
KEY FEATURES
HARDWARE COMPONENTS
PIN DEFINITIONS
DISPLAY PREVIEW
ARDUINO SKETCH
/* ESP32-S3 Web Server + FTP + SD Card Generic Template - Customize for your project Hardware: - ESP32-S3 Super Mini - GC9A01 Round Display (240x240) - Micro SD TF Card Reader */ #include <WiFi.h> #include <WebServer.h> #include <SD.h> #include <SPI.h> #include <SimpleFTPServer.h> #include <Arduino_GFX_Library.h> #include <time.h> // ============== CONFIGURATION ============== // WiFi credentials - CHANGE THESE const char* ssid = "YOUR_WIFI_SSID"; const char* password = "YOUR_WIFI_PASSWORD"; // FTP credentials - CHANGE THESE const char* ftp_user = "admin"; const char* ftp_pass = "admin"; // NTP Time settings const char* ntpServer = "pool.ntp.org"; const long gmtOffset_sec = -21600; // CST = UTC-6 (adjust for your timezone) const int daylightOffset_sec = 3600; // DST offset // ============== PIN DEFINITIONS ============== // Display pins (separate SPI bus from SD card) #define TFT_SCK 12 #define TFT_MOSI 11 #define TFT_CS 8 #define TFT_DC 9 #define TFT_RST 10 #define TFT_BL 7 // SD Card pins (separate SPI bus - do NOT share with display) #define SD_SCK 4 #define SD_MISO 3 #define SD_MOSI 2 #define SD_CS 1 // ============== COLORS (RGB565) ============== #define BLACK 0x0000 #define WHITE 0xFFFF #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define GREEN 0x07E0 #define RED 0xF800 #define DARKGRAY 0x4208 #define DARKCYAN 0x0345 #define DARKMAGENTA 0x4008 #define ORANGE 0xFC00 // ============== OBJECTS ============== Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, -1); Arduino_GFX *gfx = new Arduino_GC9A01(bus, TFT_RST, 0, true); SPIClass sdSPI = SPIClass(HSPI); WebServer server(80); FtpServer ftpSrv; // ============== VARIABLES ============== unsigned long lastDisplayUpdate = 0; unsigned long lastTickerUpdate = 0; unsigned long requestCount = 0; int animFrame = 0; bool sdCardMounted = false; // ============== CONTENT TYPES ============== String getContentType(String filename) { if (filename.endsWith(".html")) return "text/html"; else if (filename.endsWith(".css")) return "text/css"; else if (filename.endsWith(".js")) return "application/javascript"; else if (filename.endsWith(".png")) return "image/png"; else if (filename.endsWith(".jpg")) return "image/jpeg"; else if (filename.endsWith(".gif")) return "image/gif"; else if (filename.endsWith(".ico")) return "image/x-icon"; else if (filename.endsWith(".json")) return "application/json"; return "text/plain"; } // ============== FILE HANDLER ============== bool handleFileRead(String path) { Serial.println("Request: " + path); requestCount++; if (path.endsWith("/")) path += "index.html"; if (!sdCardMounted) { server.send(503, "text/plain", "SD Card not mounted"); return false; } String contentType = getContentType(path); if (SD.exists(path)) { File file = SD.open(path, FILE_READ); if (file) { server.streamFile(file, contentType); file.close(); return true; } } return false; } // ============== DISPLAY HELPER FUNCTIONS ============== void drawCornerBrackets(int x, int y, int w, int h, uint16_t color) { int len = 8; gfx->drawFastHLine(x, y, len, color); gfx->drawFastVLine(x, y, len, color); gfx->drawFastHLine(x + w - len, y, len, color); gfx->drawFastVLine(x + w - 1, y, len, color); gfx->drawFastHLine(x, y + h - 1, len, color); gfx->drawFastVLine(x, y + h - len, len, color); gfx->drawFastHLine(x + w - len, y + h - 1, len, color); gfx->drawFastVLine(x + w - 1, y + h - len, len, color); } void drawTickMarks(int cx, int cy, int r, uint16_t color) { for (int i = 0; i < 12; i++) { float angle = i * 30 * PI / 180; int x1 = cx + cos(angle) * (r - 5); int y1 = cy + sin(angle) * (r - 5); int x2 = cx + cos(angle) * r; int y2 = cy + sin(angle) * r; gfx->drawLine(x1, y1, x2, y2, color); } } void drawSignalBars(int x, int y, int rssi) { int bars = 0; if (rssi > -50) bars = 4; else if (rssi > -60) bars = 3; else if (rssi > -70) bars = 2; else if (rssi > -80) bars = 1; for (int i = 0; i < 4; i++) { int barHeight = 4 + (i * 3); uint16_t color = (i < bars) ? CYAN : DARKGRAY; gfx->fillRect(x + (i * 6), y + (12 - barHeight), 4, barHeight, color); } } // 7-Segment patterns const uint8_t segPatterns[] = { 0b1111110, 0b0110000, 0b1101101, 0b1111001, 0b0110011, 0b1011011, 0b1011111, 0b1110000, 0b1111111, 0b1111011 }; void draw7Seg(int x, int y, int digit, int w, int h, int t, uint16_t color, uint16_t dimColor) { if (digit < 0 || digit > 9) return; uint8_t seg = segPatterns[digit]; int hh = h / 2; gfx->fillRect(x + t, y, w - t*2, t, (seg & 0b1000000) ? color : dimColor); gfx->fillRect(x + w - t, y + t, t, hh - t, (seg & 0b0100000) ? color : dimColor); gfx->fillRect(x + w - t, y + hh, t, hh - t, (seg & 0b0010000) ? color : dimColor); gfx->fillRect(x + t, y + h - t, w - t*2, t, (seg & 0b0001000) ? color : dimColor); gfx->fillRect(x, y + hh, t, hh - t, (seg & 0b0000100) ? color : dimColor); gfx->fillRect(x, y + t, t, hh - t, (seg & 0b0000010) ? color : dimColor); gfx->fillRect(x + t, y + hh - t/2, w - t*2, t, (seg & 0b0000001) ? color : dimColor); } void drawColon(int x, int y, int h, int t, uint16_t color) { int dotSize = t + 1; gfx->fillRect(x, y + h/3 - dotSize/2, dotSize, dotSize, color); gfx->fillRect(x, y + 2*h/3 - dotSize/2, dotSize, dotSize, color); } void draw7SegTime(int x, int y, int hours, int mins, uint16_t color, uint16_t dimColor) { int digitW = 16, digitH = 24, thick = 3, gap = 3, colonW = 6; draw7Seg(x, y, hours / 10, digitW, digitH, thick, color, dimColor); draw7Seg(x + digitW + gap, y, hours % 10, digitW, digitH, thick, color, dimColor); int colonX = x + 2*(digitW + gap) + gap; drawColon(colonX, y, digitH, thick, color); int minX = colonX + colonW + gap; draw7Seg(minX, y, mins / 10, digitW, digitH, thick, color, dimColor); draw7Seg(minX + digitW + gap, y, mins % 10, digitW, digitH, thick, color, dimColor); } void drawSecondsTick(int secs) { int cx = 120, cy = 120, r = 112; float angle = (secs * 6 - 90) * PI / 180; gfx->drawLine(cx + cos(angle)*(r-4), cy + sin(angle)*(r-4), cx + cos(angle)*(r+2), cy + sin(angle)*(r+2), WHITE); int prevSec = (secs == 0) ? 59 : secs - 1; float prevAngle = (prevSec * 6 - 90) * PI / 180; gfx->drawLine(cx + cos(prevAngle)*(r-4), cy + sin(prevAngle)*(r-4), cx + cos(prevAngle)*(r+2), cy + sin(prevAngle)*(r+2), DARKGRAY); } void drawChevrons(int frame) { int y = 198; uint16_t color = (frame % 2 == 0) ? MAGENTA : DARKMAGENTA; uint16_t color2 = (frame % 2 == 0) ? DARKMAGENTA : MAGENTA; gfx->setTextSize(1); gfx->setTextColor(color); gfx->setCursor(60, y); gfx->print(">>"); gfx->setTextColor(color2); gfx->setCursor(72, y); gfx->print(">>"); gfx->setTextColor(DARKGRAY); gfx->setCursor(90, y); gfx->print("WEBSRV 1.0T"); gfx->setTextColor(color2); gfx->setCursor(156, y); gfx->print("<<"); gfx->setTextColor(color); gfx->setCursor(168, y); gfx->print("<<"); } void drawTicker(int frame) { const char* msg = " /// SYSTEM NOMINAL /// WEB SERVER ONLINE /// TF CARD ACTIVE /// ESP32-S3 /// "; int msgLen = strlen(msg); int charW = 6; int totalW = msgLen * charW; int scrollX = 240 - (millis() / 20) % (totalW + 240); gfx->fillRect(35, 183, 170, 12, BLACK); gfx->drawFastHLine(35, 183, 170, DARKGRAY); gfx->drawFastHLine(35, 194, 170, DARKGRAY); gfx->setTextColor(CYAN); gfx->setTextSize(1); for (int i = 0; i < msgLen; i++) { int charX = scrollX + (i * charW); if (charX >= 35 && charX < 200) { gfx->setCursor(charX, 185); gfx->print(msg[i]); } } } // ============== MAIN DISPLAY FUNCTIONS ============== void drawBootScreen() { gfx->fillScreen(BLACK); gfx->drawCircle(120, 120, 119, DARKCYAN); gfx->drawCircle(120, 120, 118, CYAN); gfx->drawCircle(120, 120, 117, DARKCYAN); gfx->drawCircle(120, 120, 110, DARKGRAY); drawTickMarks(120, 120, 115, MAGENTA); gfx->drawCircle(120, 120, 85, DARKMAGENTA); gfx->drawCircle(120, 120, 60, DARKCYAN); gfx->setTextColor(DARKCYAN); gfx->setTextSize(2); gfx->setCursor(59, 49); gfx->print("WEB SERVER"); gfx->setTextColor(CYAN); gfx->setCursor(60, 50); gfx->print("WEB SERVER"); gfx->drawFastHLine(40, 72, 160, DARKGRAY); gfx->drawFastHLine(50, 74, 140, MAGENTA); gfx->drawFastHLine(40, 76, 160, DARKGRAY); gfx->setTextColor(MAGENTA); gfx->setTextSize(1); gfx->setCursor(48, 85); gfx->print("[ ESP32-S3 NODE ]"); drawCornerBrackets(35, 105, 170, 40, CYAN); gfx->setTextColor(YELLOW); gfx->setCursor(52, 120); gfx->print(">> INITIALIZING..."); } void drawStatusScreen() { gfx->fillScreen(BLACK); gfx->drawCircle(120, 120, 119, DARKCYAN); gfx->drawCircle(120, 120, 118, CYAN); gfx->drawCircle(120, 120, 117, DARKCYAN); drawTickMarks(120, 120, 115, MAGENTA); gfx->drawCircle(120, 120, 108, DARKGRAY); gfx->fillRect(30, 22, 180, 22, DARKMAGENTA); gfx->drawRect(30, 22, 180, 22, MAGENTA); gfx->setTextColor(WHITE); gfx->setTextSize(2); gfx->setCursor(60, 26); gfx->print("WEB SERVER"); gfx->drawFastHLine(35, 48, 170, CYAN); gfx->fillCircle(52, 58, 4, GREEN); gfx->drawCircle(52, 58, 6, GREEN); gfx->setTextColor(GREEN); gfx->setTextSize(1); gfx->setCursor(62, 54); gfx->print("ON"); if (sdCardMounted) { gfx->fillCircle(90, 58, 4, YELLOW); gfx->setTextColor(YELLOW); } else { gfx->fillCircle(90, 58, 4, RED); gfx->setTextColor(RED); } gfx->setCursor(100, 54); gfx->print("SD"); gfx->setTextColor(DARKGRAY); gfx->setCursor(140, 54); gfx->print("SIG"); drawCornerBrackets(28, 68, 184, 110, CYAN); gfx->drawFastHLine(35, 69, 170, DARKGRAY); gfx->drawFastHLine(35, 177, 170, DARKGRAY); } void updateDisplay() { animFrame++; gfx->fillRect(30, 70, 180, 106, BLACK); gfx->drawFastHLine(35, 69, 170, DARKGRAY); gfx->drawFastHLine(35, 177, 170, DARKGRAY); int rssi = WiFi.RSSI(); drawSignalBars(165, 52, rssi); int scanY = 70 + (animFrame % 20) * 5; if (scanY < 175) gfx->drawFastHLine(32, scanY, 176, DARKCYAN); gfx->setTextColor(DARKGRAY); gfx->setTextSize(1); gfx->setCursor(90, 76); gfx->print("NET.ADDR"); String ip = WiFi.localIP().toString(); int ipWidth = ip.length() * 6; gfx->setTextColor(CYAN); gfx->setCursor((240 - ipWidth) / 2, 88); gfx->print(ip); gfx->drawFastHLine(40, 100, 160, DARKGRAY); unsigned long uptime = millis() / 1000; int hours = uptime / 3600; int mins = (uptime % 3600) / 60; int secs = uptime % 60; gfx->setTextColor(DARKGRAY); gfx->setCursor(69, 106); gfx->print("RUNTIME"); gfx->setCursor(135, 106); gfx->print("REQ"); char uptimeStr[12]; sprintf(uptimeStr, "%02d:%02d:%02d", hours, mins, secs); gfx->setTextColor(YELLOW); gfx->setCursor(63, 118); gfx->print(uptimeStr); gfx->setTextColor(GREEN); gfx->setCursor(135, 118); gfx->print(requestCount); gfx->drawFastHLine(40, 130, 160, DARKGRAY); struct tm timeinfo; if (getLocalTime(&timeinfo)) { int hour12 = timeinfo.tm_hour % 12; if (hour12 == 0) hour12 = 12; drawSecondsTick(timeinfo.tm_sec); draw7SegTime(78, 138, hour12, timeinfo.tm_min, CYAN, BLACK); gfx->setTextSize(1); gfx->setTextColor(GREEN); gfx->setCursor(168, 156); gfx->print(timeinfo.tm_hour >= 12 ? "PM" : "AM"); char dateStr[12]; strftime(dateStr, sizeof(dateStr), "%m/%d/%Y", &timeinfo); gfx->setTextColor(YELLOW); gfx->setCursor(90, 168); gfx->print(dateStr); } else { gfx->setTextColor(DARKGRAY); gfx->setCursor(60, 150); gfx->print("SYNCING TIME..."); } drawTicker(animFrame); drawChevrons(animFrame); } // ============== SETUP ============== void setup() { Serial.begin(115200); delay(1000); Serial.println("\n=== ESP32 SD Card Web Server ===\n"); // Initialize SD card FIRST (before display) Serial.println("Initializing SD card..."); pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); sdSPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS); if (!SD.begin(SD_CS, sdSPI, 4000000)) { // 4MHz for compatibility Serial.println("SD Card mount failed!"); sdCardMounted = false; } else { sdCardMounted = true; Serial.println("SD Card OK!"); uint64_t cardSize = SD.cardSize() / (1024 * 1024); Serial.printf("SD Card Size: %lluMB\n", cardSize); } // Initialize display pinMode(TFT_BL, OUTPUT); digitalWrite(TFT_BL, HIGH); gfx->begin(); gfx->setRotation(0); drawBootScreen(); // Show SD status on display if (!sdCardMounted) { gfx->setTextColor(RED); gfx->setCursor(52, 140); gfx->print("SD CARD ERROR!"); delay(2000); } // Connect to WiFi Serial.printf("Connecting to %s", ssid); WiFi.begin(ssid, password); int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < 30) { delay(500); Serial.print("."); attempts++; } if (WiFi.status() == WL_CONNECTED) { Serial.println(" Connected!"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // Configure NTP time configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); // Start FTP server ftpSrv.begin(ftp_user, ftp_pass); Serial.println("FTP server started"); Serial.printf("FTP User: %s\n", ftp_user); drawStatusScreen(); updateDisplay(); } else { Serial.println(" Failed!"); WiFi.softAP("ESP32-Server", "password123"); Serial.print("AP IP: "); Serial.println(WiFi.softAPIP()); } // Setup web server server.onNotFound([]() { if (!handleFileRead(server.uri())) { server.send(404, "text/plain", "404: Not Found"); } }); server.begin(); Serial.println("Web server started on port 80"); } // ============== LOOP ============== void loop() { server.handleClient(); ftpSrv.handleFTP(); if (millis() - lastDisplayUpdate > 1000) { lastDisplayUpdate = millis(); if (WiFi.status() == WL_CONNECTED) { updateDisplay(); } } if (millis() - lastTickerUpdate > 50) { lastTickerUpdate = millis(); if (WiFi.status() == WL_CONNECTED) { drawTicker(0); } } }
WEB PAGE TEMPLATE
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ESP32 Server</title> <link rel="stylesheet" href="style.css"> </head> <body> <div class="scanlines"></div> <div class="container"> <header> <div class="logo-frame"> <span class="bracket">[</span> <h1>ESP32<span class="accent">SERVER</span></h1> <span class="bracket">]</span> </div> <p class="status">// SYSTEM ONLINE</p> </header> <main> <section class="card"> <h2>SYSTEM STATUS</h2> <div class="status-grid"> <div class="status-item"> <span class="label">WiFi</span> <span class="value online">CONNECTED</span> </div> <div class="status-item"> <span class="label">SD Card</span> <span class="value online">MOUNTED</span> </div> <div class="status-item"> <span class="label">FTP</span> <span class="value online">ACTIVE</span> </div> <div class="status-item"> <span class="label">Web Server</span> <span class="value online">RUNNING</span> </div> </div> </section> <section class="card"> <h2>ABOUT</h2> <p>ESP32-S3 Web Server with SD Card storage and FTP access.</p> <p>Upload files via FTP or swap the SD card to update content.</p> </section> </main> <footer> <p>© 2025 // ESP32 SERVER</p> </footer> </div> </body> </html>
STYLESHEET TEMPLATE
/* Cyberpunk Theme - ESP32 Server */ :root { --bg-dark: #0a0a0f; --bg-card: #12121a; --neon-cyan: #00ffff; --neon-magenta: #ff00ff; --neon-yellow: #ffff00; --text-primary: #e0e0e0; --text-dim: #666; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Courier New', monospace; background: var(--bg-dark); color: var(--text-primary); min-height: 100vh; overflow-x: hidden; } /* Scanline Effect */ .scanlines { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; background: repeating-linear-gradient( 0deg, rgba(0,0,0,0.1) 0px, rgba(0,0,0,0.1) 1px, transparent 1px, transparent 2px ); z-index: 1000; } .container { max-width: 800px; margin: 0 auto; padding: 20px; } /* Header */ header { text-align: center; padding: 40px 0; border-bottom: 1px solid #333; } .logo-frame { display: inline-flex; align-items: center; gap: 10px; } .bracket { font-size: 3rem; color: var(--neon-magenta); text-shadow: 0 0 20px var(--neon-magenta); } h1 { font-size: 2.5rem; color: var(--neon-cyan); text-shadow: 0 0 30px var(--neon-cyan); letter-spacing: 8px; } .accent { color: var(--neon-magenta); text-shadow: 0 0 30px var(--neon-magenta); } .status { color: var(--text-dim); margin-top: 10px; letter-spacing: 3px; } /* Cards */ .card { background: var(--bg-card); border: 1px solid #333; border-radius: 10px; padding: 25px; margin: 20px 0; } .card h2 { color: var(--neon-magenta); font-size: 1rem; letter-spacing: 3px; margin-bottom: 20px; border-bottom: 1px solid var(--neon-magenta); padding-bottom: 10px; } .card p { color: var(--text-dim); line-height: 1.6; margin-bottom: 10px; } /* Status Grid */ .status-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; } .status-item { display: flex; justify-content: space-between; padding: 10px; background: rgba(0,255,255,0.05); border: 1px solid #333; border-radius: 5px; } .label { color: var(--text-dim); } .value.online { color: #00ff00; text-shadow: 0 0 10px #00ff00; } /* Footer */ footer { text-align: center; padding: 30px 0; border-top: 1px solid #333; color: var(--text-dim); font-size: 0.8rem; } /* Responsive */ @media (max-width: 600px) { .status-grid { grid-template-columns: 1fr; } h1 { font-size: 1.5rem; } }
SETUP INSTRUCTIONS
- WiFi: Replace
YOUR_WIFI_SSIDandYOUR_WIFI_PASSWORDwith your credentials. - FTP: Default credentials are
admin/admin. Change these for security. - Library: Install
SimpleFTPServerandArduino_GFX_Libraryvia Arduino Library Manager. - SimpleFTPServer Config: Edit
FtpServerKey.hin the library folder:- Set
STORAGE_TYPEtoSTORAGE_SD - Set
STORAGE_SD_FORCE_DISABLE_SEPORATECLASStotrue
- Set
- FTP Client: Use FileZilla or similar. Connect to the ESP32's IP on port 21.
- Board: Select "ESP32S3 Dev Module" in Arduino IDE.
- Serial Monitor: 115200 baud to see IP address and debug info.
SD CARD FILE STRUCTURE
Format your SD card as FAT32 and organize the website files as follows:
- Format SD card as FAT32 (use SD Card Formatter tool for best results)
- Copy
index.htmlandstyle.cssto the root of the SD card - Create an
imagesfolder for any graphics (optional) - Insert SD card into the module before powering on
SD Card folder structure:
SD Card (FAT32)/
├── index.html // Main webpage
├── style.css // Stylesheet
├── script.js // JavaScript (optional)
└── images/ // Image folder (optional)
├── logo.png
└── background.jpg
Tip: Use FTP to upload files wirelessly after initial setup. Connect to the ESP32's IP address on port 21.
DISPLAY ROTATION
To rotate the display, add gfx->setRotation(n); in setup() after gfx->begin();
gfx->setRotation(0); // 0° - Default orientation
gfx->setRotation(1); // 90° - Rotate clockwise
gfx->setRotation(2); // 180° - Upside down
gfx->setRotation(3); // 270° - Rotate counter-clockwise
Note: This rotates the entire display output. Use this if your display is mounted upside down or at an angle.
ARDUINO PROJECT SETUP
- Create Project Folder: Create a folder named
LittleWebServer_SDin your Arduino sketches directory - Main Sketch: Save the code as
LittleWebServer_SD.ino- filename MUST match folder name - Single File Project: This project uses only one .ino file
- SD Card: Format as FAT32, copy your website files to root
LittleWebServer_SD/ └── LittleWebServer_SD.ino // Main sketch SD Card (FAT32): ├── index.html // Your website ├── style.css // Stylesheets └── images/ // Any assets
COMPONENTS NEEDED
| ESP32-S3 Super Mini | Main microcontroller | AliExpress |
| GC9A01 Round Display | 240x240 1.28" TFT | Amazon |
| MicroSD Card Module | SPI TF card reader | Amazon |
| MicroSD Card | FAT32 formatted (≤32GB) | Amazon |
| Dupont Wires | For connections | Amazon |
WIRING DIAGRAM
| GC9A01 Display | ESP32-S3 |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SCL (SCK) | GPIO 12 |
| SDA (MOSI) | GPIO 11 |
| RES (RST) | GPIO 10 |
| DC | GPIO 9 |
| CS | GPIO 8 |
| BLK | GPIO 7 |
| SD Card Module | ESP32-S3 |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SCK | GPIO 4 |
| MISO | GPIO 3 |
| MOSI | GPIO 2 |
| CS | GPIO 1 |
Note: Display and SD card use separate SPI buses.
REQUIRED LIBRARIES
Install via Arduino Library Manager:
| Arduino_GFX_Library | by moononournation - Display driver |
| SimpleFTPServer | For wireless file upload (optional) |
ARDUINO IDE 3.x BOARD SETTINGS
| Board | ESP32S3 Dev Module |
| USB CDC On Boot | Enabled |
| Flash Size | 4MB (32Mb) |
| Partition Scheme | Default 4MB with spiffs |
| Upload Speed | 921600 |
ESP32 Board URL:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
TROUBLESHOOTING
- Upload fails: Hold BOOT button while clicking Upload.
- Display is blank: Check display wiring. Verify 3.3V power.
- SD card not detected: Format as FAT32. Try 4MHz in SD.begin().
- Files not found: Put files in SD root, not subfolders.
- WiFi won't connect: Check SSID/password. 2.4GHz only.
- Web page not loading: Check Serial for IP. Clear browser cache.
BUILD CHECKLIST
- □ Install Arduino IDE 3.x and ESP32 boards
- □ Install Arduino_GFX_Library
- □ Create folder:
LittleWebServer_SD/ - □ Copy sketch as
LittleWebServer_SD.ino - □ Edit code: Set WiFi credentials
- □ Format SD card as FAT32
- □ Copy website files to SD card
- □ Wire display and SD card module
- □ Insert SD card
- □ Upload sketch (hold BOOT if needed)
- □ Check Serial Monitor for IP
- □ Open IP in browser - Done!