/** * Olimex ESP32-C6-EVB — Board Functional Test * ================================================= * Flash this sketch BEFORE deploying the main firmware. * It tests every hardware subsystem and reports PASS/FAIL * on the Serial Monitor AND on a simple web page. * * Board settings (Arduino IDE): * Board : ESP32C6 Dev Module * USB CDC On Boot : Enabled ← REQUIRED * Flash Size : 4MB * Upload Speed : 921600 * * How to read results: * 1. Open Serial Monitor at 115200 baud after upload. * 2. Press RESET on the board — full report prints once. * 3. Connect a phone/PC to the same WiFi and open: * http://192.168.0.181/test (or whatever IP prints) * * Relay self-test: the test pulses each relay 200 ms ON then OFF. * You will see/hear the relays click twice each. * * NFC self-test: tries all baud rates (115200 / 9600 / 57600) * on both pin orientations. Module must be wired on UEXT1. */ #include #include #include #include // ── WiFi credentials ───────────────────────────────────────────────────────── const char* SSID = "BUON GUSTO PARTER"; const char* PASSWORD = "arleta13"; IPAddress STATIC_IP(192, 168, 0, 181); IPAddress GATEWAY (192, 168, 0, 1); IPAddress SUBNET (255, 255, 255, 0); // ── Pin map ─────────────────────────────────────────────────────────────────── const int LED_PIN = 8; const int BUT_PIN = 9; const int RELAY_PIN[] = {10, 11, 22, 23}; // Relay 1-4 const int INPUT_PIN[] = {1, 2, 3, 15}; // Digital Input 1-4 const int NFC_RX = 5; // UEXT1 pin 4 const int NFC_TX = 4; // UEXT1 pin 3 // ── NFC objects ─────────────────────────────────────────────────────────────── HardwareSerial nfcSerial(1); PN532_HSU pn532hsu(nfcSerial); PN532 nfc(pn532hsu); // ── Web server ──────────────────────────────────────────────────────────────── WebServer server(80); // ── Test result storage ─────────────────────────────────────────────────────── struct TestResult { const char* name; bool passed; String detail; }; static const int MAX_TESTS = 20; TestResult results[MAX_TESTS]; int result_count = 0; int pass_count = 0; int fail_count = 0; // ── Helper: record a result ─────────────────────────────────────────────────── void record(const char* name, bool ok, String detail = "") { if (result_count < MAX_TESTS) { results[result_count++] = {name, ok, detail}; } if (ok) pass_count++; else fail_count++; Serial.printf(" [%s] %s%s\n", ok ? "PASS" : "FAIL", name, detail.length() ? (" — " + detail).c_str() : ""); } // ───────────────────────────────────────────────────────────────────────────── // TEST FUNCTIONS // ───────────────────────────────────────────────────────────────────────────── void testGPIO() { Serial.println("\n--- GPIO Test ---"); // ── LED ────────────────────────────────────────────────────────────────── pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // LED on (active-low) delay(300); digitalWrite(LED_PIN, HIGH); // LED off delay(100); // We cannot read back an output pin reliably, so just record as attempted. record("LED on/off", true, "GPIO8 — verify LED blinked"); // ── Button ──────────────────────────────────────────────────────────────── pinMode(BUT_PIN, INPUT_PULLUP); int btn = digitalRead(BUT_PIN); // Button is pull-up; HIGH = not pressed. Either state is valid at test time. record("Button readable", true, String("GPIO9 = ") + (btn ? "HIGH (not pressed)" : "LOW (pressed)")); // ── Digital Inputs ──────────────────────────────────────────────────────── const char* in_names[] = {"Input1 (GPIO1)", "Input2 (GPIO2)", "Input3 (GPIO3)", "Input4 (GPIO15)"}; for (int i = 0; i < 4; i++) { pinMode(INPUT_PIN[i], INPUT_PULLUP); int v = digitalRead(INPUT_PIN[i]); record(in_names[i], true, String("= ") + (v ? "HIGH (open)" : "LOW (active)")); } // ── Relays ──────────────────────────────────────────────────────────────── const char* rel_names[] = {"Relay1 (GPIO10)", "Relay2 (GPIO11)", "Relay3 (GPIO22)", "Relay4 (GPIO23)"}; for (int i = 0; i < 4; i++) { pinMode(RELAY_PIN[i], OUTPUT); digitalWrite(RELAY_PIN[i], LOW); } delay(100); for (int i = 0; i < 4; i++) { // Pulse ON for 200 ms — you should hear/see relay click digitalWrite(RELAY_PIN[i], HIGH); delay(200); digitalWrite(RELAY_PIN[i], LOW); delay(100); record(rel_names[i], true, "pulsed 200 ms — listen for click"); } } // ── WiFi ───────────────────────────────────────────────────────────────────── void testWiFi() { Serial.println("\n--- WiFi Test ---"); WiFi.disconnect(true); delay(200); WiFi.mode(WIFI_STA); WiFi.config(STATIC_IP, GATEWAY, SUBNET); bool connected = false; for (int pass = 1; pass <= 3 && !connected; pass++) { Serial.printf(" Connecting (attempt %d/3)...", pass); WiFi.begin(SSID, PASSWORD); for (int t = 0; t < 40 && WiFi.status() != WL_CONNECTED; t++) { delay(500); Serial.print("."); } Serial.println(); connected = (WiFi.status() == WL_CONNECTED); if (!connected && pass < 3) { WiFi.disconnect(true); delay(500); WiFi.mode(WIFI_STA); WiFi.config(STATIC_IP, GATEWAY, SUBNET); } } if (connected) { record("WiFi connect", true, WiFi.localIP().toString() + " RSSI=" + String(WiFi.RSSI()) + " dBm"); } else { record("WiFi connect", false, "status=" + String(WiFi.status()) + " — check SSID/password"); } } // ── NFC ────────────────────────────────────────────────────────────────────── void testNFC() { Serial.println("\n--- NFC (PN532 HSU) Test ---"); const long BAUDS[] = {115200, 9600, 57600, 38400}; const int NPINS[2][2]= {{NFC_RX, NFC_TX}, {NFC_TX, NFC_RX}}; uint32_t ver = 0; long found_baud = 0; int found_rx = NFC_RX, found_tx = NFC_TX; for (int pi = 0; pi < 2 && !ver; pi++) { for (int bi = 0; bi < 4 && !ver; bi++) { int rx = NPINS[pi][0], tx = NPINS[pi][1]; Serial.printf(" baud=%-7ld RX=GPIO%d TX=GPIO%d ... ", BAUDS[bi], rx, tx); nfcSerial.begin(BAUDS[bi], SERIAL_8N1, rx, tx); delay(500); nfc.begin(); ver = nfc.getFirmwareVersion(); if (ver) { found_baud = BAUDS[bi]; found_rx = rx; found_tx = tx; Serial.println("FOUND"); } else { Serial.println("no response"); delay(100); } } } if (ver) { nfc.SAMConfig(); char detail[80]; snprintf(detail, sizeof(detail), "PN5%02X FW=%d.%d baud=%ld RX=GPIO%d TX=GPIO%d", (ver >> 24) & 0xFF, (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, found_baud, found_rx, found_tx); record("NFC PN532 init", true, detail); } else { record("NFC PN532 init", false, "not detected — check DIP switches (both=0) & UEXT1 wiring"); } } // ───────────────────────────────────────────────────────────────────────────── // WEB PAGE GET /test // ───────────────────────────────────────────────────────────────────────────── void handleTestPage() { String h = "Board Test"; h += ""; h += ""; h += "

Olimex ESP32-C6-EVB — Functional Test

"; h += "
MAC: " + WiFi.macAddress() + "   IP: " + WiFi.localIP().toString() + "   Uptime: " + String(millis() / 1000) + "s
"; h += ""; for (int i = 0; i < result_count; i++) { bool ok = results[i].passed; h += ""; h += ""; h += ""; h += ""; } h += "
#TestResultDetail
" + String(i + 1) + "" + String(results[i].name) + "" + String(ok ? "PASS" : "FAIL") + "" + results[i].detail + "
"; bool all_ok = (fail_count == 0); h += "
"; h += String(pass_count) + " PASSED   /   " + String(fail_count) + " FAILED   out of " + String(result_count) + " tests"; if (all_ok) h += "   ✓ Board OK"; else h += "   ✗ Check failures above"; h += "
"; server.send(200, "text/html", h); } void handleTestJSON() { String j = "{\"pass\":" + String(pass_count) + ",\"fail\":" + String(fail_count) + ",\"total\":" + String(result_count) + ",\"board_ok\":" + String(fail_count == 0 ? "true" : "false") + ",\"mac\":\"" + WiFi.macAddress() + "\"" + ",\"ip\":\"" + WiFi.localIP().toString() + "\"" + ",\"uptime_s\":" + String(millis() / 1000) + ",\"tests\":["; for (int i = 0; i < result_count; i++) { if (i) j += ","; j += "{\"name\":\"" + String(results[i].name) + "\"" + ",\"pass\":" + String(results[i].passed ? "true" : "false") + ",\"detail\":\"" + results[i].detail + "\"}"; } j += "]}"; server.send(200, "application/json", j); } // ───────────────────────────────────────────────────────────────────────────── // setup / loop // ───────────────────────────────────────────────────────────────────────────── void setup() { Serial.begin(115200); delay(2000); for (int i = 0; i < 10 && !Serial; i++) delay(500); Serial.println("\n\n╔══════════════════════════════════════╗"); Serial.println("║ Olimex ESP32-C6-EVB Board Test ║"); Serial.println("╚══════════════════════════════════════╝"); testGPIO(); testWiFi(); testNFC(); // ── Start web server ────────────────────────────────────────────────────── server.on("/", HTTP_GET, handleTestPage); server.on("/test", HTTP_GET, handleTestPage); server.on("/test.json", HTTP_GET, handleTestJSON); server.onNotFound([](){ server.send(404, "text/plain", "use /test or /test.json"); }); server.begin(); // ── Final summary on serial ─────────────────────────────────────────────── Serial.println("\n╔══════════════════════════════════════╗"); Serial.printf( "║ PASSED: %2d FAILED: %2d TOTAL: %2d ║\n", pass_count, fail_count, result_count); Serial.println(fail_count == 0 ? "║ ✓ ALL TESTS PASSED — board is OK ║" : "║ ✗ FAILURES DETECTED — see above ║"); Serial.println("╚══════════════════════════════════════╝"); if (WiFi.status() == WL_CONNECTED) { Serial.printf("\nOpen browser: http://%s/test\n", WiFi.localIP().toString().c_str()); Serial.printf("Or fetch JSON: http://%s/test.json\n\n", WiFi.localIP().toString().c_str()); } } void loop() { server.handleClient(); }